加固
app面临的威胁
App主要面临的威胁有,反编译,二次打包,动态调试,hook等
为什么需要加固
加固是为了保护APK不被别人逆向分析,保护程序核心代码
加壳概念
加壳通常是对dex文件进行加密存储,在程序运行的时候由可程序将dex文件解密到执行
-
dex
由apktool等工具可以轻易的逆向得出代码
- 通过壳程序对dex加密
-
将加密的dex放入apk得到加密apk
当使用apktool逆向时,不能得到或得到很少量的代码。并且那可能只是壳程序的代码
- 最后在运行时,壳程序会最先运行,然后对dex进行解密
四个发展阶段
-
一代壳:dex动态加密
对dex整体加密,加密之后放在apk的目录中。一些简单的加固程序,可能只是对dex文件进行了一些修改(例如修改文件后缀名,或是修改dex文件的头信息)
可以对壳文件进行修复后逆向
壳程序在运行的时候,会将完整的dex程序释放到内存中。那么在内存中是完整的、解密的。所以可以对内存扣取,将内存中的dex文件进行拷贝
-
二代壳:代码抽取
将dex文件的一些函数,提取出来放入so文件中。相对于smali、java代码来说,so文件的逆向是比较有难度的。
但二代壳在运行时依旧会在内存释放出完整、解密的dex文件,所以依旧可以通过内存dump把内存中的dex文件提取出来
-
三代壳:动态解密
同样将java中的一些代码进行本地化,写入so文件中。但是相对二代壳,三代壳只有在函数调用的时候才释放到内存中,那么内存中的dex文件就是不完整的。
针对三代壳呢,一般是通过hook框架,对apk中的所有函数进行调用。那么他的所有函数都会释放到内存中。也就可以对内存进行dump操作了。
-
四代壳:VMP虚拟机加密
解决了以上三代壳所有弊端
使用虚拟机对指令进行加密。类似自行实现了一个dalvik虚拟机,对dex进行加密后,只有它自己的虚拟机可以对程序进行解密运行。常用的apktool工具反编译出来也不认识这个代码。
代码混淆
-
名称混淆
将类名、函数名替换成随机的字符串
逆向时,常通过函数名来找到关键功能。而对类名和函数名进行随机替换后,能增大逆向工作者阅读代码的难度。
-
逻辑混淆
打乱代码执行流程,增加逆向人员分析程序的难度
简单的程序逆向后可以轻松分辨其功能,而逻辑混淆会增加大量代码,较难从中分析出有用的代码。
反调试
-
java层反调试
逆向工程师可以通过jdb调试工具对apk进行java代码调试
为了防止apk被调试
AndroidMainfest.xml, Android:debuggable=false/true
绕过这种反调试只需要修改false/true即可
- so层反调试
很多核心功能写在so中,所以需要对so进行反调试
Ptrace防护:
通过对父进程进行附加(附加一个子进程),这样ida就无法对父进程进行附加了。
双ida,一个ida附加子进程,这时候子进程就处于暂停状态,所以就失效了。可以使用另一个ida附加父进程
三向抱死
子进程 附加 父进程
子子进程 附加 子进程
父进程 附加 子子进程
需要修改安卓的fork源码,使得附加失效(无法创建子进程)。这样ida就可以对父进程进行附加
-
tacePID反调试
通过检查TracePid的值是否为0来判断当前进程是否被调试
可以通过使用ida的debug的单步调试,找到判断tracePid的代码位置,然后修改tracePid为零从而绕过该反调试。
反注入
程序在运行时会加载自身所以来的so文件,注入就是让程序加载我们自己的so文件。判断是否被注入,如果被注入,程序就结束。