com.googlecode.dex2jar.tools.ExtractOdexFromCoredumpCmd Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
fakeradnroid gradle builder
package com.googlecode.dex2jar.tools;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
@BaseCmd.Syntax(cmd = "extract-odex-from-coredump", syntax = "", desc = "Extract odex from dalvik memery core dump")
public class ExtractOdexFromCoredumpCmd extends BaseCmd {
public static void main(String... args) {
new ExtractOdexFromCoredumpCmd().doMain(args);
}
@Override
protected void doCommandLine() throws Exception {
if (remainingArgs.length < 1) {
throw new HelpException(" is required.");
}
Path core = new File(remainingArgs[0]).toPath();
try (SeekableByteChannel channel = FileChannel.open(core, StandardOpenOption.READ);) {
List possibleOdexs = findPossibleOdexLocation(channel);
extractDex(channel, possibleOdexs, core.getFileName().toString());
}
}
private static void extractDex(SeekableByteChannel channel, List possibleOdexs, String namePrefix) throws IOException {
int dexIndex = 0;
ByteBuffer odexHead = ByteBuffer.allocate(0x28).order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer copyBuff = ByteBuffer.allocate(512 * 1024).order(ByteOrder.LITTLE_ENDIAN);
final int buffSize = 0x28 + 0x70;
ByteBuffer head = ByteBuffer.allocate(buffSize).order(ByteOrder.LITTLE_ENDIAN); // odex+dex head
for (long pos : possibleOdexs) {
System.err.println(String.format(">> Check for %08x", pos));
channel.position(pos);
head.position(0);
int c = channel.read(head);
head.position(0);
if (c == buffSize) {
int version = head.getInt(4);
if (version == 0x00363330 || version == 0x00353330) { // odexVersion
int dexOffset = head.getInt(8);
int dexLength = head.getInt(12);
int depsOffset = head.getInt(16);
int depsLength = head.getInt(20);
int optOffset = head.getInt(24);
int optLength = head.getInt(28);
int flags = head.getInt(32);
int checksum = head.getInt(36);
if (dexOffset != 0x28) {
System.err.println(String.format(">>> dex offset is not 0x28"));
} else {
int dexMagic = head.getInt(dexOffset + 0);
int dexVersion = head.getInt(dexOffset + 4);
if (dexMagic != 0x0a786564 || !(dexVersion == 0x00363330 || dexVersion == 0x00353330)) {
System.err.println(String.format(">>> dex magic is not dex.036 or dex.035: 0x%08x 0x%08x", dexMagic, dexVersion));
} else {
int fileSize = head.getInt(dexOffset + 32);
if (fileSize != dexLength) {
System.err.println(String.format(">>> dex file size is same with dexLength in odex %d vs %d", fileSize, dexLength));
} else {
int endian = head.getInt(dexOffset + 40);
if (endian != 0x12345678) {
System.err.println(String.format(">>> dex endian is not 0x12345678"));
} else {
// find new dex
Path nFile = new File(String.format("%s-%02d.odex", namePrefix, dexIndex++)).toPath();
System.out.println(String.format(">>>> extract 0x%08x to %s", pos, nFile));
try (SeekableByteChannel channel2 = Files.newByteChannel(nFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE);) {
odexHead.rewind();
odexHead.putInt(0x0a796564);// dey
odexHead.putInt(0x00363330);// 036
odexHead.putInt(0x28);
odexHead.putInt(fileSize);
int nDepsOffset = 0x28 + fileSize;
int nDepsPadding = 0;
if (nDepsOffset % 8 != 0) {
nDepsPadding = 8 - (nDepsOffset % 8);
nDepsOffset += nDepsPadding;
}
odexHead.putInt(nDepsOffset);
odexHead.putInt(depsLength);
int nOptOffset = nDepsOffset + depsLength;
int nOptPadding = 0;
if (nOptOffset % 8 != 0) {
nOptPadding = 8 - (nOptOffset % 8);
nOptOffset += nOptPadding;
}
odexHead.putInt(nOptOffset);
odexHead.putInt(optLength);
odexHead.putInt(flags);
odexHead.putInt(checksum);
odexHead.position(0);
channel2.write(odexHead);
// copy dex
channel.position(pos + dexOffset);
copy(channel, channel2, copyBuff, fileSize);
if (nDepsPadding != 0) {
channel2.write(ByteBuffer.allocate(nDepsPadding));
}
// copy deps
channel.position(pos + depsOffset);
copy(channel, channel2, copyBuff, depsLength);
if (nOptPadding != 0) {
channel2.write(ByteBuffer.allocate(nOptPadding));
}
// copy opts
channel.position(pos + optOffset);
copy(channel, channel2, copyBuff, optLength);
}
}
}
}
}
}
}
}
}
private static void copy(SeekableByteChannel channel, SeekableByteChannel channel2, ByteBuffer copyBuff, int fileSize) throws IOException {
int remain = fileSize;
while (remain > 0) {
copyBuff.rewind();
copyBuff.limit(Math.min(remain, copyBuff.capacity()));
int read = channel.read(copyBuff);
copyBuff.position(0);
channel2.write(copyBuff);
remain -= read;
}
}
private static List findPossibleOdexLocation(SeekableByteChannel channel) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(1024 * 512).order(ByteOrder.LITTLE_ENDIAN);
IntBuffer intBuffer = buffer.asIntBuffer();
List possibleOdexs = new ArrayList<>();
while (true) {
long position = channel.position();
//System.out.printf("load @%x\n", position);
int count = channel.read(buffer);
if (count <= 0) {
break;
}
int s = count / 4;
for (int i = 0; i < s; i++) {
int u4 = intBuffer.get(i);
if (u4 == 0x0a796564) {// dey
if (i + 1 < s) {
int v4 = intBuffer.get(i + 1);
if (v4 == 0x00363330 || v4 == 0x00353330) {
possibleOdexs.add(position + 4 * i);
System.err.println(String.format("> Possible %08x | %08x %08x", position + i * 4, u4, v4));
}
} else {
possibleOdexs.add(position + 4 * i);
System.err.println(String.format("> Possible %08x | %08x", position + i * 4, u4));
}
}
}
buffer.position(0);
intBuffer.position(0);
}
return possibleOdexs;
}
}