手把手教你解析Resources.arsc

本文详细介绍了Resources.arsc文件的格式和解析过程,包括R.java文件、资源ID、Resources.arsc的结构,如chunk、全局字符串池、Package解析等,帮助读者理解Android应用程序资源的编译和打包原理。此外,还阐述了如何根据资源ID定位到Resources.arsc中的数据。

一、前言

对于APK里面的Resources.arsc文件大家应该都知道是干什么的(不知道的请看我的另一篇文章Android应用程序资源文件的编译和打包原理),它实际上就是App的资源索引表。下面我会结合实例对它的格式做一下剖析,读完这篇文章应该能够知道Resources.arsc的格式,并可以从二进制的文件中查找到资源的相关信息,或者根据资源的id可以定位到二进制文件中的位置。不过本人对Android资源文件的有一些相关概念并不是特别熟悉,所以文章中有很多地方也并不明白,如有错误欢迎指正!


二、R.java文件及资源ID

首先先介绍一下我们在Android应用开发过程中程序中用的资源的id,相信大家都知道R.java文件,这个是通过aapt对资源文件进行编译生成的资源id文件,这样我们程序中使用资源文件更加方便。举例我们先看一下原始的资源文件res/values/strings.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Cert</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

</resources>

代码段1

这里先介绍几个概念,上面的app_name和hello_world这些叫做资源项名称(其它的还有windowActionBar、ActionBarTabStyle类似这种),而它们对应的资源项类型就是string(其它的还有attr、drawable类似这些),资源项的值就是Cert和Hello world!这些。


下面是对应R.java文件的内容:

public final class R {
              ...
    public static final class string {
                     ...
        /**  Description of the choose target button in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] 
         */
        public static final int abc_shareactionprovider_share_with=0x7f0a000c;
        /**  Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] 
         */
        public static final int abc_shareactionprovider_share_with_application=0x7f0a000b;
        public static final int action_settings=0x7f0a000f;
        public static final int app_name=0x7f0a000d;
        public static final int hello_world=0x7f0a000e;
    }
                     ...
}

代码段2

可以看到每个资源文件在R中都是一个class,每个资源项名称都分配了一个id,id值是一个四字节无符号整数,格式是这样的:0xpptteeee,(p代表的是package,t代表的是type,e代表的是entry),最高字节代表Package ID,次高字节代表Type ID,后面两个字节代表Entry ID。

Package ID相当于是一个命名空间,限定资源的来源。Android系统当前定义了两个资源命令空间,其中一个系统资源命令空间,它的Package ID等于0x01,另外一个是应用程序资源命令空间,它的Package ID等于0x7f。所有位于[0x01, 0x7f]之间的Package ID都是合法的,而在这个范围之外的都是非法的Package ID。前面提到的系统资源包package-export.apk的Package ID就等于0x01,而我们在应用程序中定义的资源的Package ID的值都等于0x7f,这一点可以通过生成的R.java文件来验证。

Type ID是指资源的类型ID。资源的类型有animator、anim、color、drawable、layout、menu、raw、string和xml等等若干种,每一种都会被赋予一个ID。

Entry ID是指每一个资源在其所属的资源类型中所出现的次序。注意,不同类型的资源的Entry ID有可能是相同的,但是由于它们的类型不同,我们仍然可以通过其资源ID来区别开来。


三、解析Resources.arsc


1. Resources.arsc文件格式

下面我们开始看Resources.arsc(后面截图给出的resources.arsc文件的二进制内容都是与上面代码段1和代码段2相对应的),首先看一下文件的格式,如下面两个图:


图1


图2

以上两个图都是Resources.arsc文件的格式,图1是从网上找的,其中很多项都展开了,不了解对应的数据结构肯定看不懂,所以我自己画了图2(画图好蛋疼的说~抓狂),相对来说更容易接受一点,这里都放出来做个对照吧。Resources.arsc对应的数据结构的定义在Android源码/frameworks/base/include/androidfw/ResourceType.h中,大家可以自己去看一下。


2. chunk

下面我来从上到下介绍一下文件的格式,首先是chunk概念,整个文件是由一系列的chunk构成的,算是整个文件划分的基本单位吧,实际上就是把整个文件无差别的划分成多个模块,每个模块就是一个chunk,结构更加清晰。每个chunk是最前面是一个ResChunk_header的结构体,描述这个chunk的信息,ResChunk_header如下:

struct ResChunk_header
 {
     enum 
     {
         RES_NULL_TYPE               = 0x0000,
         RES_STRING_POOL_TYPE        = 0x0001,
         RES_TABLE_TYPE              = 0x0002,
         RES_XML_TYPE                = 0x0003,
         RES_XML_FIRST_CHUNK_TYPE    = 0x0100,
         RES_XML_START_NAMESPACE_TYPE= 0x0100,
         RES_XML_END_NAMESPACE_TYPE  = 0x0101,
         RES_XML_START_ELEMENT_TYPE  = 0x0102,
         RES_XML_END_ELEMENT_TYPE    = 0x0103,
         RES_XML_CDATA_TYPE          = 0x0104,
         RES_XML_LAST_CHUNK_TYPE     = 0x017f,
         RES_XML_RESOURCE_MAP_TYPE   = 0x0180,
         RES_TABLE_PACKAGE_TYPE      = 0x0200,
         RES_TABLE_TYPE_TYPE         = 0x0201,
         RES_TABLE_TYPE_SPEC_TYPE    = 0x0202
     };
     //当前这个chunk的类型
     uint16_t t
<think>我们正在解析Android resources.arsc文件,这是一个二进制文件,包含应用程序的所有资源信息(如字符串、布局、样式等)。解析该文件需要了解其结构,通常使用工具或编写程序来读取。 根据引用[1],我们可以使用Android Asset Packaging Tool (aapt)来解析resources.arsc文件。aapt是Android SDK中的一个工具,可以用于查看、创建、更新ZIP格式的归档文件(如APK文件),也可以用于解析resources.arsc文件。 另外,引用[3]提到resources.arsc文件包含多个chunk(块),每个chunk都有一个头部,其中包含类型标识(如0x0202表示Type Spec)和大小等信息。 解析步骤: 1. 使用aapt工具:这是最简单的方法,通过命令行执行aapt命令来转储resources.arsc的内容。 2. 编程解析:如果需要在自己的程序中解析,则需要了解resources.arsc的二进制格式,并编写代码读取。 下面分别介绍这两种方法: ### 方法1:使用aapt工具 在Android SDK的build-tools目录下可以找到aapt(或aapt2)工具。使用以下命令: ```bash aapt dump resources <path_to_apk> > output.txt ``` 或者,如果你已经将resources.arsc文件单独提取出来(例如从APK中解压),则可以使用: ```bash aapt dump resources resources.arsc > output.txt ``` 这个命令会将resources.arsc文件的内容输出到output.txt文件中,包括资源类型、资源项的具体信息等。 注意:在Android SDK build-tools 30.0.0及以上版本中,aapt2是默认工具,但aapt2主要用于编译资源,而aapt则用于转储资源信息。不过,aapt2也提供了类似的功能: ```bash aapt2 dump resources <path_to_apk> --output output.txt ``` ### 方法2:编程解析 如果需要编程解析,我们需要了解resources.arsc的文件格式。该文件大致由以下几个部分组成: - 文件头(ResTable_header) - 全局字符串池(String Pool) - 包数据(Package):包含多个类型(Type)和配置(Config)的资源项。 每个资源项都有其特定的结构,如ResTable_typeSpec、ResTable_type等。 由于格式复杂,我们可以参考Android源码中的ResourceTypes.h(位于frameworks/base/include/androidfw/)来了解详细结构。 以下是一个简化的步骤(使用C++或Java,但通常C++更常见,因为需要处理二进制数据): 1. 读取文件头,验证魔数(0x00000002)和文件大小。 2. 读取字符串池(全局字符串池)。 3. 读取包数据(可能有多个包,但通常只有一个)。 4. 在包数据中,读取类型规范(TypeSpec)和类型(Type)信息。 但是,编程解析较为复杂,通常建议使用现有的库或工具。例如,在Java中,可以使用Android的AssetManager类,但该类主要用于运行时访问资源,并不直接用于解析arsc文件。 另外,也有一些开源库可以解析resources.arsc,例如: - [ArscBlamer](https://github.com/google/android-arscblamer) - [android-arsc-parser](https://github.com/rednaga/android-arsc-parser)(一个Python库) 例如,使用Python库android-arsc-parser: ```python from arsc_parser import ArscParser with open('resources.arsc', 'rb') as f: data = f.read() parser = ArscParser(data) parser.parse() # 然后可以访问parser中的各种结构 ``` 该库可以将resources.arsc文件解析成结构化的数据,然后我们可以按需提取信息。 ### 注意事项 - resources.arsc文件可能包含多个包(package),但通常一个APK只有一个包。 - 资源项按照类型(如drawable、string、layout等)和配置(如语言、屏幕方向等)分组。 总结:对于大多数情况,使用aapt工具即可满足查看资源信息的需求。如果需要编程处理,则可以选择现有的解析库。 下面,我们将根据用户的问题,生成相关问题。</think>要解析 Android 的 `resources.arsc` 文件(资源映射表),主要有以下方法: ### 一、使用 Android SDK 工具解析 1. **aapt/aapt2 工具** 在终端执行以下命令(需提前配置 Android SDK 环境): ```bash # 解析 APK 中的 resources.arsc aapt dump resources your_app.apk # 若已提取 resources.arsc 文件 aapt dump resources resources.arsc ``` 输出内容包含: - 资源类型(字符串、布局、样式等) - 资源 ID 与资源路径的映射关系 - 资源配置(语言、屏幕尺寸等)[^1][^2] 2. **apktool 反编译工具** 使用命令解压 APK: ```bash apktool d your_app.apk ``` 解压后可在输出目录查看 `resources.arsc` 的文本化内容(存储在 `res/values/` 下的 XML 文件中)。 --- ### 二、编程解析(Java/Kotlin) 通过 `AndroidResourcesParser` 读取二进制数据: ```java InputStream arscStream = new FileInputStream("resources.arsc"); AndroidResourcesParser parser = new AndroidResourcesParser(); ResTable resTable = parser.parse(arscStream, true); // 遍历所有资源类型 for (ResType type : resTable.getTypes()) { System.out.println("Type: " + type.getName()); // 遍历资源项 for (ResEntry entry : type.getEntries()) { System.out.println("ID: " + entry.getResourceId() + " | Value: " + entry.getValue()); } } ``` --- ### 三、关键文件结构解析 `resources.arsc` 采用二进制格式,主要结构包括: | **区块类型** | **十六进制标识** | **描述** | |--------------|------------------|----------| | **ResTable_header** | `0x00000002` | 文件头(魔数) | | **String Pool** | `0x0001` | 全局字符串池(存储资源键名) | | **Package** | `0x0200` | 资源包定义(包名、类型数量) | | **TypeSpec** | `0x0202` | 资源类型规范(如 `layout`/`string`) | | **Type** | `0x0201` | 具体资源配置项(不同语言/屏幕尺寸的资源值)[^3] | --- ### 四、应用场景 1. **资源混淆分析**:检查资源 ID 与名称的映射关系,用于反编译防护研究[^2][^3]。 2. **动态换肤**:运行时修改资源值实现主题切换。 3. **资源优化**:分析未使用的资源项以减少 APK 体积。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值