dpt-shell: 函数抽取原理解析
dpt-shell 如何将 DEX 函数抽取为加密的壳代码,使逆向工程变得极其困难。
dpt-shell 是一种函数抽取型加固。它不把方法体留在 classes.dex 里,而是把真正的方法体抽空,移到一份加密负载中,只在运行时才还原。逆向者用 jadx 打开 APK 时,看到的方法只剩一个 nop 空壳,因为实际逻辑从来不在磁盘上的 DEX 文件里。
还原由壳 ClassLoader 配合 JNI 桥完成。应用启动时,壳加载 native 库,读取加密负载,解密方法体,并把它补回正在运行的类。整个过程在内存中进行,所以静态 dump 只能拿到空壳。
安全模式是 Standard 与 Enhanced 档的默认选择。它传入 --disable-anti-debug 与 --disable-frida-detect,关掉内置的调试器和 Frida 检测,但保留抽取本身。它刻意不用 -vs,因为该参数启用运行时签名校验,会与最后一步重签名冲突导致构建崩溃;也不用 -S,那是更激进的优化,部分应用扛不住。
最常见的崩溃是 UnsatisfiedLinkError: No implementation found for JniBridge.ia()。它发生在构建排除了 x86 与 x86_64 ABI 的设备上。壳按当前运行的 vmInstructionSet 查找 native 库,发现 assets/vwwwwwvwww/x86_64/ 下没有 .so,解压失败,System.load 在任何一个方法还原之前就抛异常。
修复方法简单却反直觉:不要排除 x86 与 x86_64。哪怕真实用户全在 ARM,也要为每种 ABI 都带上库。代价只是几百 KB 体积,远比在每台模拟器、Chrome OS 设备和 Intel 安卓平板上直接崩溃来得便宜。
函数抽取很强,但有代价:它会增大包体,带来首次加载的一次性还原开销,并把应用绑定到特定的 native ABI 布局。把它当作整套防护中的一层,与资源混淆、RASP 叠加,这样即便壳被绕过,其余保护仍然有效。