2015年11月17日
解析 dex 文件结构 - DexHeader
dex 简介
dex 文件是 dalvik 虚拟机的可执行文件。
dex 文件结构
该结构位于系统源码 dalvik\libdex\DexFile.h
中,描述的是 dex 文件被映射到内存中的结构。
|
|
基本的文件结构只需关注:1234567891011struct DexFile{ DexHeader Header; DexStringId StringIds[stringIdsSize]; DexTypeId TypeIds[typeIdsSize]; DexFieldId FieldIds[fieldIdsSize]; DexMethodId MethodIds[methodIdsSize]; DexProtoId ProtoIds[protoIdsSize]; DexClassDef ClassDefs[classDefsSize]; DexData Data[]; DexLink LinkData;};
大体结构图
大致可以将 dex 文件分为三个部分:DexHeader 、Table 是索引结构区 、data 部分是数据区。
程序使用到的数据都在 data section 内, Tables 是指向 data section 中具体数据结构的索引。
DexHeader 结构
头部记录了整个文件的索引。
|
|
其中:
field | description |
---|---|
magic | dex文件标识,值必须为常量 DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x35 0x00 } = “dex\n035\0” |
checkSum | 对除 magic 和 checkSum 外的剩余文件计算 adler32 校验值,目的是检测文件是否损坏 |
signature | 对除 magic、checkSum 和 signature 外的剩余文件计算 SHA-1 校验值,用来确定文件的唯一性 |
fileSize | 以字节为单位,整个文件(包括头部)的大小 |
headerSize | 头部大小,0x70 字节,已经考虑到兼容性 |
endianTag | 两种字节序取值: uint ENDIAN_CONSTANT = 0x12345678 ; uint REVERSE_ENDIAN_CONSTANT = 0x78563412 |
linkSize | 链接段的大小,如果没有使用静态链接,值为0 |
linkOff | 链接段的文件偏移,指向链接数据段内,如果 linkSize 为 0,则为 0 |
mapOff | map item 的文件偏移,指向数据段内,数据结构为 mapList ,如果没有 map,值为 0 |
stringIdsSize | 字符串 id 的个数 |
stringIdsOff | 字符串 id 清单的文件偏移,指向 stringIds 的起始地址,如果 stringIdsSize 为 0,值为0 |
typeIdsSize | 类型标识符的个数 |
typeIdsOff | 类型标识符清单的文件偏移,指向 typeIds 的起始地址,如果 typeIdsSize 为 0,值为 0 (这就很奇怪了哟) |
protoIdsSize | 原型标识符的个数 |
protoIdsOff | 原型标识符清单的文件偏移,指向 protoIds 的起始地址,如果 protoIdsSize 为 0,值为 0 (这就很奇怪了哟) |
fieldIdsSize | 字段标识符的个数 |
fieldIdsOff | 字段标识符清单的文件偏移,指向 fieldIds 的起始地址,如果 fieldIdsSize 为 0,值为 0 |
methodIdsSize | 方法标识符的个数 |
methodIdsOff | 方法标识符清单的文件偏移,指向 methodIds 的起始地址,如果 methodIdsSize 为 0,值为 0 |
classDefsSize | 类的个数 |
classDefsOff | 类清单的文件偏移,指向 classDefs 的起始地址,如果 classDefsSize 为 0,值为 0 (这就很奇怪了哟) |
dataSize | 数据段的大小,以字节为单位,并且是 sizeof(uint) 的偶数倍 |
dataOff | 数据段的文件偏移 |
手工查找
更方便的方式是使用 010 Editor,下载其官网上可解析 dex 文件的脚本文件,可高亮相应的二进制。
linux 下可以使用 hexdump
查看某文件的二进制数据 -> hexdump -C classes.dex
option | description |
---|---|
-b | 将每个字节显示为8进制 |
-c | 将每个字节显示为ASCII字符 |
-C | 每个字节显示为16进制和相应的ASCII字符 |
-d | 每两个字节显示为10进制 |
-o | 每两个字节显示为8进制 |
-x | 每两个字节显示为16进制 |
某 dex 文件的头部:
|
|
binary | field |
---|---|
64 65 78 0a 30 33 35 00 | magic |
3b ba fe c3 | checksum |
83 7e aa be 09 97 71 1e 17 96 9f e9 0c bd 01 60 b4 2a 1a c9 | signature |
c4 10 00 00 | fileSize |
70 00 00 00 | headerSize |
78 56 34 12 | endianTag |
00 00 00 00 | linkSize |
00 00 00 00 | linkOff |
00 10 00 00 | mapOff |
5c 00 00 00 | stringIdsSize |
70 00 00 00 | stringIdsOff |
19 00 00 00 | typeIdsSize |
e0 01 00 00 | typeIdsOff |
12 00 00 00 | protoIdsSize |
44 02 00 00 | protoIdsOff |
01 00 00 00 | fieldIdsSize |
1c 03 00 00 | fieldIdsOff |
2b 00 00 00 | methodIdsSize |
24 03 00 00 | methodIdsOff |
02 00 00 00 | classDefsSize |
7c 04 00 00 | classDefsOff |
08 0c 00 00 | dataSize |
bc 04 00 00 | dataOff |
写程序解析 DexHeader
|
|
Reference
来源 :
http://kiya.studio
著作权归作者所有,转载请联系作者获得授权。