Skip to content

Instantly share code, notes, and snippets.

@vvb2060
Forked from liudongmiao/SimpleApkV2.java
Last active February 8, 2024 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vvb2060/8436e7f516eae2c58472b61709749241 to your computer and use it in GitHub Desktop.
Save vvb2060/8436e7f516eae2c58472b61709749241 to your computer and use it in GitHub Desktop.
SimpleApkV2
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
public class SimpleApkV2 {
private SimpleApkV2() {
}
private static abstract class ApkV2Parser {
private final Path sourceDir;
ApkV2Parser(String sourceDir) {
this.sourceDir = Paths.get(sourceDir);
parse();
}
private void parse() {
final byte[] apkSignV2 = {'A', 'P', 'K', ' ', 'S', 'i', 'g', ' ',
'B', 'l', 'o', 'c', 'k', ' ', '4', '2'};
try (var channel = FileChannel.open(sourceDir, StandardOpenOption.READ)) {
int apkSize = (int) channel.size();
var apk = channel.map(FileChannel.MapMode.READ_ONLY, 0, apkSize);
apk.order(ByteOrder.LITTLE_ENDIAN);
int offset;
for (int i = 0; ; i++) {
if (apk.getShort(apkSize - 0x2 - i) == i) {
if (apk.getInt(apkSize - 0x16 - i) == 0x6054b50) {
offset = apk.getInt(apkSize - 0x6 - i);
break;
}
}
if (i == 0xffff) {
System.out.println("invalid APK format");
return;
}
}
var buffer = new byte[0x10];
apk.position(offset - 0x10);
apk.get(buffer);
if (!Arrays.equals(apkSignV2, buffer)) {
System.out.println("APK Sig Block 42");
return;
}
int blockSize = (int) apk.getLong(offset - 0x18);
apk.position(offset - blockSize - 0x8);
if (blockSize != apk.getLong()) {
System.out.println("invalid APK sig block");
return;
}
while (apk.remaining() > apkSize - offset + 0x18) {
int size = (int) apk.getLong();
int id = apk.getInt();
int newPosition = apk.position() + size - 0x4;
handle(id, size, apk);
apk.position(newPosition);
}
if (apk.remaining() != apkSize - offset + 0x18) {
System.out.println("have more data");
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
protected abstract void handle(int id, int size, ByteBuffer block);
}
public static void main(String[] args) {
new DummyParser(args[0]);
}
private static class DummyParser extends ApkV2Parser {
DummyParser(String sourceDir) {
super(sourceDir);
}
@Override
protected void handle(int id, int size, ByteBuffer block) {
switch (id) {
default ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(unknown), size: " + size);
case 0x7109871a ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(signature scheme v2), size: " + size);
case 0xf05368c0 ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(signature scheme v3), size: " + size);
case 0x1b93ad61 ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(signature scheme v3.1), size: " + size);
case 0x2b09189e ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(source stamp V1), size: " + size);
case 0x6dff800d ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(source stamp V2), size: " + size);
case 0x2146444e ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(play store security metadata), " + size);
case 0x504b4453 ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(dependencies metadata), size: " + size);
case 0x42726577 ->
System.out.println("id: 0x" + Integer.toHexString(id) + "(padding), size: " + size);
case 0x71777777 -> {
byte[] bytes = new byte[size - 0x4];
block.get(bytes, 0, bytes.length);
String channel = new String(bytes);
System.out.println("id: 0x" + Integer.toHexString(id) + "(meituan channel), " + channel);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment