共计 1929 个字符,预计需要花费 5 分钟才能阅读完成。
在 Android 逆向工程中,理解函数调用关系是分析复杂业务逻辑和定位关键算法的核心能力。无论是破解加密算法、分析协议流程,还是挖掘漏洞,都需要快速准确地追踪函数调用链。本文将从工具选择、实战技巧到自动化处理,带新手系统掌握这一关键技能。

一、静态与动态分析工具对比
1. 静态分析工具
- JADX:
- 优势:可视化的调用树生成(右键方法→Find Usage),支持导出 Gradle 项目
-
局限:无法处理动态加载的 DEX,对混淆代码可读性差
-
Ghidra:
- 优势:支持 Native 层分析,数据流跟踪功能强大
- 局限:学习曲线陡峭,Android 专项支持较弱
2. 动态分析工具
- Frida:
- 优势:无需重启 APP,支持 JS/Python 脚本热更新
-
典型场景:运行时修改参数、动态构造调用链
-
Xposed:
- 优势:系统级 Hook 稳定性高
- 局限:需要刷机或模拟器支持
二、JADX 静态分析实战
- 基础操作流程:
- 拖入 APK 文件自动反编译
- 搜索目标类名 / 方法名(Ctrl+F)
-
右键方法选择 ”Find Usage” 查看调用层级
-
调用树导出技巧:
- 使用 ”Save All” 导出完整工程
-
在 Android Studio 中查看更完整的引用关系
-
混淆代码处理:
- 观察字符串常量池定位关键方法
- 结合
adb logcat过滤日志关键词
三、Frida 动态追踪方案
1. 基本 Hook 脚本
// 拦截特定类方法
Interceptor.attach(Module.findExportByName(null, "target_function"), {onEnter: function(args) {console.log(`[+] Called with args: ${args[0]}, ${args[1]}`);
this.startTime = Date.now();},
onLeave: function(retval) {console.log(`[-] Returned: ${retval} (took ${Date.now() - this.startTime}ms)`);
}
});
2. 多线程处理
// 添加线程标识
Interceptor.attach(targetMethod, {onEnter: function(args) {this.threadId = Process.getCurrentThreadId();
console.log(`[TID-${this.threadId}] Enter`);
}
});
3. 参数深度解析
// 解析复杂参数结构
onEnter: function(args) {const env = Java.vm.getEnv();
const jstr = args[1];
console.log(env.getStringUtfChars(jstr, null).readCString());
}
四、Python 自动化分析
import frida
import sys
# 连接设备
device = frida.get_usb_device()
# 加载脚本
with open("trace.js") as f:
script = device.attach("com.target.app").create_script(f.read())
# 处理回调
def on_message(message, data):
if message['type'] == 'send':
print(f"[LOG] {message['payload']}")
script.on('message', on_message)
script.load()
sys.stdin.read()
五、避坑指南
1. 反调试对抗
-
延迟注入:
setTimeout(function() { // 在 APP 启动后 5 秒注入 interceptCriticalMethods();}, 5000); -
检测绕过:
// 修改 TracePid 值 const fake_status = "Name:\ttarget_app\nTracerPid:\t0"; Memory.writeUtf8String(ptr(status_addr), fake_status);
2. 性能优化
-
过滤高频方法:
if (this.callCount++ > 1000) return; -
使用 CModule 加速:
const fastFilter = new NativeCallback(ptr("0x1234"), 'bool', ['pointer']);
六、进阶思考
- 如何追踪 JNI 调用的 Native 层函数链?
- 在 ART 虚拟机下如何解析动态代理方法的调用关系?
- 怎样实现跨进程的 RPC 调用追踪?
掌握函数调用追踪技术后,建议尝试将这些方法组合使用:先用静态分析建立整体认知,再通过动态 Hook 验证关键路径。随着经验积累,你会逐渐形成自己的逆向分析方法论。
正文完
