Skip to content

Instantly share code, notes, and snippets.

@liudongmiao
Last active March 19, 2020 17:43
Show Gist options
  • Save liudongmiao/537d90fbc6485900f059dbab8542dfb5 to your computer and use it in GitHub Desktop.
Save liudongmiao/537d90fbc6485900f059dbab8542dfb5 to your computer and use it in GitHub Desktop.
SimpleApkV2
// package me.piebridge;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by thom on 2018/5/31.
*/
public class SimpleApkV2 {
private SimpleApkV2() {
}
private static abstract class ApkV2Parser {
private final String sourceDir;
ApkV2Parser(String sourceDir) {
this.sourceDir = sourceDir;
parse();
}
private void parse() {
final byte[] apkSignV2 = {'A', 'P', 'K', ' ', 'S', 'i', 'g', ' ',
'B', 'l', 'o', 'c', 'k', ' ', '4', '2'};
try (
RandomAccessFile apk = new RandomAccessFile(sourceDir, "r")
) {
ByteBuffer buffer = ByteBuffer.allocate(0x10);
buffer.order(ByteOrder.LITTLE_ENDIAN);
apk.seek(apk.length() - 0x6);
apk.readFully(buffer.array(), 0x0, 0x6);
int offset = buffer.getInt();
if (buffer.getShort() != 0) {
return;
}
apk.seek(offset - 0x10);
apk.readFully(buffer.array(), 0x0, 0x10);
if (!Arrays.equals(apkSignV2, buffer.array())) {
return;
}
// Read and compare size fields
apk.seek(offset - 0x18);
apk.readFully(buffer.array(), 0x0, 0x8);
buffer.rewind();
int size = (int) buffer.getLong();
ByteBuffer block = ByteBuffer.allocate(size + 0x8);
block.order(ByteOrder.LITTLE_ENDIAN);
apk.seek(offset - block.capacity());
apk.readFully(block.array(), 0x0, block.capacity());
if (size != block.getLong()) {
return;
}
while (block.remaining() > 0x18) {
size = (int) block.getLong();
int id = block.getInt();
int newPosition = block.position() + size - 0x4;
if (handle(id, size, block)) {
return;
}
block.position(newPosition);
}
} catch (IOException ignore) {
// do nothing
}
}
protected abstract boolean handle(int id, int size, ByteBuffer block);
}
public static void main(String[] args) {
new DummyParser(args[0]);
}
private static class DummyParser extends ApkV2Parser {
private static final char[] HEX = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
DummyParser(String sourceDir) {
super(sourceDir);
}
@Override
protected boolean handle(int id, int size, ByteBuffer block) {
if (id == 0x7109871a) {
System.out.println("id: " + Integer.toHexString(id) + "(sign v2), size: " + size);
} else if (id == 0xf05368c0) {
System.out.println("id: " + Integer.toHexString(id) + "(sign v3), size: " + size);
} else if (id == 0x42726577) {
System.out.println("id: " + Integer.toHexString(id) + "(padding), size: " + size);
} else if (id == 0x71777777) {
byte[] bytes = new byte[size - 0x4];
block.get(bytes, 0, bytes.length);
String channel = new String(bytes);
System.out.println("id: " + Integer.toHexString(id) + "(channel), " + channel);
} else {
System.out.println("id: " + Integer.toHexString(id) + "(unknown), size: " + size);
byte[] bytes = new byte[size - 0x4];
block.get(bytes, 0, bytes.length);
System.out.println(" " + hex(bytes));
}
return false;
}
private static String hex(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
sb.append(HEX[(b >> 4) & 0xf]);
sb.append(HEX[b & 0xf]);
}
return sb.toString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment