10.1.3 资源保护

10.1.3 资源保护

1.PC端

这里的资源是指存储在PE程序文件中的非程序自身指令的数据,如字串表、图标、图片、窗口资源等。在PE程序中,它们被集中存储在一个数据区域内,而这个区域是PE程序中非常重要的区域,因此保护系统自然不会放过对资源的处理。但是,受限于资源区段的特殊性,且保护系统很难准确识别资源中的具体数据格式和用途,所以,除了几种特定类型的资源外,保护系统为了实现较好的兼容性,只能将其他资源都作为纯二进制数据来对待。因此,保护系统无法将具体资源变形或者加密,只能整体移动其位置,或者对其实行整体算术加密,这限制了资源保护的力度。大部分的保护系统对于资源的加密都停留在压缩移位上,当程序运行后就将资源解压或解密,放到一个内存区域,并修正内存中的PE文件头。

有些保护系统会HOOK各种与资源相关的函数,然后在调用这些函数时动态解密资源。我们来看VMProtect保护系统的例子。打开资源保护加密程序,直接查看程序运行时的一些与资源相关的系统函数入口,如图10.1和图10.2所示。

图10.1 系统函数入口(a)

图10.2 系统函数入口(b)

可以发现,VMProtect保护系统接管了Ldr AccessResource()和Ldr Find Resource_U()这两个系统函数,实际上被保护程序导入表中的上层函数(如Load Resources()和Find Resources())都被替换成了VMProtect自己的函数。这样,当需要在程序中查找资源时,VMProtect会动态解密资源。尽管会带来一些兼容性上的问题,但这仍是一种非常好的资源加密方式。

2.移动端

由于.dex文件的重要性,绝大多数开发者在开发阶段就会使用eclipse开发工具自带的ProGuard对.dex文件进行混淆保护,但是对于资源文件,绝大部分开发者并没有考虑这些文件的安全性。下面通过一个例子说明保护资源文件的重要性。首先使用反编译工具apktool对某应用进行反编译,使用命令为:“apktool d-s xxx.apk”,反编译成功之后,得到的资源文件的目录如图10.3所示。

通过图10.3中的目录结构,可以看到这个应用的资源文件有color、layout、menu等,可以使用xml编辑工具对这些文件夹下的资源文件进行修改。例如,图10.3中横线所标示的payment_list_item.xml文件,从该文件的名称可知该文件与支付信息相关,可对其进行修改,就能向原有APK的支付信息中添加一些自己的东西,最后通过apktool进行回编译就能创建一个经过修改过的APK应用。这个问题发生的原因是,在开发过程中开发人员倡导命名的规范性,不仅方便自己的理解,也有利于后期的维护工作。但与此同时也方便攻击人员进行破解工作,他们可以根据文件名称来猜测该文件的意图和作用,从而做一些针对性的修改。通过这个例子我们可以看出资源安全的重要性,那如何做到资源安全呢?从上文的分析可知,资源文件的规范性命名使得攻击人员轻易猜测到这些文件的作用,但是若不规范命名,又给开发过程增添额外的负担。而且,对于加固系统来说,是无法涉及应用程序的原始编译过程的。

图10.3 Apktool反编译后资源文件的目录

混淆工具Proguard能对源码级别的一些变量名、函数名等进行混淆,但是该工具与编译过程相关,不适合用于加固系统。通过实验验证,发现编译后的资源文件也是可以进行重命名操作的,主要是通过修改resources.arsc和资源文件来对资源文件进行重命名。为方便理解,下面先介绍Android应用查找资源的流程。Android应用程序为了适配不同的手机之间屏幕的差异性,以及适配不同的国家、地区和语言等,包含了许多不同的资源文件。应用程序运行时Android系统会自动根据设备的配置信息进行适配,因此给定一个相同的资源ID,在不同的设备配置之下,查找到的可能是不同的资源。在Android系统中,Resources类可以根据ID来查找资源,Asset Manager类根据文件名来查找资源。事实上,如果一个资源ID对应的是一个文件,那么Resources类是先根据ID来找到资源文件名称,然后再将该文件名称交给Asset Manager类来打开对应的文件的。混淆工具Proguard的工作基本流程如图10.4所示。

图10.4 混淆工具Proguard的工作基本流程

通过图10.4我们可以看到Resources类是通过resources.arsc把资源的ID转化成资源文件的名称,然后交由Asset Manager来加载的。而resources.arsc这个文件是存放在APK包中的,他是由编译工具在打包过程中生成的,它本身是一个资源的索引表,里面维护着资源ID、Name、Path或者Value的对应关系,Asset Manager通过这个索引表,就可以通过资源的ID找到这个资源对应的文件或数据。因此通过修改resources.arsc文件和res目录,可以达到资源名称混淆的效果。