- 对本书的赞誉
- 前言
- 基础篇
- 第 1 章 Android 中锁屏密码加密算法分析
- 第 2 章 Android 中 NDK 开发
- 第 3 章 Android 中开发与逆向常用命令总结
- 第 4 章 so 文件格式解析
- 第 5 章 AndroidManifest.xml 文件格式解析
- 第 6 章 resource.arsc 文件格式解析
- 第 7 章 dex 文件格式解析
- 防护篇
- 第 8 章 Android 应用安全防护的基本策略
- 第 9 章 Android 中常用权限分析
- 第 10 章 Android 中的 run-as 命令
- 第 11 章 Android 中的 allowBackup 属性
- 第 12 章 Android 中的签名机制
- 第 13 章 Android 应用加固原理
- 第 14 章 Android 中的 so 加固原理
- 工具篇
- 第 15 章 Android 逆向分析基础
- 第 16 章 反编译神器 apktool 和 Jadx
- 第 17 章 Hook 神器 Xposed
- 第 18 章 脱壳神器 ZjDroid
- 第 19 章 Native 层 Hook 神器 Cydia Substrate
- 操作篇
- 第 20 章 静态方式逆向应用
- 第 21 章 动态调试 smali 源码
- 第 22 章 IDA 工具调试 so 源码
- 第 23 章 逆向加固应用
- 第 24 章 逆向应用经典案例分析
- 第 25 章 Android 中常见漏洞分析
- 第 26 章 文件加密病毒 Wannacry 样本分析
6.2 数据结构定义
资源文件的项目如图 6-4 所示。
图 6-4 资源文件的数据结构
可见到这里定义了很多的数据结构,下面分别介绍。
6.2.1 头部信息
Resources.arsc 文件格式是由一系列的 chunk 构成,每一个 chunk 均包含如下结构的 ResChunk_header,用来描述这个 chunk 的基本信息:
参数说明:
·type:当前 chunk 的类型。
·headerSize:当前 chunk 的头部大小。
·size:当前 chunk 的大小。
6.2.2 资源索引表的头部信息
Resources.arsc 文件的第一个结构是资源索引表头部,其结构描述了 Resources.arsc 文件的大小和资源包数量:
参数说明:
·header:就是标准的 Chunk 头部信息格式。
·packageCount:被编译的资源包的个数。
6.2.3 资源项的值字符串资源池
紧跟着资源索引表头部的是资源项的值字符串资源池,这个字符串资源池包含了所有在资源包里面定义的资源项的值字符串,字符串资源池头部的结构如下:
参数说明:
·header:标准的 Chunk 头部信息结构。
·stringCount:字符串的个数。
·styleCount:字符串样式的个数。
·flags:字符串的属性,可取值包括 0x000(UTF-16)、0x001(字符串经过排序)、0X100(UTF-8)和它们的组合值。
·stringStart:字符串内容块相对于其头部的距离。
·stylesStart:字符串样式块相对于其头部的距离。
紧接着头部的是两个偏移数组,分别是字符串偏移数组和字符串样式偏移数组。这两个偏移数组的大小分别等于 stringCount 和 styleCount 的值,而每一个元素的类型都是无符号整型。整个字符中资源池结构如图 6-5 所示。
图 6-5 字符串资源池结构
字符串资源池中的前两个字节为字符串长度,长度计算方法如下代码:
如果字符串编码格式为 UTF-8 则字符串以 0X00 作为结束符,UTF-16 则以 0X0000 作为结束符。
字符串与字符串样式有一一对应的关系,也就是说,如果第 n 个字符串有样式,则它的样式描述位于样式块的第 n 个元素。字符串样式的结构包括如下两个结构体:ResStringPool_ref 和 ResStringPool_span。一个字符串可以对应多个 ResStringPool_span 和一个 ResStringPool_ref。ResStringPool_span 在前描述字符串的样式,ResStringPool_ref 在后固定值为 0XFFFFFFFF 作为占位符。样式块最后会以两个值为 0XFFFFFFFF 的 ResStringPool_ref 作为结束。
6.2.4 Package 数据块
接着资源项的值字符串资源池后面的部分就是 Package 数据块,这个数据块记录编译包的元数据,头部结构如下:
参数说明:
·header:Chunk 的头部信息数据结构。
·id:包的 id,等于 Package Id,一般用户包的值 Package Id 为 0X7F,系统资源包的 Package Id 为 0X01。这个值很重要的。
·name:包名。
·typeString:类型字符串资源池相对头部的偏移。
·lastPublicType:最后一个导出的 Public 类型字符串在类型字符串资源池中的索引,目前这个值设置为类型字符串资源池的元素个数。在解析的过程中没发现它的用途。
·keyStrings:资源项名称字符串相对头部的偏移。
·lastPublicKey:最后一个导出的 Public 资源项名称字符串在资源项名称字符串资源池中的索引,目前这个值设置为资源项名称字符串资源池的元素个数。在解析的过程中没发现它的用途。
Package 数据块的整体结构参见图 6-6。
图 6-6 Package 数据块结构
其中 Type String Pool 和 Key String Pool 是两个字符串资源池,结构和资源项的值字符串资源池结构相同,分别对应类型字符串资源池和资源项名称字符串资源池。
再接下来的结构体可能是类型规范数据块或者类型资源项数据块,可以通过它们的 Type 来识别,类型规范数据块的 Type 为 RES_TABLE_TYPE_SPEC_TYPE,类型资源项数据块的 Type 为 RES_TABLE_TYPE_TYPE。
6.2.5 类型规范数据块
类型规范数据块用来描述资源项的配置差异性。通过这个差异性描述,就可以知道每一个资源项的配置状况。知道了一个资源项的配置状况之后,Android 资源管理框架在检测到设备的配置信息发生变化之后,就可以知道是否需要重新加载该资源项。类型规范数据块是按照类型来组织的,也就是说,每一种类型都对应有一个类型规范数据块。其数据块头部结构如下:
参数说明:
·header:Chunk 的头部信息结构。
·id:标识资源的 Type ID。Type ID 是指资源的类型 ID。资源的类型有 animator、anim、color、drawable、layout、menu、raw、string 和 xml 等若干种,每一种都会被赋予一个 ID。
·res0:保留,始终为 0。
·res1:保留,始终为 0。
·entryCount:等于本类型的资源项个数,指名称相同的资源项的个数。
ResTable_typeSpec 后面紧跟着的是一个大小为 entryCount 的 uint32_t 数组,每一个数组元素都用于描述一个资源项的配置差异性。
6.2.6 资源类型项数据块
资源类型项数据块用来描述资源项的具体信息,这样就可以知道每一个资源项的名称、值和配置等信息。资源类型项数据同样是按照类型和配置来组织的,也就是说,一个具有 n 个配置的类型一共对应有 n 个类型资源项数据块,其数据块头部结构如下:
参数说明:
·header:Chunk 的头部信息结构。
·id:标识资源的 Type ID。
·res0:保留,始终为 0。
·res1:保留,始终为 0。
·entryCount:等于本类型的资源项个数,指名称相同的资源项的个数。
·entriesStart:等于资源项数据块相对头部的偏移值。
·resConfig:指向一个 ResTable_config,用来描述配置信息、地区、语言、分辨率等。
ResTable_type 后接着是一个大小为 entryCount 的 uint32_t 数组,每一个数组元素都用于描述一个资源类型项数据块的偏移位置。紧跟在这个偏移数组后面的是一个大小为 entryCount 的 ResTable_entry 数组,每一个数组元素都用来描述一个资源项的具体信息。ResTable_entry 的结构如下:
ResTable_entry 根据 flags 的不同,后面跟随的数据也不相同,如果 flags 为 1,则 ResTable_entry 是 ResTable_map_entry。ResTable_map_entry 继承自 ResTable_entry,其结构如下:
ResTable_map_entry 其后跟随 count 个 ResTable_map 类型的数组,ResTable_map 的结构如下:
如果 flags 为 0,则 ResTable_entry 其后跟随的是一个 Res_value,描述一个普通资源的值,Res_value 结构如下:
参数说明:
·size:ResValue 的头部大小。
·res0:保留,始终为 0。
·dataType:数据的类型,可以从上面的枚举类型中获取。
·data:数据对应的索引。
这里看到了有一个转化的方法,在解析 AndroidManifest 文件的时候也用到了这个方法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论