所有内容仅供学习
这一节简单看一下dex文件的结构和smali语法。具体格式请参考谷歌官网
dex 文件结构如下图:
dexHeader定义如下:
1 /* 2 * Direct-mapped "header_item" struct. 3 */ 4 struct DexHeader { 5 u1 magic[8]; /* includes version number */ 6 u4 checksum; /* adler32 checksum */ 7 u1 signature[kSHA1DigestLen]; /* SHA-1 hash */ 8 u4 fileSize; /* length of entire file */ 9 u4 headerSize; /* offset to start of next section */ 10 u4 endianTag; 11 u4 linkSize; 12 u4 linkOff; 13 u4 mapOff; 14 u4 stringIdsSize; 15 u4 stringIdsOff; 16 u4 typeIdsSize; 17 u4 typeIdsOff; 18 u4 protoIdsSize; 19 u4 protoIdsOff; 20 u4 fieldIdsSize; 21 u4 fieldIdsOff; 22 u4 methodIdsSize; 23 u4 methodIdsOff; 24 u4 classDefsSize; 25 u4 classDefsOff; 26 u4 dataSize; 27 u4 dataOff; 28 };
为了便于理解,我们自己搞个简单的例子来学习一下。
1 public class Hell{ 2 private static final String HELL = "bupt"; 3 4 public void sayNothing(String str1){ 5 6 } 7 8 public static void main(String[] args){ 9 10 } 11 }
javac Hell.java
dx --dex --output=Hell.dex Hell.class
dx工具将class文件转为dex文件,打开Hell.dex
magic ---- "64 65 78 0a 30 33 35 00", 代表"dex\n035\0"
checksum --- "8e 53 bd 27", 采用alder32算法
signature --- "35 32 b2 ……d1 50 e8", 采用SHA-1算法
fileSize --- "c0 02 00 00", 0x02c0,十进制为2*256 + 12*16 = 704个字节
headerSize --- "70 00 00 00", Dex头部大小固定,为112个字节
endianTag --- "78 56 34 12", 大小端标志,默认为小端
linkSize --- "00 00 00 00", 表示是静态连接
linkOff --- "00 00 00 00", linkSize 为0, linkOff也为0
mapOff --- "14 02 00 00", Dalvik虚拟机解析dex文件,最终将其映射成DexMapList数据结构。mapOff指明了DexMapList的偏移位置
stringIdsSize --- "0c 00 00 00", 字符串个数,12个
stringIdsOff --- "70 00 00 00", DexHeader之后紧跟string_ids
……
我们以string_ids为例,找到这12个字符串。0x70处地址为"6e 01 00 00",第一个string数据在0x16e处:
06 3c 69 6e 69 74 3e 00
第一个string长度为6,使用python转为ASCII为"<init>"
binascii.a2b_hex('3c696e69743e')
第二个string长度为4,"HELL", 第三个"Hell.java",其他的类似。
==============
我们查看当当读书的classes.dex文件,截图如下:
“64 65 78 0a 30 33 35 00”,代表“dex\n035\0”,紧接着4个字节“03 e9 ae 3d”代表利用Adler32算法算出的校验和,从0x0~0x10f共20个字节是采用SHA-1计算出的签名。
“4c 11 31 00” 4个字节代表整个classes.dex文件的大小,利用windows自带的计算器计算一下16进制“31114c”转为10进制为“3215692”字节,右键-》属性,我们发现大小就是3.06MB。
接下来4字节为DexHeader大小0x70(112)个字节,目前是固定的。“78 56 34 12”代表大小端标志,后面8个字节都为0表明为静态链接。
“ac 10 31 00”为map_off值
“7e 58 00 00”为字符串个数,转为10进制为22654个。
接下来又是0x70,dexheader的大小,说明“string_ids”从0x70处开始,即“fa 73 25 00 ……”,根据这两个值,算出string_ids从0x70开始,在(0x70 + 0x587e * 4)= 0x16267处终止??
由“fa 73 25 00”知,第一个String Data 在0x2573fa处,貌似不对啊,0x2573fa处的值为00 啊?????是我算错了,还是混淆后就这样? 实在搞不懂。
附上下载android dalvik源码方法:
git clone http://android.googlesource.com/platform/dalvik