软件神器 --- hook之王 frida
Frida 是一款强大的动态代码插桩工具(Dynamic Instrumentation Toolkit),允许通过 JavaScript 注入到目标进程,实时修改、监控和分析应用程序行为。其核心功能覆盖逆向工程、安全测试、漏洞挖掘、自动化分析等场景。以下是 Frida 功能的详细分类列举:
总得来讲就是
-
实时函数 Hook
-
内存数据读写
-
动态修改应用逻辑
1.寄生进程。自己的代码注入到目标进程中使用js脚本语言进行运行时自定义控制。
2.函数监事与替换:在 App 调用某个关键函数时,当个“中间人”,能监视、甚至修改它传入的参数和返回的结果。通过监听关键函数实现,甚至可以实现。文件系统监控:监视这个 App 都读了或写了手机里的哪些文件。禁用证书绑定使得抓包软件可以抓取https数据进行安全分析。绕过 Root/Jailbreak 检测。流量拦截,即使通讯是加密。比绕过root检测更近一步。直接Hook获取设备信息的函数(如Build.Serial, Build.MODEL,android_id,IMEI等),返回我自定义的虚假信息,保护个人隐私数据让App以为运行在另一台完全不同的设备上。
3.内存读写与查找:直接翻看或修改这个 App 内存里记着的数据。甚至可以实现 动态修改DEX/ELF文件 在内存中直接修补Android的DEX字节码或原生库的机器码。这比简单的函数Hook更底层,可以实现更彻底的功能修改,比如永久性地跳过一个检查逻辑。
4.强迫app调用一个内部原生函数并告诉我结果。
5.动态代码执行:让 App 临时执行一段我塞给它的新指令。
6.枚举模块与导出函数:把这个 App 都加载了哪些“技能包”(插件/库)以及包里都有哪些“技能”(函数)全都列表给我看。
7.线程控制:把这个 App 里干活的每个“工人”(线程)叫停或者让他继续干活。
8.堆栈回溯:当 App 执行到某处时,查它的“族谱”,看它是从哪一步一步步调过来的。
9.持久化注入:把这针(脚本)打成“疫苗”,让 App 每次一启动就自动带上我的命令。
10.代码追踪与分析 (Stalker),不是只监听一个函数调用,而是给App的一小段代码“戴上一个贴身记录仪”,把它执行的每一条指令(比如CPU执行的每一个步骤)都详细记录下来,生成一份极其详细的“行动报告”,用于深度分析复杂算法或混淆代码的执行流程。
11.进程间通信 (RPC - Remote Procedure Call) 让我写在App里的JS脚本“变身”成一个小服务端。我电脑上的Python程序可以直接“远程调用”这个服务端里的函数,让它返回数据或者执行任务。这样我就不用一直把结果console.log出来再手动复制了,可以实现全自动化分析。
12.崩溃收集与分析 给目标App装一个“黑匣子”。当App因为各种原因(比如我Hook出错或者它本身的Bug)突然崩溃时,这个黑匣子会自动触发,把崩溃那一刻的内存、寄存器状态、调用栈等所有信息都保存下来发给我,方便我定位问题。
13.模拟用户操作 (仅限Android) 虽然这不是Frida的核心API,但通过Frida调用Android的Java API,可以模拟点击、滑动、输入等操作,实现“机器人”式的自动化测试或UI交互,无需root权限。
一、核心功能:代码注入与运行时控制
-
进程注入
-
支持注入到 本地进程(Windows/macOS/Linux)、移动端(Android/iOS)、模拟器 和 IoT 设备。
-
注入方式:
frida-trace
,frida CLI
, Python/Node.js API,或直接嵌入到应用。
-
-
跨平台支持
-
目标系统:Windows, Linux, macOS, Android, iOS, QNX, FreeBSD。
-
架构兼容:x86, x64, ARM, ARM64, MIPS。
-
-
多语言运行时绑定
-
通过 JavaScript 编写注入脚本(核心)。
-
支持 TypeScript(需编译为 JS)。
-
通过 Python, C#, Node.js, Swift 等控制脚本执行。
-
二、动态代码插桩(Hooking)
-
函数级 Hook
-
拦截任意函数调用(包括系统 API、第三方库、自定义函数)。
-
修改参数/返回值:动态篡改输入输出。
Interceptor.attach(targetFunction, { onEnter: function(args) { args[0] = ptr(0x1000); // 修改参数 }, onLeave: function(retval) { retval.replace(0); // 修改返回值 } });
-
-
内存读写
-
读取/修改任意内存地址:
let buffer = Memory.readByteArray(ptr(0x1000), 4); Memory.writeUtf8String(ptr(0x2000), "Hacked!");
-
-
内存扫描与模式匹配
-
搜索特征码、字符串、整数等:
Memory.scan(module.base, module.size, "41 B8 ? ? ? ?", { onMatch: (address) => console.log("Found at:", address) });
-
三、运行时操作
-
调用原生函数
-
直接调用目标进程中的函数:
let func = new NativeFunction(ptr(0x1234), 'int', ['int']); let result = func(42);
-
-
动态代码执行
-
注入并执行 Shellcode:
const code = Memory.allocUtf8String("mov x0, #0x42; ret"); const func = new NativeFunction(code, 'int', []); func();
-
-
对象操作(Android/iOS)
-
Android (Java):Hook Java 方法、枚举类、实例化对象:
Java.perform(() => { let TextView = Java.use("android.widget.TextView"); TextView.setText.implementation = (text) => { this.setText("Hijacked: " + text); }; });
-
iOS (Objective-C/Swift):Hook OC 方法、调用 Swift 函数:
ObjC.classes.NSString.stringWithString_("Frida Rocks!");
-
四、进程与模块分析
-
枚举模块与导出函数
Process.enumerateModules().forEach(module => { console.log(module.name, module.base); module.enumerateExports().forEach(exp => console.log(exp.name)); });
-
线程控制
-
枚举线程、挂起/恢复、注入线程上下文。
-
-
堆栈回溯(Stack Trace)
-
实时捕获函数调用栈:
Thread.backtrace(this.context, Backtracer.ACCURATE);
-
五、网络与加密监控
-
SSL/TLS 解密
-
Hook OpenSSL/BoringSSL/NSS 等库,捕获明文:
Interceptor.attach(ssl_read_ptr, { onEnter: logBuffer });
-
HTTP(S) 流量拦截
-
Hook 网络库(如 Android 的
OkHttp
, iOS 的NSURLSession
):OkHttpClient.onRequest = (request) => { console.log("Request to:", request.url()); };
六、反调试与绕过
-
绕过 Root/Jailbreak 检测
-
Hook 检测函数(如 Android 的
checkSuExists()
),强制返回false
。
-
禁用证书绑定(SSL Pinning)
-
Hook 证书验证函数(如
checkServerTrusted()
),直接跳过验证。
-
对抗反调试机制
-
Patch
ptrace
(Linux/Android)、sysctl
(macOS/iOS) 等反调试函数。
七、工具链与集成
-
命令行工具
-
frida
:REPL 交互环境。 -
frida-trace
:快速追踪函数调用(如frida-trace -i "open*" com.app.xxx
)。 -
frida-ps
:列出设备进程。
-
开发者 API
-
支持 Python, Node.js, C 等编写控制脚本:
import frida device = frida.get_usb_device() session = device.attach("com.app.target") script = session.create_script(open("script.js").read()) script.load()
-
可视化工具集成
-
Frida CodeShare:共享社区脚本。
-
Objection(基于 Frida):自动化移动端安全测试。
-
r2frida:与 Radare2/Ghidra 集成。
八、高级特性
-
持久化注入
-
注入到
init
(Android)或launchd
(iOS)实现开机自启。
-
-
远程设备管理
-
通过
frida-linux-server
等连接远程设备。
-
-
性能分析
-
使用
Stalker
追踪代码执行路径,生成 CPU 剖面图:Stalker.follow({ events: { compile: true }, onReceive: (events) => { /* 分析指令流 */ } });
-
-
文件系统监控
-
Hook 文件操作函数(
open
,read
,write
)记录敏感访问。
-
二、环境准备
1. 安装 Frida
# 安装 Python 环境 (推荐 Python 3.8+)
pip install frida-tools frida
2. 下载 Frida-Server (以 Android 为例)
-
查看设备 CPU 架构:
adb shell getprop ro.product.cpu.abi # 输出示例:arm64-v8a
-
在 Frida Releases 下载对应版本的
frida-server-xx.x.x-android-xx.xz
-
推送并运行:
adb push frida-server /data/local/tmp/ adb shell "chmod 755 /data/local/tmp/frida-server" adb shell "/data/local/tmp/frida-server &"
3. 验证安装
frida-ps -U # 查看 USB 连接的设备进程列表
# 成功则显示设备上的进程列表
三、第一个 Frida 脚本
目标:Hook Android 的 java.lang.String
构造函数
创建脚本 hook_string.js
:
Java.perform(() => {
// 获取 String 类
const StringClass = Java.use("java.lang.String");
// Hook 构造函数
StringClass.$init.overload("[B").implementation = function (bytes) {
console.log("创建字符串: " + this.toString());
return this.$init(bytes); // 调用原方法
};
});
执行脚本:
frida -U -l hook_string.js -f com.example.app --no-pause
-
-U
: 使用 USB 设备 -
-l
: 加载脚本 -
-f
: 启动应用并注入 -
--no-pause
: 立即启动进程
四、核心 API 详解
1. 基础结构
Java.perform(() => {
// 所有 Java 相关操作必须在此回调中
});
2. Hook 方法
const Activity = Java.use("android.app.Activity");
Activity.onCreate.implementation = function (bundle) {
console.log("Activity 被创建!");
this.onCreate(bundle); // 调用原方法
};
3. 调用静态方法
const System = Java.use("java.lang.System");
System.exit.implementation = function (code) {
console.log("阻止退出: " + code);
}; // 不调用原方法,阻止退出
4. 修改方法返回值
const Math = Java.use("java.lang.Math");
Math.random.implementation = function () {
return 0.5; // 永远返回 0.5
};
5. 创建新对象
const String = Java.use("java.lang.String");
const newStr = String.$new("Hello Frida!"); // 等价于 new String("...")
6. 动态调用实例方法
Java.choose("android.view.View", {
onMatch: function (instance) {
instance.setBackgroundColor(0xFFFF0000); // 将所有 View 背景设为红色
},
onComplete: () => console.log("搜索完成")
});
五、实战案例:破解登录验证
假设目标应用有登录逻辑:
public boolean checkPassword(String input) {
return input.equals("SECRET_PASSWORD");
}
Hook 脚本 bypass_login.js
:
Java.perform(() => {
const LoginClass = Java.use("com.example.app.LoginManager");
LoginClass.checkPassword.implementation = function (input) {
console.log("原始输入: " + input);
// 修改返回值,始终返回 true
return true;
};
});
执行:
frida -U -l bypass_login.js -n "App Name"
六、进阶技巧
-
批量 Hook 所有重载方法
TargetClass.targetMethod.overloads.forEach(overload => {
overload.implementation = function () {
console.log(`调用 ${this} 的方法`);
return this.targetMethod.apply(this, arguments);
};
});
-
拦截系统加密函数
const Cipher = Java.use("javax.crypto.Cipher");
Cipher.doFinal.overload("[B").implementation = function (data) {
const result = this.doFinal(data);
console.log("加密数据: " + bytesToHex(result));
return result;
};
-
内存操作
const base = Module.findBaseAddress("libtarget.so");
const offset = 0x1234;
const ptr = base.add(offset);
Memory.writeUtf8String(ptr, "HACKED"); // 修改内存字符串
七、调试与排错
-
查看堆栈
console.log(Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Exception").$new()
));
-
错误处理
try {
riskyCode();
} catch (e) {
console.log("错误: " + e.message);
}
-
日志输出到文件
frida -U -l script.js -o log.txt
八、学习资源
-
Frida CodeShare - 共享脚本库
-
《逆向工程核心原理》 - Frida 实战章节