解析 dex 文件结构 - 索引区和数据区(一) - Strings & Types
前言
在 解析 dex 文件结构 - DexHeader 中我们知道 Table 部分就是索引结构区,他们是是作为指向 Data 区数据的结构索引而存在的。
数据区是 dex 会用到的全部数据。
StringIds 和 StringData
StringIds 存放的是字符串的 id,也就是数据区中各个 StringData 的文件偏移。
StringIds 的大小和文件偏移在 DexHeader 和 map_list 中都有指定。
结构
StringIds 以4字节对齐,即总大小为 4 * stringIdsSize .
|
|
按照 StringIds 指示的偏移来到数据区对应的位置,StringData 采用的格式为:
字符串长度 : uleb128 格式,不包括字符串尾部的 00 。
字符串内容:MUTF-8(经过修改的UTF-8),以 00 结尾 .
手工查找
某 dex 文件的 StringIds 部分:
stringIdsSize:0x5c
stringIdsOff:0x0070
0x0070 ~ 0x01df
|
|
以第一个字符串为例,文件偏移为 bc 04 00 00
:
根据 LEB128 的解码格式可知:
字符串的长度为 0x31(有效位:011 0001) = 49 个字节。(“/data/data/com.zyh.lightingbackup/.lib/libexec.so”)
以此类推:
序数 | 文件偏移 | 字符串长度 | 字符串 |
---|---|---|---|
0x00 | 0x04bc | 0x31 | /data/data/com.zyh.lightingbackup/.lib/libexec.so |
0x01 | 0x04ef | 0x35 | /data/data/com.zyh.lightingbackup/.lib/libexecmain.so |
… | … | … | … |
0x04 | 0x0538 | 0x07 | CPU_ABI |
0x05 | 0x0541 | 0x01 | I |
0x06 | 0x0544 | 0x02 | IL |
0x07 | 0x0548 | 0x01 | J |
0x08 | 0x054b | 0x02 | JL |
0x09 | 0x054f | 0x01 | L |
0x0a | 0x0552 | 0x02 | LL |
0x0b | 0x0556 | 0x19 | Landroid/app/Application; |
0x0c | 0x0571 | 0x19 | Landroid/content/Context; |
… | … | … | … |
0x5b | 0x09f0 | 0x02 | ze |
0x5c | 0x09f4 | 0x02 | zf |
写程序解析字符串
|
|
TypeIds
TypeIds 存放的是 stringIds 内的索引,也就是说 StringData 里面的一些字符串是类型描述符。
TypeIds 的大小和文件偏移在 DexHeader 和 map_list 中都有指定。
这里的类型描述符可以代表 dex 文件中的任何类型,包括基本类型,类类型,数组类型和空类型。
结构
TypeIds 以4字节对齐,即总大小为 4 * typeIdsSize .
|
|
通过 descriptorIdx
可以得到相应类型描述符
的字符串的 StringId,从而找到相应的字符串。
手动查找
某 dex 文件的 TypeIds 部分:
TypeIdsSize:0x19
TypeIdsOff:0x01e0
0x01e0 ~ 0x0244
|
|
以第一个索引值 0x05 为例,在 StringIds 中找到第 0x05 个 StringId,也就是 0x0070(stringIdsOff) + 0x05 * 4 = 0x0084,
该地址值为 0x0541,0x0541 处的字符串为 “I”,int 类型。类型对照参见下表 - Dalvik 字节码类型。
语法 | 含义 |
---|---|
V | void; 只用于返回值 |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
Lfully/qualified/Name; | 类名:fully.qualified.Name |
[descriptor | 数组描述符,可以表示多维数组如 [[[descriptor,但最多只能有255个维度 |
以此类推:
序数 | descriptorIdx | StringId | Type | 真正类型 |
---|---|---|---|---|
0x00 | 0x05 | 0x0084 | I | int |
0x01 | 0x07 | 0x008c | J | long |
0x02 | 0x0b | 0x009c | Landroid/app/Application; | android.app.Application |
0x03 | 0x0c | 0x00a0 | Landroid/content/Context; | android.content.Context |
0x04 | 0x0d | 0x00a4 | Landroid/os/Build; | android.os.Build |
0x05 | 0x0e | 0x00a8 | Lcom/shell/NativeApplication; | com.shell.NativeApplication |
0x06 | 0x0f | 0x00ac | Lcom/shell/SuperApplication; | com.shell.SuperApplication |
0x07 | 0x10 | 0x00b0 | Ldalvik/annotation/Throws; | dalvik.annotation.Throws |
0x08 | 0x11 | 0x00b4 | Ljava/io/File; | java.io.File |
0x09 | 0x12 | 0x00b8 | Ljava/io/FileInputStream; | java.io.FileInputStream |
0x0a | 0x13 | 0x00bc | Ljava/io/FileOutputStream; | java.io.FileOutputStream |
0x0b | 0x14 | 0x00c0 | Ljava/io/IOException; | java.io.IOException |
0x0c | 0x15 | 0x00c4 | Ljava/io/InputStream; | java.io.InputStream |
0x0d | 0x16 | 0x00c8 | Ljava/lang/Exception; | java.lang.Exception |
0x0e | 0x17 | 0x00cc | Ljava/lang/Object; | java.lang.Object |
0x0f | 0x18 | 0x00d0 | Ljava/lang/String; | java.lang.String |
0x10 | 0x19 | 0x00d4 | Ljava/lang/System; | java.lang.System |
0x11 | 0x1a | 0x00d8 | Ljava/util/zip/CRC32; | java.util.zip.CRC32 |
0x12 | 0x1b | 0x00dc | Ljava/util/zip/CheckedInputStream; | java.util.zip.CheckedInputStream |
0x13 | 0x1c | 0x00e0 | Ljava/util/zip/Checksum; | java.util.zip.Checksum |
0x14 | 0x1d | 0x00e4 | Ljava/util/zip/ZipEntry; | java.util.zip.ZipEntry |
0x15 | 0x1e | 0x00e8 | Ljava/util/zip/ZipFile; | java.util.zip.ZipFile |
0x16 | 0x21 | 0x00f4 | V | void |
0x17 | 0x26 | 0x0108 | Z | boolean |
0x18 | 0x29 | 0x0114 | [B] | byte[] |
写程序解析 TypeIds
|
|