ODEX
在android5.0之前,主要使用Dalvik,Dalvik对
apk的dex文件进行一定程度的优化,解析dex文件并生成ODEX文件
比dex多了以下内容
DexOptHeader:ODEX文件头,描述了ODEX文件的基本信息
Dependences:依赖库列表,描述了ODEX文件加载时可能使用的依赖库
classlookups:优化数据块的类索引列表信息
registerMaps:优化数据块的寄存器图信息
struct DexOptHeader
{
u1 magic[8];//固定为dex\n036
u4 dexOffset;//dex在ODEX中的偏移量
u4 dexLength;//dex文件的长度
u4 depsOffset; //依赖库的文件偏移
u4 depsLength;//依赖库的大小
u4 optOffset;//优化数据块的偏移
u4 optLength;//优化数据块的大小
u4 flags; //验证标志位
u4 checksum;//校验和信息
}
struct Dependences{
u4 modWhen; //优化前dex时间戳
u4 crc; //优化前dex检验
u4 DALVIK_VM_BUILD;//dalvik虚拟机版本号
struct{
u4 len; //name字符串的长度
u1 name[len];//依赖库的名称
KSHA1DigestLen signature;//sha-1散列值
}table[numDeps];
}
优化数据块有如下三种类型
enum {
kDexChunkClassLookuo = 0x434c4b50,
kDexChunkRegisterMaps = 0x524d4150,
kDexChunkEnd = 0x41454e44,
}
kDexChunkEnd表示优化数据块结束
kDexChunkClassLookup表示ckasslookup数据
kDexChunkRegisterMaps是RegisterMaps数据
将ODEX转成DEX
odex先反编译成smali,再编译成dex,叫做"deodex"
工具:baksmali smali
脚本命名deodex
rm -rf ./outdex
rm -rf ./outdex.dex
baksmali -a 19 -x "$1" -d 目录 -o ./outdex
smali ./outdex -o outdex.dex
echo done
OAT
OAT是优化过的,用于ART虚拟机执行的dex文件?(odex 5.0前) 5.0后
和elf差不多
struct OatHeader {
uint8_t magic[4];//固定为oat\n
uint8_t version[4];//oat文件格式版本
uint32_t adler32_checksum;//oat的adler32校验和
InstructionSet instruction_set;//oat使用的指令集(枚举)
uint32_t instruction_set_features_bitmap;
uint32_t dex_file_count;//dex文件的个数
uint32_t executable_offset;//oatexec与oatdata的偏移量
uint32_t interpreter_to_interpreter_bidge_offset;
uint32_t interpreter_to_compiled_code_bridge_offset;
uint32_t jni_dlsym_lookup_offset;
uint32_t quick_generic_jni_trampoline_offset;
uin32_t quick_imt_conflict_trampoline_offset;
uin32_t quick_resolution_trampoline_offset;
uin32_t quick_to_interpreter_bridge_offset;
int32_t image_patch_delta;
uint32_t image_file_location_oat_checksum;
uint32_t image_file_location_oat_data_begin;
uint32_t key_value_store_size;
uint8_t key_value_store[0];
};
header中有dex_file_count就有几个oatdexfile?(不是一个都包涵了吗)
struct OatDexFile{
uint32 dex_file_name_size;//大小
char dex_filename_data[dex_filename_size];//dex文件的完整路径
uint32 dex_file_checksum;
uint8_t* dex_file_pointer;
uint32_t* oat_class_offsets;
}
将OAT文件转化DEX
只有oat时用010editor脚本
脚本如下
LittleEndian();
int i;
char filename[512];
filename = GetFileName();
int filenum = GetFileNum();
TFindResults r = FindAll("dex\n035");//搜索所有dex
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);
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);
if(FileSave(dexname) < 0)
{
Print("An error occured writing file '%s' of size 0x%lx.\n",dexname,sz);
return -1;
}
FileClose();
FileSelect(filenum);//这个干嘛?
Printf("Wrie %s ok\n",filename);
SelSelection(0,1);
CopyToClipboard();
SetSelection(0,0);
}
Printf("Done.\n");