内容纲要

resource.arsc

resource.arsc文件是Apk打包过程中的产生的一个资源索引文件。

文件作用

在java中访问一个文件是需要提供文件的文件名,例如:

new File("./res/drawable-xxhdpi/img.png");

然而在Android中,却可以通过drawable Id获得资源文件:

getDrawable(R.drawable.img);

这里凭一个id就能获取资源文件内容,省去了文件路径的手动输入,其背后就是通过读取arsc文件实现的。

这些R.drawable.xxxR.layout.xxxR.string.xxx等的值(存储在R.jar或者R.java文件中)称之为 资源索引 ,通过这些资源索引可以在arsc文件中查取实际的资源路径或资源值;

例如: getDrawable(R.drawable.img)在编译后成了getDrawable(2131099964),再将id转为十六进制:

2131099964 = 0x7f06013c

这时的资源索引为0x7f06013c

资源索引具有固定的格式:0xPPTTEEEE

PackageId(2位) + TypeId(2位) + EntryId(4位)

  • PP: Package ID,包的命名空间,取值范围为[0x01, 0x7f],第三方应用均为7f。
  • TT: 资源类型,有anim、layout、mipmap、string、style等资源类型。
  • EEEE: 代表某一类资源在偏移数组中的值

所以,0x7f06013c中 PackageId = 0x7f、TypeId = 0x06、EntryId = 0x013c

最简单的我们可以将arsc函数想象成一个含有多个Pair数组的文件,且每个资源类型(TypeId)对应一个Pair[](或多个,为了便于理解先只认为是一个)。因此在arsc中查找0x7f06013c元素的值,就是去设法找到TypeId=0x06所对应的数组,然后找到其中的第0X013c号元素。这个元素恰好就是"img => ./res/drawable-xxhdpi/img.png",左边是资源名称,右边是资源的文件路径,有了这个字符串程序便可以访问到对应的资源文件了。

arsc文件结构

img

android-chunk-utils是一个用java编写的arsc文件解析工具

参考

https://zhuanlan.zhihu.com/p/262000709

资源加密

打包后的apk如需资源加密,只能通过在运行过程中hook相关的函数接口进行解密,来达到保护效果。市场上的资源文件保护方案可分为定制方案和通用方案两大类。

img

定制方案

定制方案的使用场景多样,一般根据文件类型分类,包括脚本类和资源类。其中,js,lua,python等脚本,根据不同的脚本引擎做加密,同时利用hook或重写解释器的方式重新解析脚本进行解密,而u3d资源,png,jpg图片等资源,可能会涉及资源读取方式或基于图片格式制定的加密方式,加密后需在特定时机进行解密。

通用方案

apk本质上是个zip格式文件,读取资源文件即读取zip里的文件。因此,其原理离不开读文件和解压两个过程。如果能在读文件或者解压两个过程进行hook,并对文件内容进行解密,就能达到资源保护的效果。简单来讲,一个是针对libz.so进行hook,一个是针对libc.so进行hook。

参考

https://dun.163.com/news/p/760c8c1ad4ee4349951646d85814264d