目录
  1. 1. 一、加固原理概述
  2. 2. 二、检测加固类型
  3. 3. 三、内存 DEX 脱壳
    1. 3.1. 方法一:Frida Dump
    2. 3.2. 方法二:DumpDex 工具
    3. 3.3. 方法三:Objection
  4. 4. 四、对抗反调试
  5. 5. 五、对抗 APK 签名校验
  6. 6. 六、处理 Multi-DEX 应用
  7. 7. 面试常考问题
【逆向安全技术-实战篇】逆向加固应用

一、加固原理概述

Android 应用加固(壳)的核心思路:将原始 DEX 文件加密后打包进 APK,类加载时由壳代码动态解密 DEX,并通过自定义 ClassLoader 加载到 ART 虚拟机中。常见加固厂商包括:腾讯乐固、360 加固保、梆梆安全、阿里聚安全等。

加固层次分为:DEX 整体加密DEX 方法抽取DEX 指令虚拟化(VMP),难度依次递增。

二、检测加固类型

# 1. 解包 APK,观察结构
apktool d target.apk -o unpacked
ls unpacked/lib/armeabi-v7a/

# 常见特征文件:
# libtup.so → 腾讯乐固
# libjiagu.so → 360 加固
# libSecShell.so → 梆梆安全
# libDexHelper.so → 顶象安全
# 2. 检查 classes.dex 大小
# 如果 classes.dex 只有几十 KB,大概率是壳的 DEX
ls -la target/classes.dex

# 3. 查看 Manifest,壳通常会添加自己的组件
grep -r "StubShell\|StubApp\|Wrapper" unpacked/AndroidManifest.xml

三、内存 DEX 脱壳

加固的 DEX 最终必须加载到内存才能执行。利用此特点,在运行时从内存中 Dump 解密后的 DEX。

方法一:Frida Dump

// frida_dex_dump.js — attach 后自动 dump 所有已加载的 DEX
Java.perform(function() {
var dex_class = Java.use("dalvik.system.DexFile");
dex_class.$init.overload('java.lang.String').implementation = function(path) {
console.log("[+] Dex loaded: " + path);
return this.$init(path);
};
});
frida -U -f com.target.app -l frida_dex_dump.js --no-pause

方法二:DumpDex 工具

将设备 root 后,使用 DumpDex(https://github.com/WrBug/dumpDex)通过 Hook ClassLoader.loadClass 获取所有已加载的类,逐一 dump 出 DEX。

方法三:Objection

objection -g com.target.app explore
# 在 objection 终端中
android hooking list classes
android heap search instances dalvik.system.DexFile

四、对抗反调试

加固应用通常会检测调试状态:

# /proc/self/status 中的 TracerPid 为非 0 表示正在被调试
adb shell cat /proc/$(adb shell pidof com.target.app)/status | grep TracerPid

对抗 ptrace 反调试的方法:

// Frida 脚本:Hook ptrace 调用
Interceptor.attach(Module.findExportByName("libc.so", "ptrace"), {
onEnter: function(args) {
// 检查是否是反调试检测
if (args[0].toInt32() == 0) { // PTRACE_TRACEME
console.log("[*] ptrace(PTRACE_TRACEME) called, bypassing...");
}
},
onLeave: function(retval) {
retval.replace(0); // 返回 0 表示成功,绕过检测
}
});

对抗 TracerPid 检测:直接 patch /proc/self/status 的读取结果,或使用 MagiskHide 隐藏调试状态。

五、对抗 APK 签名校验

加固应用常调用 PackageManager.getPackageInfo() 校验 APK 签名:

// Frida Hook 签名校验
var pkgMgr = Java.use("android.content.pm.PackageManager");
pkgMgr.getPackageInfo.implementation = function(pkg, flags) {
console.log("[*] getPackageInfo called for: " + pkg);
// 返回原始签名信息,绕过校验
return this.getPackageInfo(pkg, flags);
};

六、处理 Multi-DEX 应用

加固后的应用通常包含多个 DEX:

# JADX 打开所有 DEX
jadx-gui classes.dex classes2.dex classes3.dex

# 将 DEX 合并
java -jar dx.jar --dex --output=merged.dex *.dex

面试常考问题

Q1:Frida 脱壳的原理是什么?被检测到怎么办?
A:Frida 脱壳利用应用运行时 DEX 已在内存中解密的特点,通过 Hook ClassLoader 或直接遍历内存将 DEX dump 出来。被检测的对抗措施:使用 Frida 的 anti-detection 脚本(frida-antidetect)、修改 Frida 进程名、使用定制版 Frida Server(如 hluda-server)绕过端口检测和 D-Bus 扫描。

Q2:什么是 VMP(虚拟化保护)?如何分析?
A:VMP 将 DEX 字节码转换为自定义的虚拟机指令,运行时由壳自带的解释器执行。传统反编译工具无法还原。分析需要逆向壳本身的虚拟机解释器,理解其指令编码格式,编写专用的反汇编器。常见思路:利用 trace 工具记录指令执行序列,结合符号执行推导原始逻辑。

Q3:加固应用如何做 so 层分析?
A:先用工具(如 Frida 的 dlopen Hook)确认 so 文件被加载到哪个内存地址,然后使用 IDA Pro 的 attach 功能进行动态调试。对于加密的 so,可以通过 /proc/pid/maps 查看内存布局后,用 dd 命令从内存中 dump 解密后的 so。

打赏
  • 微信
  • 支付宝

评论