OAT文件简介
OAT文件
是在Android4.4中引入的。OAT是优化过的、用于ART虚拟机执行的DEX文件,类似于Dalvik的ODEX文件。
生成OAT文件
系统在安装APK时,会调用dex2oat
自动生成OAT文件。用户也可以手动执行dex2oat命令,为指定的DEX文件生成OAT文件。
在执行dex2oat
命令的时候,使用--dex-file
参数指定传入的DEX路径(若有多个DEX文件,可以多次指定该参数),然后通过--oat-file
参数指定OAT文件的输出路径(注意输出路径的写的权限)
例如
unzip app-release.apk classes.dex
mv classes.dex crackme.dex
adb push crackme.dex /data/local/tmp
adb shell dex2oat --dex-file=/data/local/tmp/crackme.dex --runtime-arg -Xms64m --runtime-arg -Xmx64m --oat-file=/data/local/tmp/crackme.oat
adb pull /data/local/tmp/crackme.oat .
OAT文件格式
OAT文件格式完全融入Android所特有的ELF格式。
识别OAT文件格式的一个有效方法是查看该ELF文件的符号表。
使用Android NDK包中的readelf
工具查看oat
的符号表
arm-linux-androideabi-readelf.exe -s demo.oat
一个OAT文件必须包含oatdata
,oatexec
,oatlastword
三个符号
Symbol table '.dynsym' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00001000 0xb4000 OBJECT GLOBAL DEFAULT 4 oatdata
2: 000b5000 0x75fe8 OBJECT GLOBAL DEFAULT 5 oatexec
3: 0012afe4 4 OBJECT GLOBAL DEFAULT 5 oatlastword
oatdata
符号指向的地址是OAT所在ELF的.rodata
段,这里存放的是OAT文件头OATHeader
、OAT的DEX文件头OATDexFile
、原始的DEX文件DexFile
、OAT的DEX类OatClass
等信息。oatexec
符号指向的地址是OAT所在ELF的.text
段,这里存放的是编译生成的Native指令代码。oatlastword
符号指向的地址是OAT文件结束处在ELF中的文件偏移,通过它可以确定OAT文件的内容在哪里结束

将OAT文件转换成DEX文件
由于OAT文件包含完整的DEX文件,取出OAT文件的方法非常简单;定位OAT文件中的DexFile结构体,将它的完整数据导出。
我们可以使用Android系统中的oatdump
命令,使用该命令的--output
参数可以将OAT中的所有DEX文件导出、放到指定的目录下。
oatdump --oat-file=demo.oat --output=demo.dex
- 也可以使用010 Editor的脚本实现oat到dex的转化。
将下面脚本保存为Oat2Dex.1sc
,然后执行即可。
LittleEndian();
int i;
char filename[512];
filename = GetFileName();
int filenum = GetFileNum();
TFindResults r = FindAll("dex\n035");
//Printf("%d\n", r.count);
int pos, sz;
char dexname[512];
char ext[128];
for(i=0; i < r.count; i++) {
pos = r.start[i];
sz = ReadInt(pos + 0x20);
Printf( "Found DEX at: 0x%lx, size: 0x%lx\n", pos, sz);
// Copy data to clipboard and write to a new file
SetSelection(pos, sz);
CopyToClipboard();
FileNew( "Hex" );
PasteFromClipboard();
SPrintf(ext, ".0x%lx.dex", pos);
Memset(dexname, 0, 512);
Strcat(dexname, filename);
Strcat(dexname, ext);
Printf("dexname: %s\n", dexname);
// Save the new file to disk
if(FileSave(dexname) < 0)
{
Printf("An error occured writing file '%s' of size 0x%lx.\n", dexname, sz);
return -1;
}
FileClose();
FileSelect(filenum);
Printf("Write %s ok.\n", filename);
// Make sure a big block of data is not still on the clipboard
SetSelection(0, 1);
CopyToClipboard();
SetSelection(0, 0);
}
Printf("Done.\n");
Comments | 1 条评论