作者:张跃骞
关键词:Android,加固,脱壳;
原文链接:http://www.inforsec.org/wp/?p=581
Android平台自发布以来受到了广大消费者的欢迎,已经占到81%的市场份额,也吸引了大量的开发者,带来了巨大的收益。然而巨大的成功也使得Android系统成为了黑客的一大战场。由于Android app自身的机制,使得其很容易遭到破解。通过使用简单的反编译工具,基本上能够达到阅读源代码的程度,进而再进行二次修改、重新打包并发布。由此可见,恶意软件可以很容易地附加在正常的app中伪装自己,竞争对手间可以很容易地获得对方app中的技术信息,这种严峻的形势催生了Android app保护技术的出现并不断地提高完善。
在中国,出现了相当数量的一批Android app保护的厂商。它们通常采用多种手段来保护和隐藏原有的可执行文件(即dex文件),并使用反调试技术在运行的时候阻止对相关内存区域进行读取而得到有效的dex文件。同时也使用混淆技术如ProGuard、DexGuard等工具增加反编译后的代码的分析难度。
Android app保护技术也是一把双刃剑,黑客也广泛使用它来保护恶意和重打包的app,使得难以被分析和判定,在一定程度上提高了传播的范围。所以对于恶意程序分析人员来说,甚至对于软件相似性检测、代码抄袭等相关电子取证技术,破除app的保护也是必不可少的第一步。
我们主要研究了6中主流的Android app保护厂商的产品:梆梆、腾讯、爱加密、360、阿里和百度(截止2015年9月)。通过相关的一些分析,我们来看一看这些厂商是如何来实现app的保护的:
360:将原有的dex文件加密后存储在libjiagu.so/libjiagu_art.so,在运行时动态释放并解密。
阿里:将原有的dex文件拆分为两部分,一部分主体保存为libmobisecy.so,另一部分包含了一部分class_data_item和code_item。在运行的时候将两部分释放在内存中,并修复相关的指针,恢复数据之间的连接关系。同时一些annotation_off被设置为无效的值。
百度:将一些class_data_item存储在dex文件的外部,在运行时恢复与主体的dex的连接关系。在dex文件加载后,其头部的魔数,校验和以及签名值会被擦除。同时某些方法被改写,使得其在执行前相关的指令才会被恢复,在执行之后便立即擦除。
梆梆:提前准备了一个odex或oat文件,并加密保存为外部的jar文件,运行时解密;同时hook了libc.so中的一些函数,如read,write, mmap等,监视其操作区域是否包含了dex的头部,保证无法使用这些函数对于dex文件进行操作。
爱加密:同样是加密原有的dex文件,在运行时整体释放并解密,只不过其释放的处于固定路径下的临时文件的名字是随机的。
腾讯:提供选项可以指定需要保护的方法。如果某个方法被保护,则在dex文件中的相关class_data_item中无法看到其数据,即为一个假的class_data_item;在运行时释放真正的class_data_item并连接到dex文件上,但是其code_item却一直存在于原有的dex文件中。同样地,一些annotation_off和debug_info_off被填充为无效值来阻止静态反编译。只支持在DVM环境下运行。
这些产品都具备反调试的能力,也就是说通过使用ptrace或JWDP等调试接口动态附加调试比较困难。
App加固作为一项技术热点,之前的研究主要处于工业界,学术界对其关注不多。
比较著名的反编译工具有backsmali/smali, Apktool , IDA Pro等,但是无法克服 app加固 的保护。
Apvrille [1] 较早地提出了利用加密方法如异或操作、DES或AES算法来隐藏原始的指令。Strazzere在 [2] 提出利用反射方法来调用一些关键的函数,并将真正地dex文件保存在资源中以及使用一些反调试的技术。Schulz在 [3,4] 讨论了利用变量名和字符串混淆,代码动态加载,插入垃圾指令以及利用JNI来实现dalvik代码自修改 [5] ,这些技术现在仍在被广泛使用。Apvrille [6] 通过修改encoded_method的数据实现了对相关方法的保护。Martin在 [7] 描述了一种新的保护方法。从Android 4.0起提供了一个新的接口,可以将一块内存作为dex文件打开,利用此特性可以进一步保护dex文件的指令并实现动态指令修改。Nigam 在 [8] 分析了当时的一些加固产品及其工作原理。 Strazzere 在 [9] 介绍并分析了一些混淆工具如ProGuard, DexGuard和 ALLATORI和梆梆的加固产品。Apvrille 在 [10] 中将dex文件利用AngeCryption [11] 处理为一个resource文件从而进行隐藏,而且这个被加密的dex文件可以被静态打开显示为一个图片,同时在运行的时候可以进行解密并得到执行。Apvrille 在 [12,13] 也讨论了一些混淆工具和加固产品的原理,并分析了一些可以用于干扰静态和动态分析的方法。YU [14] 分析了一些Android加固产品的原理,并基于LiME [15] 构建了一个工具用于获取目标内存区域的内容。
ZjDroid [16] 是基于Xposed的脱壳工具。它hook了BaseDexClassLoader对象来获取包含dex文件的目标内存,它只支持DVM并且需要root权限。对于阿里等将原始dex文件拆分的做法,它也无法克服。
Park在 [17] 提出了一种方法:对apk进行重新打包,并插入一个调用了wait-for-debug 功能的方法,使得app在启动后会暂停并等待用户利用JWDP调试协议进行连接。这样可以调试目标app并读取其内存。但此方法很容易被检测绕过且无法克服反调试的限制。
Jung 在 [18] 提出了一个叫做DABiD的调试器。它可以获取到内存中有效的dex文件。它通过将自己的模块注入到目标app的进程中,监视内存中的动态修改包括代码自修改和动态类加载,并将相关信息反映到调试器中。同样地,它不支持ART环境。并且由于它只监视了dex文件的内存区域,所以针对于修改Android运行时所维护的对象的行为无法进行监视和捕获。
之前对于各种app保护的破解方法,主要还是处于和app自身同样的运行级别,所以很容易被检测到并且绕过,所以我们的思路是直接提高脱壳模块的等级,将其整合到Android的运行时中,并使得内存中的dex文件得到尽大程度的恢复,这样被运行时解释和执行的app便很难绕过了,而且也轻易解决了反调试技术的限制。
根据此思路我们设计了DexHunter [19,20] ,它整合进了DVM和ART两个运行时。通过由用户指定一个特征字符串来定位到包含dex主体部分的内存区域。这个特征字符串主要用来匹配运行时当前使用的dex文件是否是我们需要的dex文件。一旦获取了dex的主体部分,接下来便主动加载并初始化dex文件中的所有class,尽力使其恢复到正常运行的状态。接下来我们将整个区域分为三部分,重点处理包含class数据的第二部分。我们对于每一个class进行解析,并观察其中是否有数据位于主体dex范围之外,及相关的信息是否与Android运行时所维护的数据一致,如果有所出入,则修改dex文件中的相关数据,并将外部的数据收集在一起重新存储在尾部,并修正相关的指针,这样我们便能够得到一个完整的dex文件。整体的思路如图1所示:
图1. DexHunter工作原理
对于一些无效的字段,我们可以在得到dex文件后将其全部抹除为0,这样便不会影响apktool等工具进行反编译。对于百度所使用的抹除方法指令的手段,我们也可以监控DoInvoke (ART) 和dvmMterp_invokeMethod (DVM)方法实时的提取有效指令;也可以修改还原的dex文件,去掉调用百度中抹除指令的JNI方法的指令,这样的话同样可以从内存中获取有效的指令。
破除app的保护,主要的手段就是从内存中拿到有效的执行数据,这样关键点就在于时机的选择或主动触发,从而保证内存中存在有效的数据。所以app保护技术一个重要的关注点也就在于如何打乱时机,使破解者无法找到一个关键点来获取到有效的dex文件。下一步的发展趋势是可能使用虚拟机壳的技术。虽然实现上并没有太多障碍,但是由于效率原因,距离实用还是有一些距离的。
此外,一个简单的方法是可以将关键的代码编写为native指令,通过JNI来调用,增加逆向的难度。也可以对dex中的dalvik指令进行控制流混淆。
对于ART下的保护,由于设备依赖性的问题,其实还是使用解释执行的方式来运行。由于ART下的dex文件需要编译为native指令,尤其对于static方法的调用,使用的是确定的地址进行调用的。如果想提前准备一个编译好的oat文件,除去要绕过运行时对于oat文件和framework的匹配校验,还需要对这些地址根据不同设备的framework进行动态patch。如果能处理好这些的限制,便可以直接提前准备好native指令的oat文件,同样能够大幅度增加保护的力度。
最后,也可以通过VMI的方法,监控所有内存写指令,并辅以人工分析,也可以逐步地恢复出加固工具的工作原理和流程,有助于自动化分析一些新的保护技术。
张跃骞,安全技术爱好者,看雪社区成员,长期从事系统及软件安全研究,曾任香港理工大学研究助理,HITCON 2015 讲师。
[1] Axelle Apvrille, “Cryptography for mobile malware obfuscation,” http://goo.gl/jOiYHt .
[2] Timothy Strazzere, “Dex education: Practicing safe dex,” http://goo.gl/U84ja .
[3] P. Schulz, “Code protection in android,” Tech. Rep., 2012. https://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/2012-Schulz-Code_Protection_in_Android.pdf
[4] Patrick Schulz, Felix Matenaar, “Android reverse engineering & defenses,” https://goo.gl/nZEOGm , 2013.
[5] Patrick Schulz, “Android security analysis challenge: Tampering dalvik bytecode during runtime,” https://goo.gl/07QBou , 2013.
[6] Axelle Apvrille, “Playing hide and seek with dalvik executables,” https://goo.gl/LNIJcx .
[7] Xavier Martin, “Nifty stuff that you can still do with android,” http://goo.gl/vEPXsq .
[8] Ruchna Nigam, “Android packers: Separating from the pack,” http://goo.gl/FM0lzc .
[9] Tim Strazzere, Jon Sawyer, “Android hacker protection level 0,” https://goo.gl/agIEmb .
[10] “Hide android applications in images,” https://goo.gl/DDZUjA .
[11] “Angecryption,” http://goo.gl/tb6irJ .
[12] Axelle Apvrille, Ruchna Nigam, “Obfuscation in android malware, and how to fight back,” https://goo.gl/qw38un .
[13] “How android malware fights,” http://goo.gl/4zLoRK .
[14] Rowland YU, “Android packer: facing the challenges, building solutions,” https://goo.gl/xrC8xO .
[15] “Lime-linux memory extractor,” https://goo.gl/JyUopv .
[16] “Zjdroid,” http://goo.gl/xFxxNh , 2015.
[17] Yeongung Park, “We can still crack you!” https://goo.gl/7PMn0v .
[18] Jin-hyuk Jung, Jieun Lee, “Dabid, the powerful interactive android debugger for android malware analysis,” https://goo.gl/KTbLyx .
[19] Y. Zhang, X. Luo, and H. Yin, “ Dexhunter: Toward extracting hidden code from packed android applications,” in Proc. ESORICS , 2015.
[20] “DexHunter”, https://github.com/zyq8709/DexHunter