Frida简介
什么是Frida
Frida是一个动态代码分析工具包,主要用于:
- 动态Hook应用程序
- 实时修改程序行为
- 分析应用程序逻辑
- 绕过安全检测
核心特点
- 跨平台:支持Windows、macOS、Linux、Android、iOS
- 多语言:支持JavaScript、Python、C等
- 易上手:简单的API设计,学习成本低
- 功能强大:可以Hook几乎所有系统调用和API
Frida工作原理
基本架构
1 2 3
| 目标应用 ←→ Frida Server ←→ Frida Client ←→ 你的脚本 ↓ 注入进程 → Hook函数 → 修改行为 → 返回结果
|
Hook机制
1 2 3 4 5
| 1. 注入Frida Agent到目标进程 2. 定位目标函数地址 3. 替换函数入口点 4. 执行自定义逻辑 5. 调用原函数或返回自定义值
|
Frida安装配置
1. 安装Frida
1 2 3 4 5
| pip install frida-tools
frida --version
|
2. Android环境配置
1 2 3 4 5 6 7 8 9
|
adb push frida-server /data/local/tmp/ adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &
|
3. 连接设备
1 2 3 4 5 6 7 8 9 10
| import frida
device = frida.get_usb_device() print(f"设备: {device}")
processes = device.enumerate_processes() for process in processes: print(f"进程: {process.name} (PID: {process.pid})")
|
基础Hook示例
1. Hook Java方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Java.perform(function() { var String = Java.use("java.lang.String"); String.equals.implementation = function(obj) { console.log("String.equals被调用"); console.log("参数: " + obj); var result = this.equals(obj); console.log("返回值: " + result); return result; }; });
|
2. Hook Native函数
1 2 3 4 5 6 7 8 9 10 11 12 13
| var libc = Module.findExportByName("libc.so", "strlen"); if (libc) { Interceptor.attach(libc, { onEnter: function(args) { console.log("strlen被调用"); console.log("参数: " + Memory.readUtf8String(args[0])); }, onLeave: function(retval) { console.log("返回值: " + retval); } }); }
|
3. Hook系统调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var openat = Module.findExportByName("libc.so", "openat"); if (openat) { Interceptor.attach(openat, { onEnter: function(args) { var path = Memory.readUtf8String(args[1]); console.log("打开文件: " + path); if (path.includes("su")) { console.log("隐藏su文件访问"); args[1] = Memory.allocUtf8String("/dev/null"); } } }); }
|
实用Hook技巧
1. 绕过Root检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| Java.perform(function() { var File = Java.use("java.io.File"); File.exists.implementation = function() { var path = this.getAbsolutePath(); console.log("检查文件: " + path); if (path.includes("su") || path.includes("magisk")) { console.log("隐藏Root文件: " + path); return false; } return this.exists(); }; var SystemProperties = Java.use("android.os.SystemProperties"); SystemProperties.get.overload("java.lang.String", "java.lang.String").implementation = function(key, def) { console.log("获取属性: " + key); if (key === "ro.debuggable") { return "0"; } if (key === "ro.secure") { return "1"; } return this.get(key, def); }; });
|
2. 绕过SSL Pinning
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Java.perform(function() { var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager"); X509TrustManager.checkClientTrusted.implementation = function(chain, authType) { console.log("绕过客户端证书检查"); }; X509TrustManager.checkServerTrusted.implementation = function(chain, authType) { console.log("绕过服务端证书检查"); }; X509TrustManager.getAcceptedIssuers.implementation = function() { return Java.use("java.util.ArrayList").$new(); }; });
|
3. 监控网络请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Java.perform(function() { var OkHttpClient = Java.use("okhttp3.OkHttpClient"); var Request = Java.use("okhttp3.Request"); var RequestBuilder = Java.use("okhttp3.Request$Builder"); RequestBuilder.build.implementation = function() { var request = this.build(); var url = request.url().toString(); console.log("HTTP请求: " + url); return request; }; });
|
进阶Hook技术
1. 动态类加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Java.perform(function() { Java.choose("com.example.TargetClass", { onMatch: function(instance) { console.log("找到目标实例: " + instance); instance.targetMethod.implementation = function() { console.log("目标方法被调用"); return this.targetMethod(); }; }, onComplete: function() { console.log("搜索完成"); } }); });
|
2. 内存操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Java.perform(function() { var baseAddr = Module.getBaseAddress("libtarget.so"); var value = Memory.readU32(baseAddr.add(0x1000)); console.log("内存值: " + value); Memory.writeU32(baseAddr.add(0x1000), 0x12345678); var buffer = Memory.alloc(1024); Memory.writeUtf8String(buffer, "Hello Frida"); });
|
3. 函数替换
1 2 3 4 5 6 7 8 9 10 11 12
| var targetFunc = Module.findExportByName("libtarget.so", "target_function"); if (targetFunc) { Interceptor.replace(targetFunc, new NativeCallback(function(arg1, arg2) { console.log("替换函数被调用"); console.log("参数1: " + arg1); console.log("参数2: " + arg2); return 0x12345678; }, 'int', ['int', 'int'])); }
|
常用命令
1. 基础命令
1 2 3 4 5 6 7 8 9 10 11
| frida-ls-devices
frida-ps -U
frida -U -f com.example.app -l script.js
frida -U -f com.example.app -l script.js --no-pause
|
2. 高级命令
1 2 3 4 5 6 7 8
| frida-trace -U -i "*open*" com.example.app
frida-trace -U -j "*" com.example.app
frida -U com.example.app -e "console.log(Module.enumerateExports('libc.so'))"
|
结语
这篇文章主要是讲解了官方版本的Frida,另外还有一些第三方魔改的基于一定特性修改的版本这里就不展开了,有兴趣的可以自行去翻阅一下,或者后面讲一篇关于自定义自己的frida该怎么做。
本文关键要点:
- 基本原理:进程注入 + 函数Hook
- 核心功能:动态修改程序行为
- 应用场景:安全研究、逆向分析、漏洞挖掘