移动安全-Frida脱壳脚本与加固迭代
众所周知,Android应用开发完成后,除了使用Google官方的混淆外,还需要使用一些第三方的安全软件的加壳处理,比较出名的有腾讯乐固、360加固和爱加密等。我之前所在的公司,就是使用爱加密进行加壳处理的。虽然加密后,让软件的安全性更高了,但并不是无懈可击,一些反加固技术和脱壳技术应运而生。今天要说的就是腾讯乐固、360加固一键脱壳。经过加固后的apk,通过dex2jar反编译效果是下面这样的:
前言
随着移动互联网和智能手机的普及,加之移动应用体验的不断提升,各类 APP 迅速覆盖了人们日常出行、购物娱乐、金融理财等各个领域,一边是移动应用带来的方便快捷的生活,一边是系统漏洞、病毒木马、山寨 APP 带来的隐私侵犯,现如今 APP 安全备受争议。
加固迭代
移动应用加固的主要从技术层面对 DEX 文件、SO 文件、资源文件等进行保护。为应对不断出现的新型黑客攻击手段,Android 加固技术也经历了代码混淆保护技术、Dex 整体加密保护技术、Dex 函数抽取加密保护技术、混合加密保护技术、虚拟机保护技术等五代技术更新与迭代。
代码混淆保护
Android 平台采用使用 Java 作为原生语言进行开发,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,需要对 Java 字节码进行混淆,比较常见的代码混淆有 proguard 和 dexguard,其中包括了名称混淆、字符串加密、反射替换、日志清除、花指令等。
第一代加固保护技术的优缺点:
- 优点:代码混淆保护技术在保护效果上增加了逆向成本,一定程度上保护了程序的逻辑;
- 缺点:保护强度有限,无法对抗静态分析、动态调试,同时与反射调用冲突。
Dex整体加密
DEX 整体加密保护技术是基于类加载的方式来实现的,整个加壳的过程涉及到三个程序:源程序,加壳程序,解壳程序。基本原理是对 Dex 文件进行整体加密后存放在 APK 的资源中,运行时将加密后的 Dex 文件在内存中解密,并让 Dalvik 虚拟机动态加载执行。
第二代加固保护技术的优缺点:
- 优点:DEX 文件整体加固的目的是增加静态分析的难度,可以有效对抗静态分析、二次打包;
- 缺点:无法完全对抗动态调试、内存 dump、自动化脱壳工具、定制化虚拟机等攻击方式。
Dex函数抽取
第三代保护技术——Dex 函数抽取加密保护技术
针对 DEX 文件整体加固可以被内存 Dump 的弱点,第三代保护技术对代码中的每个方法抽出并进行单独加密,基本原理是利用 Java 虚拟机执行方法的机制来实现。利用这个机制将解密操作延迟到某个方法在执行之前才开始加载该方法的代码,同时解密后的代码在内存是不连续存放的。例如通过抽取 Dalvik 虚拟机运行一个 DEX 必不可缺少 DEXCode 中的部分,然后对字节码指令添加 nop,这种方式极大的提高了代码安全性。
DEX 函数抽取加密保护技术的执行流程如下:
- 打包时,将原 APK 中的所有方法的代码提取出来,单独加密到一个文件;
- 运行时,加固引擎首先会动态修改当前进程 Dalvik 虚拟机,初始化动态解密的虚拟机适配层;
- 当 Dalvik 虚拟机要执行某个方法时,加固引擎才解密该方法的代码,并将解密后的代码交给虚拟机执行引擎执行。
第三代加固保护技术的优缺点:
- 优点:加密粒度变小,加密技术从 Dex 文件级变为方法级;按需解密,解密操作延迟到某类方法被执行前,如果方法不被执行,则不被解密;解密后的代码在内存不连续,克服了内存被 Dump 的缺点,有效保护了移动客户端的 Java 代码。
- 缺点:DEX 函数抽取加密技术本质上也是一种代码隐藏技术,最终代码还是通过 Dalvik 或者 ART 虚拟机进行执行,因此破解者可以构建一个自己修改过的虚拟机来脱壳,且第三代保护技术无法保护所有方法,控制权获取较晚,集成其他保护功能困难,这需要寻求更加强大、安全的防逆向技术来保证 APK 的安全。
Dex混合加密
Dex 混淆加密主要是为了隐藏 dex 文件中关键的代码,力度从轻到重包括:静态变量的隐藏、函数的重复定义、函数的隐藏、以及整个类的隐藏。混淆后的 dex 文件依旧可以通过 dex2jar、jade 等工具反编译成 Java 源码,但是里面关键的代码已经看不到了。
第四代加固保护技术的优缺点:
- 优点:相比于前几代加固技术,第四代加固技术加密强度有了很大的提高,能够对抗大部分定制化脱壳机,安全性和兼容性达到了比较好的平衡;
- 缺点:无法完全对抗基于方法重组的脱壳机,存在被破解的风险。
VPM保护技术
VMP(虚拟机) 保护技术是当下最前沿移动应用安全加固技术,虚拟机软件保护技术是被动型软件保护技术的分支,具体来说是添加有意义的混淆代码的一种变型使用。根据应用层级不同,基本可分为硬件抽象层虚拟机、操作系统层虚拟机和软件应用层虚拟机。用于保护软件安全的虚拟机属于软件应用层虚拟机,是对被保护的目标程序的核心代码进行“编译”,这里被编译的不是源文件,而是二进制文件,将由编译器生成的本机代码(Native code)转换成效果等价的 byte-code,然后为软件添加虚拟机解释引擎。用户最终使用软件时,虚拟机解释引擎会读取 byte-code,并进行解释执行,从而实现用户体验完全一致的执行效果。
一套高质量的自定义指令集和解释器是判断 VMP 技术真伪的唯一标准。目前国内多数厂商都推出了移动应用 VMP 保护技术,经研究多采用的是代码抽取和隐藏、代码混淆等技术,大多数技术方案并不成熟,有的方案甚至和 VMP 的核心思想有本质上的区别。
Frida 脱壳
Android 应用开发完成后,为了防止反编译和逆向分析,经常会使用一些第三方的安全软件的加壳处理,比较出名的有腾讯乐固、360 加固、梆梆加固和爱加密等。经过加固后的 APK,通过 dex2jar 反编译后是看不到 APP 源码的,比如腾讯乐固加壳的 APP:
再比如 360 加固的 APP:
简单的加壳程序演示:
壳的种类非常多,依据上面介绍的 Android 加固技术的演变,可以将 APK 加壳简单划分为以下三代:
加壳技术 | 技术特点 | 脱壳难度 |
---|---|---|
第一代:DEX 整体加密型壳 | 采用 Dex 整体加密,动态加载运行的机制 | 较容易被还原,通过自动化脱壳工具或脚本即可从内存中 dump 出 dex 文件 |
第二代:DEX 函数抽取型壳 | 粒度更细,将方法单独抽取出来,加密保存,解密执行 | 可以从根本上进行还原的,dump 出所有的运行时的方法体,填充到 dump 下来的 dex 中去的,这也是 fart 的核心原理 |
第三代:VMP、Dex2C 壳 | 独立虚拟机解释执行、语义等价语法迁移,强度最高 | Dex2C 目前是没有办法还原的,只能跟踪进行分析; VMP 虚拟机解释执行保护的是映射表,只要心思细、功夫深,是可以将映射表还原的 |
Dexdump脚本
从上面可以看到,APP 加固发展到现在已经好几代了,从整体加固到代码抽取再到虚拟机保护,加固和脱壳的方案也逐渐趋于稳定。随着保护越来越强,脱壳机们也变得越来越费劲,繁琐。但是毕竟道高一尺,魔高一丈,市面上有很多手段可以进行脱壳操作,下文将介绍的是使用 Frida 的一个脚本来从内存中 Dump 已加壳 APK 的 Dex。
Github 项目地址:FRIDA-DEXDump(作者:葫芦娃)。
脚本原理
得益于 Frida,在 PC 上面进行内存搜索、转储都变得十分方便,再也不需要考虑什么 Xposed、什么 Android 开发、什么代码注入,只需要关注如何去搜索想要的东西,于是依赖一个几十行代码的小脚本,就可以将大部分内存中的 dex 脱下来。对于完整的 dex,采用暴力搜索 dex035
即可找到。而对于抹头的 dex,通过匹配一些特征来找到。
【More】FRIDA-DEXDump 脚本的原理深入分析可以参考作者葫芦娃的文章:深入 FRIDA-DEXDump 中的矛与盾 ;或者另一位大佬的源码解读:安卓逆向:某录屏软件脱壳重打包,附对几种frida脱壳脚本的分析。
手机银行APP
下面以某手机银行 APP 为例进行脚本脱壳示范:
1、首先使用 jadx-gui 反编译查看该已加固的 APK,可以看到已经无法读到 APP 源码:
2、运行模拟器 Frida 服务端并转发端口,随后即可执行脚本python main.py
并打开目标 APP,程序将自动识别目标 APP 进程并从内存中 Dump 出其原始的 Dex 文件:
3、此时再使用 jadx 反编译查看 Dump 下来的 Dex 文件,就可以看到目标 APP 的源码了:
航旅纵横APP
1、使用查壳工具进行加壳情况的检测:
2、使用 jadx 反编译已加固 APK:
3、Frida DexDump 脚本一键脱壳:
4、最后使用 jadx 反编译并查看 dump 下来的 Dex 文件:
【More案例】
1、对抖音短视频 APP 进行脱壳也成功了:
2、对某腾讯加固的 APP 进行脱壳也成功了:
脱壳前反编译:
一键脱壳:
脱壳后查看源码:
失败案例APP
以上所演示的案例可以看到, Frida Dexdump 脱壳脚本对使用第一代壳(Dex 整体加密型)进行加固的 APP 来说,脱壳效果很好,但是对于第二代壳( Dex 函数抽取型壳)则效果不明显,脱壳后的 dex 文件中函数体为空,下面找个实例演示下。
1、查看一下已加固 APK 反编译后的代码:
2、查壳工具检测发现是梆梆企业版的壳:
3、使用 Frida Dexdump 脚本尝试一键脱壳:
4、反编译查看 Dump 下来的 dex 文件,发现函数均为空,无法读到有效源码:
对于函数抽取型的壳,fart 可以解决,寒冰大佬也是写出了 frida-fart,frida 版的 fart,安卓版本目前只适配于 Android 8.0,后续会持续学习到 fart 和 frida-fart 在安卓脱壳中的使用。
More
关于脱壳后的源码实战分析案例:
最后再附上两篇进阶资源文章:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)