APP攻防之博弈历程

1、APK结构分析

我们用 file 命令 aaa.apk 的包就会发现,其就是一个zip的文件格式,unzip解压后你会发现两者的文件结构基本相似都存在androidmanifest.xml和res,都是作应用程序的清单文件,描述应用程序的基本特性。

两者的 res 文件下都存着资源相关文件。不同的是 APK 文件解压多出了个classes.dex 文件,这个dex文件就是安卓的虚拟机的可执行文件,在一个APK中所有的dex文件存着APK整体业务逻辑的核心,APK解压后还有一个resources.res 文件该文件是用于资源文件相关文件,还有一个META-INF文件夹用于存放APP的签名文件。

2、APP攻防技术的发展

安卓还没普及时,安卓安全无人问津,随着安卓平台的流行,对其破解的需求也就增大,在2009年随着smali工具将dex反编译成smali语言的工具,以及baksmali工具将dex文件反编译成dex 的二进制文件,安卓安全正式起步。

因为安卓时运行在Dalvik或ART虚拟机当中, 于ARM汇编语言类似, 而smali语言可以当作安卓的虚拟机的汇编语言。

2010年卡巴斯基安全公司拦截到了第一种安卓病毒,同年apktool 反编译神器出现并开源,其标志着安卓逆向开始加速发展,之后几年基于apktoll的逆向工具层次不穷,例如:andorguard、jadx、jeb 都是基于apktool的进一步优化。

早期要逆向app只要使用apktool反编译后几乎于源码一摸一样,只要在加点耐心研究代码即可完成破解工具。

针对破解开发人员也利用的各种手段反击,例如:代码混淆增加阅阅读的困难度比如谷歌自带的混淆工具proguard,就是把变量 函数 类 名等变成毫无意义的 a b c 这样毫无意义的名,另一个是压缩文件,于proguard 相比还有个dexguard 混淆软件他在混淆基础上加了字符串混淆 ,花指令、资源加密、运行库加密等,不过时商业收费的。

除此之外还有动态加载方案,就是将需要保护的文件单独编译成一个二进制文件,将其加密保存在一个外部的二进制的文件中,在外部文件运行的过程中再将加密的二进制文件解密使用classloader 类 加载器来动态加载和运行被保护代码,因为java中的每一个类都是由classloader 类加载器进行动态加载和运行的。

再比如安卓的java文件代码容易被破解所以将核心代码使用NDK套件中,NDK可以让开发者使用c/c++进行开发实现应用的各个部分,这样java 代码只充当一个二进制文件装载器的角色,实际业务都被放在了更难破解的so文件中,这时jadx 、jeb 等静态工具就不太够用了,这时动态的分析方式就成了分析的主流,所谓动态分析就是附加调试或者进入进程来进行分析,不管是使用android studio或者是deb 对App的dex进行动态调试,亦或者是IDA GDB 等对native 调试对so 文件的动态调试,包括hook和trace 都是动态分析的一种方式。

所以在动态分析,不关是加载后的函数中设置断点以便dump 出被保护的代码,还在在内存中进行搜索以便根据特征找到真实dex文件并且dump出都能很轻松的应对这种保护方式。

另外针对静态分析要看很多无意义的代码,动态分析起来肯定更加高效,因为动态分析是基于进程所处的状态分析所以得到的都是你所需要信息地方的真实数据。

在动态分析的过程中,需要将调试器附加上进程或者通过注入将指令或者代码注入到目标进程,然后才能对目标进行调试和内存监控,要做到这一步最基本的方式就是利用ptrace函数对进程进行附加,活着基于二次打包的方式对程序进行修改重新打包。

ok 问题又来了如果用ptrace 进程附加那么,那么肯定就会有相应的特征点,比如/proc/pid/status 文件中的tracepid在变量被附加后会从0 变成进程id , 如果开一个线程对pid进程循环检测那么就会强制让你退出,阻止你调试程序。

adb shell

su

ps -e | grep android_server64

ps -ef | grep 包名

cat /proc/pid/status

还可以根据调试器在附加手机上时需要运行server端进行通信配合这点,通过检测进程中是否存在server 服务名称进行检测,或者根据server和调试器之间需要通行对其监听端口进行检测,这中手段不仅对ida有效对Frida同样有效。

除此之外外可以通过指令的执行时间差,进行判断保护,除此之外还可以预先防护,最经典的就是双进程保护利用一个进程只允许一个ptrace附加的特性,事先自己hook一个prtace变相阻止其他进程进入

当然仅对种种反调试,逆向也不敢示弱利用检测代码都是运行在程序中着特性,在对APP运行之前先避开这些检测,例如在程序还未证真运行起来之前就附加到进程中,或者手动绕过这些检测再重新打包。

这里就涉及包APP加固问题了,也是最难饶过的问题,所谓加固逻辑上和上面说的动态加载类似,就是用动态厂商的壳包裹住真实APP,在真正运行时通过壳程序在释放出来,历年来大家把加固历程分为了3个阶段。

第一个阶段:

对APP的整体dex代码加固,其原理就是将dex加密后动态加载,加固文件需要先进行解密并且解密后的内容被写到另外一个文件,解密后利用dexclassloade类或者其他加载函数来加载文件,由于文件操作套过于明显,之后就在内存中进行解密和加固,这样虽然是没有的文件操作但是只要在内存中搜索以dex3的文件头或者在dex加载函数上设置断点就可以利用hook找到解密数据,后来为了阻止还隐去了内存中头部名称还是无法阻止动态的内存调试,整体dex代码加固弊端就在于,对全部dex整体加固一旦破解,整体代码就完整的展现。

第二个阶段:

代码抽取保护,就是真正的代码没有和dex整体架构存储在一起,就算dex内容被dump出也无法看到真正的函数代码,被dump出的代码关键处会没有展示 是 nop 原理时通过私有函数对自身进行HOOK拦截函数被调用时的路径,在真正的函数被调用之前先一步把无用的代码塞到对应的代码块中,由于这样做会对资源消耗不小,所以一般只是对关键性的代码块进行操作进行抽取保护,也就是因为性能问题通常是关键性函数加载过一次后就不再重新进行,这样就可以把运行中的app多触发几次代码还是会在内存中,然后再dump出来,比如 dexhunter 工具 其原理就是主动的加载dex中的所有类然后再dump出所有方法和代码,经过代码重构在填回到dex文件中,为了对抗其 dexhunter 有的代码抽取方案在类加载时并不恢复函数的代码,而是将时机在进行延后处理,所以就又引出了 fupk3和fart 这样的工具,原理时对执行函数的入口处进行插装,并且在入口函数出判断是否有主动调用的标志,若属于主动调用则dump出相应的函数内容在进行重构,针对这类脱壳方案加固厂商也出了对应方案,比如对app添加一个垃圾类,一但检测到垃圾类被dump出就退出程序运行,或者是监控文件读写的方法,一但监控到dex035的文件内容被dump出就杀死进程,虽然有这些监控但是目前来讲指标标不治本,只要事先监控脱壳流程把垃圾类排除再重新进行脱壳就可以,所以第三代阶段开始了。

第三个阶段:

vmp和dex2c

vmp一个重要的特点就是将所有java层代码最终都变成native层代码,两者不同的地方在于vmp技术源于最早的pc虚拟机加固技术,核心逻辑就是将所有代码使用自定义的解释器执行,这时代码不再依赖于系统本身,即使所获的了所有代码内容也不知道如何操作,唯一的方法可能就是逆向到对应的解释器,找到于系统解释器的映射关系。

dex2c则是通过编译原理将java代码转换成native层代码,这所以这样是因为native层的二进制代码相比java更不容易被逆向,这虽然难一些但是如果懂一些c/c++语言也还是可以做到的。

以上都了解到,不管是反调试、hook、加固、都是通过native层完成的,所以为了进一步保护native层代码,就出现了ollvm 编译器,对代码进行混淆,比如控制流平坦化、虚假控制流、以及指令替换,这些将原本简单的if else 变得相当的冗余过长造成资源上的浪费和性能的损耗。

在Linux系统中,进程状态除了我们所熟知的TASK_RUNNING,TASK_INTERRUPTIBLE,TASK_STOPPED等,还有一个TASK_TRACED。这表明这个进程处于什么状态?

strace可以方便的帮助我们记录进程所执行的系统调用,它是如何跟踪到进程执行的?

gdb是我们调试程序的利器,可以设置断点,单步跟踪程序。它的实现原理又是什么?

所有这一切的背后都隐藏着Linux所提供的一个强大的系统调用ptrace().

ptrace系统调用

ptrace系统调从名字上看是用于进程跟踪的,它提供了父进程可以观察和控制其子进程执行的能力,并允许父进程检查和替换子进程的内核镜像(包括寄存器)的值。其基本原理是: 当使用了ptrace跟踪后,所有发送给被跟踪的子进程的信号(除了SIGKILL),都会被转发给父进程,而子进程则会被阻塞,这时子进程的状态就会被系统标注为TASK_TRACED。而父进程收到信号后,就可以对停止下来的子进程进行检查和修改,然后让子进程继续运行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值