
本文聚焦 Android 安全分析场景,系统梳理 Frida 在逆向工程中的三大核心能力。
基于 objection 实现类枚举、实例操作与组件调用,构建运行时对象动态分析能力;深入动态 Hook 技术,涵盖方法定位、重载处理、参数/返回值/调用栈追踪及批量监控框架 ZenTracer,实现无代码侵入的运行时行为捕获;从抓包环境配置到 SSL Pinning 绕过、Socket 通信 Hook,构建多层级流量分析技术链。
全文以技术链路为导向,面向专业工程师提供可落地的 Frida 实战方案。
一、Frida 内存漫游与运行
objection 基础操作与信息枚举
- 命令交互特性:支持空格补全、
help 查看说明、jobs 作业系统管理并发 Hook 任务。
- 基础环境信息:
env 查看应用环境变量,frida-version 查看服务端版本,android sdk 查看 SDK 版本。
- 内存模块枚举:
memory list modules:列出当前进程加载的所有动态库(含 base 地址、大小、路径)。
memory list exports libssl.so:导出指定库的所有导出函数,支持 --json 输出至文件。
- 内存区域转储:
memory dump all:转储整个内存空间(需指定文件)。
memory dump from_base 0x7a000000 0x10000:按地址范围转储。
内存数据提取技术
- 字符串搜索:
memory search --string "password" --offsets-only 定位内存中字符串,常用于密钥、URL 提取。
- 字节模式搜索:
memory search "64 65 78 0a 30 33 35 00" 搜索 Dex 文件头(dex\n035\0),实现脱壳前置。
- 批量内存导出:结合 Python 脚本,遍历内存区域自动筛选并保存包含特定特征的数据块。
堆对象操作与动态执行
- 堆实例搜索:
android heap search instances com.android.settings.DisplaySettings
返回所有存活实例的句柄及 toString() 信息。支持 --fresh 强制重新搜索。
- 实例方法调用:
android heap execute 0x2526 getPreferenceScreenResId 直接调用实例方法并打印返回值。
android heap evaluate 0x2526 进入迷你 JS 编辑器,以 clazz 变量访问实例,可执行任意 Frida 代码。
- 动态脚本执行:在已定位实例上即时编写调试逻辑,无需重新注入,显著提升逆向效率。
组件生命周期控制
- Activity 调起:
android intent launch_activity com.android.settings.DisplaySettings 直接启动目标 Activity,绕过界面层级。
- Service 启动:先通过
android hooking list services 枚举所有 Service,再使用 android intent launch_service <service_name> 启动。
- Intent 泛用性:支持携带 extra 参数,可用于自动化测试中的组件触发。
二、动态 Hook 与方法追踪
类与方法枚举技术
- 全量类枚举:
android hooking list classes 列出内存中所有已加载类(通常超万级),支持导出。
- 类名模糊搜索:
android hooking search classes display 快速定位目标类(如包含 “display” 的类)。
- 方法列表查询:
android hooking list class_methods com.android.settings.DisplaySettings 输出类中所有方法签名,包含修饰符、返回值、参数类型。
- 方法搜索:
android hooking search methods display 跨类搜索所有方法名包含关键词的方法(耗时较长,谨慎使用)。
Hook 代码自动生成与重载处理
- 生成 Hook 模板:
android hooking generate simple com.android.settings.DisplaySettings
自动生成 Java.perform 包裹的 Hook 代码框架,针对每个方法生成 implementation 占位。
- 精确重载指定:当方法存在多个重载时,可在
watch class_method 后追加参数类型列表(如 "java.lang.String,int")实现精准 Hook。
- 构造函数 Hook:使用
$init 标识构造方法,android hooking watch class_method java.io.File.$init --dump-args 可监控所有实例化过程。
运行时参数、返回值与调用栈追踪
批量 Hook 框架:ZenTracer
- 工作原理:通过正则表达式匹配类名,自动 Hook 匹配类的所有方法,将调用关系以树形结构展示。
- 配置方法:
- 匹配模式:
E:java.io.File 精准匹配类;M:java.io.File 模糊匹配(含子类、相关类)。
- 过滤模式:排除不需要的类(如
Black RegEx 输入 E:java.io.FileOutputStream)。
- 数据导出:可导出为 JSON 文件,包含完整调用树、参数、返回值,便于离线分析。
- 局限性与扩展:不支持构造函数 Hook,无调用栈打印,但可通过修改源码自行添加。
三、Frida 辅助网络抓包与协议分析
抓包环境配置与对抗
- 应用层抓包(HTTP/HTTPS):
- 推荐工具:BurpSuite(支持客户端证书)、Charles(易用)。
- 流量转发:手机安装 Postern 开启 VPN,连接 PC 的 SOCKS5 代理(Charles/Burp 需开启 SOCKS5 服务)。
- 高版本安卓证书安装:root 后将用户证书移至
/system/etc/security/cacerts,修改权限为 644。
- 会话层抓包(Socket):
- 接口转储:Hook
send/recv(Native)或 OutputStream.write(Java)。
- 驱动转储:tcpdump + Wireshark 分析。
- 路由转储:自制 Kali 热点,所有流量经笔记本网卡,实现全量抓包(应用无法检测 VPN)。
- VPN 检测绕过:
System.getProperty("http.proxyHost") 等 API 可检测系统代理,需 Hook 返回空值或原值。
HTTP/HTTPS 抓包原理与 Bypass 技术
- HTTPS 中间人原理:Charles/Burp 作为中间代理,与客户端建立 TLS 连接,再与服务器建立另一条连接。客户端验证的证书是代理证书,需将代理证书导入手机系统根目录。
- 证书校验绕过场景:
- 仅校验服务器证书:导入代理证书即可。
- SSL Pinning(证书绑定):客户端代码中额外校验证书指纹或公钥,需 Hook 校验函数。
- 抓包失败分析:若导入证书后仍报错,说明存在 SSL Pinning;若某些域名显示
CONNECT 且无数据,可能为 Socket 通信。
SSL Pinning 绕过完整方案
- 基础 Hook 方案:Hook
checkServerTrusted 方法,清空其实现。
var Platform = Java.use("com.android.org.conscrypt.Platform");
Platform.checkServerTrusted.overloads.forEach(function(overload){
overload.implementation=function(){/* 空实现 */};
});
- objection 一键绕过:
android sslpinning disable,内部集成对常见框架(okhttp、WebView、Apache HttpClient、TrustKit 等)的 Hook。
- 高级补充脚本:
ObjectionUnpinningPlus 扩展了对 SSLContext、XUtils、network_security_config(Android 7.0+)等场景的支持。
- 自定义框架处理:若加固厂商自研 SSL 库,需通过动态分析定位校验点,通常 Hook 其验证方法或直接修改验证逻辑。
Socket 通信抓包与数据提取
- Java 层 Socket Hook:
- 定位
java.net.Socket 的 getInputStream/getOutputStream,获取 SocketInputStream 和 SocketOutputStream。
- Hook
write(byte[]) 和 read(byte[]) 转储二进制数据。
- 若数据加密,需进一步分析加解密算法(常与 Java 层或 Native 层配合)。
- Native 层 Socket Hook:
- Hook
send、recv、sendto、recvfrom 等 libc 函数。
- 通过
Interceptor.attach 获取参数(fd、buf、len),输出 hexdump。
- 注意处理多线程环境,需根据 fd 区分连接。
- 数据还原:
- 若为自定义二进制协议,需逆向解析结构;若为 ProtoBuf 等序列化框架,可先 dump 原始字节再离线解析。
- 使用
tcpdump 抓取 PCAP 文件,用 Wireshark 分析,配合 Follow TCP Stream 功能重组会话。
四、实战教程
延迟 Hook 机制
在带壳环境下,类加载与方法注册存在时序依赖,需采用两种延迟策略确保 Hook 生效:
- 进程级延迟:去掉
frida --no-pause 参数,使进程启动后暂停。进入 CLI 后手动调用 %resume 恢复执行,给予足够时间完成 Hook 注入。
- 方法级延迟:在 js 中使用
setTimeout(func, delay),针对 JNI_OnLoad 或 Application.onCreate 等关键节点设置 500–2000ms 延迟,避免 Hook 时机早于方法注册。
脱壳工具依赖前置
主流脱壳工具需先绕过反调试才能正常工作:
- Frida-Dexdump:基于内存特征扫描,依赖 Frida 稳定注入。
- FART:通过主动调用链实现函数体还原,同样需先绕过检测。
反调试绕过技术链路
以某加固应用为例,完整绕过流程如下:
识别检测线程来源
- 监控动态库加载:Hook
android_dlopen_ext 记录所有加载的 so。
var dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
Interceptor.attach(dlopen_ext, {
onEnter:function(args){
var path = ptr(args[0]).readCString();
console.log("load " + path);
}
});
观察发现 libexec.so 和 libsotweak.so 为可疑检测模块。
- 定位检测线程:Hook
pthread_create 打印线程函数所在模块及偏移。
Interceptor.attach(Module.findExportByName(null, "pthread_create"), {
onEnter:function(args){
var threadFunc = args[2];
var module = Process.findModuleByAddress(threadFunc);
if(module){
var offset = threadFunc.sub(module.base);
console.log(`pthread_create from ${module.name} offset 0x${offset.toString(16)}`);
}
}
});
输出显示 libsotweak.so 加载后立即创建 4 个线程(偏移 0x45f44、0x469e8、0x497c4、0x49e8c),随后进程终止。
处理延迟加载模块
libexec.so 存在延迟加载,需动态监控其加载时机:
function hook_dlopen(){
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onLeave:function(retval){
if(this.path && this.path.includes("libexec.so")){
setupPthreadHook(); // 延迟安装 pthread_create hook
}
}
});
}
const interval = setInterval(()=>{
if(Process.findModuleByName("libexec.so")){
clearInterval(interval);
setupPthreadHook();
}
}, 100);
阻断检测线程
获取检测线程偏移后,在 pthread_create hook 中直接拦截:
const targetOffsets = [0x45f44, 0x469e8, 0x497c4, 0x49e8c];
Interceptor.replace(pthread_create_addr, new NativeCallback(function(parg0, parg1, parg2, parg3){
const module = Process.findModuleByAddress(parg2);
if(module && module.name === "libsotweak.so"){
const offset = ptr(parg2).sub(module.base);
if(targetOffsets.includes(offset.toInt32())){
console.log(`Blocking anti-debug thread at offset 0x${offset.toString(16)}`);
return 0; // 阻止线程创建
}
}
return original_pthread_create(parg0, parg1, parg2, parg3);
}, "int", ["pointer", "pointer", "pointer", "pointer"]));
绕过完整性校验
部分加固会检测 pthread_create 是否被 hook,可采用 函数替换 技术:
- 获取原始
pthread_create 函数指针
- 构造自定义 NativeCallback,内部调用原始函数
- 通过
Interceptor.replace 完成替换,使上层调用者仍认为调用的是 libc 中的原始函数
内存提取技术:mprotect Hook
当检测线程由延迟加载的 libexec.bin 等嵌入式库创建时,可前置 Hook mprotect:
Interceptor.attach(Module.findExportByName(null, "mprotect"), {
onLeave:function(retval){
if(retval.toInt32()===0){
Memory.protect(this.addr, this.size, "rwx"); // 强制设为可读写执行
// 扫描 dex 特征并 dump
if(containsDexMagic(this.addr)){
dumpMemory(this.addr, this.size);
}
}
}
});
此方法可在检测线程启动前捕获解密后的代码段,但需后续手动分析提取完整 dex。
综合反绕过脚本架构
完整绕过脚本需集成以下模块:
- 环境准备:
setImmediate 确保脚本优先执行
- 系统调用拦截:Hook
exit、_exit、abort、kill、ptrace 等防止进程退出
- 文件访问重定向:Hook
fopen 将对 /proc、/sys 的访问重定向到 /dev/null
- 时间戳篡改:Hook
gettimeofday、clock_gettime 返回伪造时间
- 动态库监控:Hook
dlopen、android_dlopen_ext 实时检测加固库加载
- 线程创建控制:Hook
pthread_create 阻断已知检测线程
- 符号解析监控:Hook
dlsym 防止获取敏感函数(如 ptrace)
- Java 层延迟 Hook:通过
setTimeout 结合 Java.perform 在应用启动后注入
- 异常处理:
Process.setExceptionHandler 捕获并抑制异常
脱壳与验证
成功绕过反调试后,执行内存扫描 dump dex:
function dumpDex(){
const dexMagic = "6465780a30333500"; // dex\n035\0
Process.enumerateRanges('r--').forEach(range=>{
Memory.scan(range.base, range.size, dexMagic, {
onMatch:function(address, size){
const dexSize = address.add(0x20).readU32();
const dexData = address.readByteArray(dexSize);
const file = new File(`/data/data/com.xxx.xxx/classes_${address}.dex`, "wb");
file.write(dexData);
file.close();
}
});
});
}
dump 出的 dex 可通过 jadx 直接反编译,获得完整业务代码。
技术链路总结
注入失败 → Hook dlopen 监控 → 发现 libsotweak.so → Hook pthread_create → 获取检测线程偏移 → 阻断线程创建 → 绕过完整性校验 → Hook mprotect 辅助提取 → 成功注入 → 内存扫描 dex → dump 完整代码
五、总结
本文以 Frida 为技术载体,构建了覆盖 Android 安全分析全流程的实战框架。
整体可归纳为四个技术维度:
- 信息收集层
通过 objection 等工具实现无代码的运行时数据采集,包括内存模块枚举、堆实例定位、类/方法搜索、组件调起等。该层为后续精准 Hook 提供目标定位,是逆向工程的起点。
- 行为观测层
利用 Frida 的动态插桩能力,对目标方法实施参数、返回值、调用栈的实时捕获,并通过 ZenTracer 等工具实现批量方法监控。该层解决了混淆代码定位、重载识别等难题,实现对应用行为的深度观测。
- 协议分析层
集成抓包环境配置、SSL Pinning 多场景绕过(覆盖 okhttp、WebView、TrustKit 等框架)以及 Socket 通信的双层 Hook(Java 层 OutputStream/InputStream,Native 层 send/recv),形成从应用层到会话层的完整流量分析链。
- 对抗突破层
针对加固与反调试,系统呈现了从识别检测线程、动态监控库加载、阻断线程创建、绕过完整性校验到内存提取的全链路对抗技术。核心方法包括 Hook dlopen 定位检测模块、替换 pthread_create 阻止恶意线程、Hook mprotect 捕获解密代码段等。
核心方法论
Frida 的真正价值在于将移动端与 PC 端的计算能力协同,构建 “采集→分析→干预→突破” 的自动化闭环。对于安全工程师而言,掌握这套从信息收集到深度对抗的完整技术链,意味着在面对各类加固手段时,具备从“被动适应”转向“主动控制”的系统化能力。更多的逆向工程与渗透测试实践,欢迎在云栈社区交流探讨。