27、加固与脱壳:360加固、腾讯加固、Frida脱壳技术
说实话,做移动安全这些年,我遇到最多的问题就是:“这App加壳了,怎么搞?”
加固,说白了就是给APK穿上一件防弹衣。厂商把Dex文件加密藏起来,运行时再解密加载。你直接反编译?看到的全是垃圾代码。我早期做渗透测试时,第一次碰到360加固,反编译出来全是空壳,当时真有点懵。
但别怕,有壳就能脱。今天咱们就聊聊主流的360加固、腾讯加固,以及怎么用Frida这把手术刀把它们剥开。
加固的本质:藏与骗
加固的核心思路其实很简单:
- 隐藏Dex:把真正的classes.dex加密或抽空,塞到so文件里或资源文件中。
- 动态加载:App启动时,壳的so库先跑起来,解密Dex,再用自定义ClassLoader加载。
- 反调试:检测调试器、Frida、Xposed,一旦发现就闪退或篡改逻辑。
你想想看,壳就像个看门大爷,你得先搞定他,才能进到屋里翻东西。
核心知识点:无论什么加固,最终都要在内存中还原出完整的Dex。我们脱壳,就是抓住它“解密后、运行前”的那个瞬间。
360加固:老牌选手
360加固在国内市场占有率很高。它的特点是:
- Dex被加密后放在libjiagu.so的特定段里。
- 运行时通过自定义的ArtMethod解释执行,甚至对代码进行VMP(虚拟机保护)。
- 有很强的反Frida检测,比如轮询/proc/self/maps。
我在项目中遇到过360加固的VMP版本,那真是硬骨头。普通的内存dump根本拿不到完整Dex,因为代码是一边解释一边执行的。
我的经验:对付360加固,早期版本可以用Frida的脚本直接hook libjiagu.so的入口点,在Dex被解密后dump内存。但新版本(尤其是VMP)需要结合定制Frida或Unicorn模拟执行。别指望一招鲜,得灵活应变。
腾讯加固:后来居上
腾讯加固(乐固)现在也很常见。它的特点:
- 使用自己的壳so库libshell.so或libtup.so。
- Dex被分割成多个块,分散在so文件的不同节区。
- 运行时通过hook系统函数(如mmap、dlopen)来拦截Dex加载。
- 对Frida的检测更隐蔽,比如检测端口27042,或者检测Frida的特定字符串。
我记得有一次,腾讯加固的App在调试器里跑得好好的,一上Frida就闪退。查了半天,发现它检测了frida-server的默认端口。改个端口号就绕过去了——有时候问题就这么简单。
注意:腾讯加固的某些版本会校验Dex的完整性。你dump出来之后,如果直接修改再打包,运行时会校验失败。所以脱壳后,通常还需要修复Dex的checksum和签名。
Frida脱壳:手术刀怎么用
Frida是我最常用的动态插桩工具。脱壳的核心思路是:在Dex被加载到内存后,立即把它dump出来。
具体怎么做?我习惯用下面这个经典脚本:
// frida_dexdump.js
function dumpDex() {
var dexAddr = Module.findBaseAddress("libart.so");
if (dexAddr) {
// 遍历ClassLinker中的DexCache
var dexCache = ... // 具体偏移需要根据Android版本调整
var dexFile = dexCache.getDexFile();
var size = dexFile.getSize();
var data = dexFile.getData();
// 写入文件
var file = new File("/sdcard/dump.dex", "wb");
file.write(data);
file.flush();
file.close();
console.log("Dex dumped to /sdcard/dump.dex");
}
}
setTimeout(dumpDex, 5000); // 等5秒,让壳完成解密
嗯,这里要注意:不同Android版本的libart.so内部结构不一样。Android 8.0和10.0的DexCache偏移就完全不同。我建议你用frida-dexdump这个开源工具,它已经适配了主流版本。
避坑指南:我曾经在Android 9上跑脚本,死活dump不出完整Dex。后来发现是壳在解密后,又把Dex的某些部分给抹掉了。解决办法是hook DexFile的构造函数,在它刚创建时就dump,别等它初始化完成。
脱壳后的修复:别高兴太早
Dump出Dex只是第一步。很多时候,dump出来的文件是损坏的,需要修复:
- 修复Header:Dex文件头部的checksum、signature可能被篡改。
- 修复StringTable:某些加固会把字符串索引打乱。
- 修复ClassDef:类定义表可能被压缩或加密。
我常用的修复工具是DexFixer和JEB。JEB的自动修复功能很强大,能处理大部分加固的Dex损坏问题。
知识体系:一张图看懂
下面这张图,是我自己总结的加固与脱壳的核心流程。你看完应该能明白整个攻防逻辑:
实战中的几个坑
脱壳这事儿,纸上谈兵容易,真上手全是坑。我列几个常见的:
- 反调试闪退:壳检测到Frida就自杀。解决办法是用Frida的spawn模式,或者用定制版Frida(比如frida-gumjs)。
- Dump不完整:只dump到了部分Dex。这时候需要hook DexFile的构造函数,或者用frida-dexdump的深度模式。
- 修复失败:Dump出来的Dex用工具修复不了。我遇到过一种情况,壳把Dex的string_ids和type_ids顺序打乱了,需要手动根据引用关系重建。
重要提醒:脱壳技术本身是中性的。但请务必只在合法授权的应用上使用。我见过有人因为脱壳分析竞品App,最后吃了官司。技术是刀,怎么用看你自己。
好了,关于加固与脱壳,今天就聊到这儿。360和腾讯的壳虽然难搞,但核心思路不变:找到解密点,抓住时机dump。Frida就是你的手术刀,多练练,手感就来了。