Android代码混淆技术总结(一)
一、前言
最近一直在学习Android加固方面的知识,看了不少论文、技术博客以及一些github上的源代码,下面总结一下混淆方面的技术,也算是给想学习加固的同学做一些科普,在文中讲到的论文、资料以及源码,我都会给出相应的链接,供大家进一步去深入学习。后面我会弄成一个系列的文章,如有一些混淆技术没讲到,还希望大家指点,当做是交流学习。
二、Android混淆技术介绍
2.1 控制流平坦化
2.1.1 概念和思路
控制流平坦化,就是在不改变源代码的功能前提下,将C或C++代码中的if、while、for、do等控制语句转换成switch分支语句。这样做的好处是可以模糊switch中case代码块之间的关系,从而增加分析难度。
这种技术的思想是,首先将要实现平坦化的方法分成多个基本块(就是case代码块)和一个入口块,为每个基本快编号,并让这些基本块都有共同的前驱模块和后继模块。前驱模块主要是进行基本块的分发,分发通过改变switch变量来实现。后继模块也可用于更新switch变量的值,并跳转到switch开始处。详细的概念可以参考文献[1]。
其模型如下图:
下面用代码来说明,左边方法是没有采用控制流平坦化之前的效果,右边是采用了控制流平坦化的效果。
2.1.2 开源项目
目前用的最多的是OLLVM(Obfuscator-LLVM)的开源混淆方案,很多国内加固厂商都可以看到使用它的身影。它提供了3中保护方式:控制流平坦化、虚假控制流和指令替换。其项目地址如下:
https://github.com/Fuzion24/AndroidObfuscation-NDK
https://github.com/obfuscator-llvm/obfuscator
2.1.3 对抗
目前,对于ollvm的反混淆思路,多采用基于符号执行的方法来消除控制流平坦化,这里不做详细分析,详细的分析思路,可以参考quarkslab写的文章[3]。
2.2 花指令
2.2.1 概念和思路
花指令也叫垃圾指令,是指在原始程序中插入一组无用的字节,但又不会改变程序的原始逻辑,程序仍然可以正常运行,然而反汇编工具在反汇编这些字节时会出错,由此造成反汇编工具失效,提高破解难度。
花指令的主要思想是,当花指令跟正常指令的开始几个字节被反汇编工具识别成一条指令的时候,才可以使得反汇编工具报错。因此插入的花指令都是一些随机的但是不完整的指令。但是这些花指令必须要满足两个条件:
在程序运行时,花指令是位于一个永远也不会被执行的路径中。
这些花指令也是合法指令的一部分,只不过它们是不完整指令而已。
也就是说,我们只需要在每个要保护的代码块之前插入无条件分支语句和花指令,如下图所示。无条件分枝是保证程序在运行的时候不会运行到花指令的位置。而反汇编工具在再反汇编时由于会执行到花指令,所以就会报错。
那么目前的反汇编工具所使用的反汇编算法,主要分为两类:线性扫描算法和递归扫描算法。
线性扫描:依次按顺序逐个地将每一条指令反汇编成汇编指令
例如下面的指令:
如果是反汇编工具使用线性扫描算法,就会把花指令错误识别,导致反汇编出错。如下:
Dalvik Bytecode Obfuscation on Android[5]这篇文章就利用线性扫描的特点,插入fill-array-data-payload花指令,导致反编译工具失效。
递归扫描:按顺序逐个反汇编指令,如果某个地方出现了分支,就会把这个分支地址记录下来,然后对这些反汇编过程中碰到的分支进行反汇编。
可见,递归扫描的算法反汇编能力更强。我们常用的Android逆向工具里面,使用的反汇编算法如下:
2.2.2 开源项目
(1) https://github.com/thuxnder/dalvik-obfuscator
可以结合文章[5]一起看。
(2) https://github.com/faber03/AndroidMalwareEvaluatingTools
这个工具是意大利萨尼奥大学的laswatlab团队打造出来的恶意程序免杀工具,其实就是使用各种混淆技术,其中也包括花指令插入,在AndroidMalwareEvaluatingTools/transformations sources/JunkInsertion/目录下。该工具的使用报告可以参考文献[4]。
(3) https://github.com/strazzere/APKfuscator
APKFuscator通过插入下图的垃圾指令使得反汇编器出错。
2.2.3 对抗
检测出花指令的位置和长度,然后用NOP指令替换即可。
2.3 标识符混淆
2.3.1 概念和思路
标识符混淆就是对源程序中的包名、类名、方法名和变量名进行重命名,用无意义的标识符来替换,使得破解这分析起来更困难。最常用的就是ProGuard开源工具,其混淆后效果如右图所示。
甚至通过定制混淆字典,可以达到下面这种混淆效果,参考开源项目[7]:
那么这个标识符混淆的原理是怎样的呢?要了解这个原理,我们得事先对dex文件格式有一定了解,这个资料大家可以在网上找,很多,这里就不详细说了。
我们知道dex文件中的类名、方法名、变量名其实都对应的一个string_id的字符串索引,如下图。每一个类对应着class_def_item结构体,其中class_idx就是指向类名的字符串索引。
同样,每个方法也是对应一个method_id_item的结构体,其中name_idx就是指向方法名的字符串索引。
字段名也一样,对应着一个field_id_item的结构体,其中name_idx是指向字段名的字符串索引。
也就是说,我们只要修改相应的string_id索引表中的字符串,就可以达到标识符混淆的目的。
具体的实现可以参考文章[10],它还提供了一个dex混淆器的简单原型:DexConfuse。
2.3.2 开源项目
(1) ProGuard
(2) https://github.com/burningcodes/DexConfuse
DexConfuse是一个简单的dex混淆器,可以混淆类名、方法名和字段名。
(3) https://github.com/strazzere/APKfuscator
APKFuscator作者通过解析修改Dex文件格式,修改类名,使类名字符个数超过255个,使得反汇编器报错。
修改类名使得字符个数超过255个
2.3.3 对抗
文献[8]采用的一种反混淆方式就是通过大规模的学习为混淆的APK,然后总结出一个概率模型,通过这个概率模型来识别混淆后的代码。其反混淆流程如下图分为3个步骤:
Step1:生成一个依赖关系图,每个节点代表要重命名的元素,每条线代表依赖关系。
Step2:导出一些限制规则,这些规则可以保证回复的APK是个正常的APK,且和原APK语义相同。
Step3:根据概率模型提供的权重,对混淆的元素的原始名称进行预测和恢复。
作者将论文中的反混淆方法做成了一个在线的反混淆工具提供使用:
2.4 字符串混淆
2.4.1 概念和思路
很多时候,为了避免反汇编后的代码容易被破解者分析读懂,往往会源程序中一些比较关键的字符串变量进行混淆,使得破解者分析成本提高。这里的字符串混淆有两种,一种是Java层的字符串混淆,另一种是native层的字符串混淆,也就是so文件中的字符串混淆。上面我们介绍了Proguard免费混淆工具,它可以混淆类名、方法名和变量名,但是不支持字符串混淆,要使用字符串混淆就需要使用DexGuard商业版混淆器。
实现思路如下:
(1) 编码混淆
编码混淆就是先将字符串转换成16进制的数组或者Unicode编码,在使用的时候才恢复成字符串。这样破解者在逆向后看到的是一串数字或者乱码,很难直接分析。
如下代码所示,其实就是输出一个Hello World。但是我们硬编码的时候是保存它的ASCII对应的十六进制,在使用的时候才转换成字符。在反编译成smali后,就看不到任何的有意义的字符串了。
Java代码:
apktool反编译后的smali代码:
同样的在native层的代码也可以使用类似的方式实现对C或C++中的字符串进行混淆。
(2) 加密处理
加密处理就是实现在本地将字符串加密,然后将密文硬编码到源程序中,再实现一个解密函数,在引用密文的地方调用解密函数解密即可。如下图。
还有一种方式是我们可以修改dex文件。对于Java层的字符串加密,我们可以在dex文件中,找到要加密的字符串在字符串常量表中的位置,然后对它用加密算法加密。然后在自定义Application的attachBaseContext方法中在运行时对密文进行解密,或者可以在native层加密,提高破解难度。
同样的,我们也可以修改SO文件。SO文件中也存在只读常量区”.rodata”,如下图所示。我们可以根据section header table来找到”.rodata”的位置和大小,然后实现对只读常量区进行加密混淆,在运行的时候再调用相应的解密算法解密即可。
2.4.2 开源项目
https://github.com/ysrc/obfuseSmaliText
obfuseSmaliText是国内同程安全的一个员工实现免费字符串混淆工具,它是通过apktool反编译安装包,在smali层对字符串进行混淆,目前采用的是异或+十六进制的方式进行混淆。效果如下图:
2.4.3 对抗
对于使用了字符串混淆,只能找到响应的解密函数,调用解密函数去解密就可以恢复明文。
三、结束
这次就写到这里,后面我还会继续补充其他的混淆技术,包括控制流变换、模拟器检测、反调试、Java代码native化等。
参考
[1] obfuscating C++ Programs via Control Flow Flattening
http://www.inf.u-szeged.hu/~akiss/pub/pdf/laszlo_obfuscating.pdf
[2]利用符号执行去除控制流平坦化
https://security.tencent.com/index.php/blog/msg/112
[3] Deobfuscation: recovering an OLLVM-protected program.
http://blog.quarkslab.com/deobfuscation-recovering-an-ollvm-protected-program.html
(备注:中文翻译版,http://www.0daybank.org/?p=7845 )
[4] Evaluating malwares obfuscation techniques against antimalware detection algorithms.
http://www.iswatlab.eu/wp-content/uploads/2015/09/mobile_antimalware_evaluation.pdf
[5] Dalvik Bytecode Obfuscation on Android http://www.dexlabs.org/blog/bytecode-obfuscation
[6] Detecting repackaged android apps using server-side analysis
https://pure.tue.nl/ws/files/46945161/855432-1.pdf
[7] https://github.com/ysrc/AndroidObfuseDictionary
[8] Statistical Deobfuscation of Android Application. http://www.srl.inf.ethz.ch/papers/deguard.pdf
[9] Android字符串及字典开源混淆实现 https://mp.weixin.qq.com/s/SRv1Oar87w1iKuDXS4oaew
[10] Dex混淆的原理及实现
http://burningcodes.net/dex%E6%B7%B7%E6%B7%86%E7%9A%84%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE%9E%E7%8E%B0/
[11] Android Code Protection via Obfuscation Techniques Past, Present and Future Directions.
https://arxiv.org/pdf/1611.10231.pdf
本文来自合作伙伴“阿里聚安全”,发表于2017年04月07日 10:58.

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
利用FRIDA攻击Android应用程序(三)
利用FRIDA攻击Android应用程序(三) 前言 在我的有关frida的第二篇博客发布不久之后,@muellerberndt决定发布另一个OWASP Android crackme,我很想知道是否可以再次用frida解决。如果你想跟着我做一遍,你需要下面的工具。 OWASP Uncrackable Level2 APK Android SDK和模拟器(我使用的是Android 7.1 x64镜像) frida(和frida-server) bytecodeviewer radare2(或您选择的其他一些反汇编工具) apktool 如果您需要知道如何安装Frida,请查看Frida文档。对于Frida的使用,您还可以检查本教程的第I部分。我假设你在继续之前拥有上面的工具,并且基本熟悉Frida。另外,确保Frida可以连接到您的设备/模拟器(例如使用frida-ps -U)。我将向您展示各种方法来克服具体的问题,如果您只是寻找一个快速的解决方案,请在本教程末尾查看Frida脚本。 注意:如果使用frida遇到了:Error: access violation accessin...
- 下一篇
D-News|英特尔首推融合现实,亚马逊云服务市场占比超3成
◆◆◆ 业界巨头 亚马逊云服务规模超微软IBM谷歌三家之和 市场研究机构Gartner发布的一份最新报告称,在今年第二季度云基础服务市场上,亚马逊市场份额达到了31%,而微软、IBM、谷歌三家公司的规模仅占23%。亚马逊推出的“基础架构即服务(IaaS)”、“平台即服务(PaaS)”等系列基础云服务,帮助该公司在云服务市场份额不断保持增长,从而确保其自2006年以来一直在该市场保持领先。尽管亚马逊在云服务市场保持绝对领先地位,但包括微软、IBM和谷歌在内的其他竞争对手正在迅速崛起,市场份额增长速度令人印象深刻。数据显示,2016年第二季度整个云基础设施服务市场规模同比增长51%,而且微软和谷歌云服务规模同比增长都在100%以上。 首款专为连接AWS云平台解决方案推出 美国微芯科技公司日前宣布推出业界首款专为连接至亚马逊Amazon We
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Mario游戏-低调大师作品
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8编译安装MySQL8.0.19
- Hadoop3单机部署,实现最简伪集群