news 2026/7/2 18:54:05

Frida Hook入门到精通:动态调试Android App网络请求

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Frida Hook入门到精通:动态调试Android App网络请求

前言

在 Android 逆向分析与安全测试领域,网络请求调试是永恒的核心课题。传统的抓包工具(如 Charles、Fiddler)在面对 SSL 证书绑定、自定义加密协议、底层 Native 网络库时往往束手无策。而 Frida 作为一款强大的动态插桩框架,能够直接注入到 App 进程中,从代码层面拦截和修改网络请求,成为逆向工程师的必备利器。

本文将从环境搭建开始,由浅入深地讲解如何使用 Frida Hook 技术对 Android App 的网络请求进行动态调试,覆盖 HttpURLConnection、OkHttp 等主流网络库,以及 SSL 绕过、请求篡改、加密参数分析等高级实战技巧。


一、环境搭建:从零开始配置 Frida

1.1 Frida 工作原理

Frida 采用 C/S 架构:PC 端作为客户端发送指令,Android 设备上运行 frida-server 作为服务端,二者通过 USB 或 TCP 通信。Frida 利用动态二进制插桩技术,在运行时向目标进程注入 JavaScript 脚本,实现对 Java 层和 Native 层函数的拦截与修改。

1.2 PC 端安装

确保已安装 Python 3.7 + 环境,执行以下命令:

bash

运行

# 安装稳定版本(推荐16.x系列) pip install frida==16.2.1 frida-tools==12.3.0 # 验证安装 frida --version

1.3 Android 端配置

步骤 1:查看设备 CPU 架构

bash

运行

adb shell getprop ro.product.cpu.abi

常见返回值:arm64-v8aarmeabi-v7ax86_64

步骤 2:下载对应版本 frida-server前往 Frida Releases 下载与 PC 端版本一致的 frida-server。例如 arm64 设备下载:frida-server-16.2.1-android-arm64.xz

步骤 3:推送到设备并启动

bash

运行

# 解压后推送到设备 adb push frida-server-16.2.1-android-arm64 /data/local/tmp/frida-server # 赋予执行权限 adb shell chmod 755 /data/local/tmp/frida-server # 后台启动 adb shell "/data/local/tmp/frida-server &"

步骤 4:验证连接

bash

运行

frida-ps -U

成功列出设备进程即表示环境搭建完成。

1.4 两种启动模式

  • Attach 模式:Hook 已运行的进程,适合调试运行中状态

    bash

    运行

    frida -U -n 进程名 -l hook.js
  • Spawn 模式:冷启动 App 并注入,适合 Hook 初始化逻辑

    bash

    运行

    frida -U -f com.example.app -l hook.js --no-pause

二、入门篇:Hook HttpURLConnection

2.1 为什么从 HttpURLConnection 开始

HttpURLConnection 是 Android 系统原生的 HTTP 客户端,位于java.net包下,几乎所有网络库底层最终都会调用它。掌握它的 Hook 方法是网络调试的基础。

2.2 核心 Hook 点

表格

方法作用Hook 时机
connect()建立连接请求发出前
getInputStream()获取响应流响应返回后
getOutputStream()获取请求流POST 数据写入时

2.3 完整 Hook 脚本

javascript

运行

Java.perform(function () { console.log("[*] HttpURLConnection Hook 已启动"); // Hook URL构造,捕获所有请求地址 var URL = Java.use("java.net.URL"); URL.$init.overload('java.lang.String').implementation = function (url) { console.log("[URL] " + url); return this.$init(url); }; // Hook connect方法,获取请求信息 var HttpURLConnection = Java.use("java.net.HttpURLConnection"); HttpURLConnection.connect.implementation = function () { console.log("\n=== 请求发起 ==="); console.log("URL: " + this.getURL().toString()); console.log("Method: " + this.getRequestMethod()); // 打印请求头 var headers = this.getRequestProperties(); console.log("请求头:"); var keys = headers.keySet().toArray(); for (var i = 0; i < keys.length; i++) { var key = keys[i]; console.log(" " + key + ": " + headers.get(key)); } // 打印调用栈,定位代码位置 var stack = Java.use("android.util.Log") .getStackTraceString(Java.use("java.lang.Exception").$new()); console.log("调用栈:\n" + stack); return this.connect(); }; // Hook getInputStream,捕获响应 HttpURLConnection.getInputStream.implementation = function () { var responseCode = this.getResponseCode(); console.log("\n=== 响应返回 ==="); console.log("状态码: " + responseCode); console.log("URL: " + this.getURL().toString()); return this.getInputStream(); }; });

2.4 POST 请求体捕获

对于 POST 请求,请求体写入getOutputStream(),需要通过反射读取输出流内容:

javascript

运行

var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); HttpsURLConnection.getOutputStream.implementation = function () { var os = this.getOutputStream(); console.log("[POST] 准备写入请求体"); // 可通过ByteArrayOutputStream包装来捕获写入内容 return os; };

注意:直接捕获 OutputStream 数据较为复杂,实际项目中更推荐 Hook 更高层的 OkHttp 库来获取请求体。


三、进阶篇:Hook OkHttp 网络库

3.1 OkHttp 的重要地位

OkHttp 是目前 Android 生态中使用最广泛的 HTTP 客户端,Retrofit、Glide 等框架均基于 OkHttp 实现。Hook OkHttp 能够获取最完整、最结构化的请求与响应信息。

3.2 核心 Hook 策略

OkHttp 有多个 Hook 切入点,各有优劣:

表格

Hook 点优点缺点
Request.Builder.build()捕获所有请求构建拿不到响应
CallServerInterceptor.intercept()请求响应都能拿到依赖内部类路径
RealCall.execute()入口级 Hook信息需二次解析

3.3 实战脚本:完整捕获请求与响应

javascript

运行

Java.perform(function () { console.log("[*] OkHttp Hook 已启动"); // ==================== 捕获请求 ==================== var RequestBuilder = Java.use("okhttp3.Request$Builder"); RequestBuilder.build.implementation = function () { var request = this.build(); console.log("\n========== OkHttp 请求 =========="); console.log("URL: " + request.url().toString()); console.log("Method: " + request.method()); // 遍历请求头 console.log("--- Headers ---"); var headers = request.headers(); for (var i = 0; i < headers.size(); i++) { console.log(headers.name(i) + ": " + headers.value(i)); } // 读取请求体 var body = request.body(); if (body !== null) { console.log("--- Request Body ---"); try { var buffer = Java.use("okio.Buffer").$new(); body.writeTo(buffer); console.log(buffer.readUtf8()); } catch (e) { console.log("请求体读取失败: " + e.message); } } return request; }; // ==================== 捕获响应 ==================== var ResponseBuilder = Java.use("okhttp3.Response$Builder"); ResponseBuilder.build.implementation = function () { var response = this.build(); console.log("\n========== OkHttp 响应 =========="); console.log("Code: " + response.code()); console.log("URL: " + response.request().url().toString()); // 响应头 console.log("--- Response Headers ---"); var headers = response.headers(); for (var i = 0; i < headers.size(); i++) { console.log(headers.name(i) + ": " + headers.value(i)); } // 响应体(注意:只能读取一次,需克隆) var body = response.body(); if (body !== null) { try { var source = body.source(); source.request(9223372036854775807); // Long.MAX_VALUE var buffer = source.buffer().clone(); console.log("--- Response Body ---"); console.log(buffer.readUtf8()); } catch (e) { console.log("响应体读取失败: " + e.message); } } return response; }; });

3.4 拦截器层面 Hook(更精准)

对于混淆过的 App,Request$Builder可能被重命名。此时可以 Hook 拦截器接口:

javascript

运行

var CallServerInterceptor = Java.use("okhttp3.internal.http.CallServerInterceptor"); CallServerInterceptor.intercept.implementation = function (chain) { var request = chain.request(); console.log("拦截到请求: " + request.url()); // 可以在这里修改请求 // var newRequest = request.newBuilder().url("新地址").build(); // var response = chain.proceed(newRequest); var response = chain.proceed(request); console.log("响应状态: " + response.code()); return response; };

四、高级篇:SSL 证书绕过与请求篡改

4.1 通用 SSL Pinning 绕过

绝大多数 App 的 SSL 证书绑定都可以通过 Frida 绕过。以下是通用脚本:

javascript

运行

Java.perform(function () { console.log("[*] SSL Pinning 绕过脚本已加载"); // OkHttp 证书绑定绕过 try { var CertificatePinner = Java.use("okhttp3.CertificatePinner"); CertificatePinner.check.overload( 'java.lang.String', 'java.util.List' ).implementation = function () { console.log("[+] 绕过 OkHttp CertificatePinner"); return; }; console.log("[+] OkHttp CertificatePinner 已Hook"); } catch (e) {} // HttpsURLConnection 绕过 try { var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); HttpsURLConnection.setSSLSocketFactory.implementation = function () { console.log("[+] 绕过 HttpsURLConnection SSL"); return; }; } catch (e) {} // 信任所有证书 var TrustManager = Java.use("javax.net.ssl.X509TrustManager"); var SSLContext = Java.use("javax.net.ssl.SSLContext"); // 构造信任所有证书的TrustManager var TrustAllManager = Java.registerClass({ name: "com.example.TrustAllManager", implements: [TrustManager], methods: { checkClientTrusted: function () {}, checkServerTrusted: function () {}, getAcceptedIssuers: function () { return Java.use("java.security.cert.X509Certificate").array.newInstance(0); } } }); console.log("[+] SSL 绕过配置完成"); });

4.2 动态修改请求参数

Hook 不仅可以观察,还可以修改请求数据:

javascript

运行

Java.perform(function () { var RequestBuilder = Java.use("okhttp3.Request$Builder"); RequestBuilder.url.overload('java.lang.String').implementation = function (url) { console.log("[原URL] " + url); // 替换指定接口 if (url.indexOf("/api/login") !== -1) { var newUrl = url.replace("/api/login", "/api/test_login"); console.log("[替换URL] " + newUrl); return this.url(newUrl); } return this.url(url); }; // 修改请求头 RequestBuilder.addHeader.implementation = function (name, value) { if (name === "User-Agent") { value = "Frida-Hooked/1.0"; } return this.addHeader(name, value); }; });

4.3 响应数据篡改

修改服务器返回的数据,常用于绕过服务端校验:

javascript

运行

var ResponseBody = Java.use("okhttp3.ResponseBody"); var BufferedSource = Java.use("okio.BufferedSource"); var Buffer = Java.use("okio.Buffer"); // Hook ResponseBody.create 替换响应体 // 实际使用中建议在拦截器层面替换完整Response对象

五、精通篇:实战技巧与进阶方案

5.1 加密参数分析技巧

当遇到请求参数加密时,按以下步骤定位加密函数:

  1. Hook 请求体输出密文
  2. 打印调用栈找到加密方法所在类
  3. Hook 加密函数,打印明文输入和密文输出
  4. 必要时主动调用加密函数生成自己的密文

示例:Hook 常见加密工具类

javascript

运行

Java.perform(function () { // Hook MD5 var MessageDigest = Java.use("java.security.MessageDigest"); MessageDigest.digest.overload('[B').implementation = function (input) { var data = Java.use("java.lang.String").$new(input); var result = this.digest(input); console.log("[MD5] input: " + data); return result; }; // Hook AES加密 var Cipher = Java.use("javax.crypto.Cipher"); Cipher.doFinal.overload('[B').implementation = function (input) { var opmode = this.getOpMode(); var data = bytesToHex(input); var result = this.doFinal(input); console.log("[AES] mode:" + opmode + " input:" + data); return result; }; }); function bytesToHex(bytes) { var hex = ""; for (var i = 0; i < bytes.length; i++) { var b = bytes[i] & 0xFF; hex += (b < 16 ? "0" : "") + b.toString(16); } return hex; }

5.2 Native 层网络请求 Hook

如果 App 使用 Native 层发起网络请求(如 libcurl、直接调用 socket),需要 Hook Native 函数:

javascript

运行

// Hook send函数(libc.so) Interceptor.attach(Module.findExportByName("libc.so", "send"), { onEnter: function (args) { var fd = args[0].toInt32(); var buf = args[1]; var len = args[2].toInt32(); var data = Memory.readUtf8String(buf, len); console.log("[send] fd=" + fd + " len=" + len); console.log(data.substring(0, 500)); } }); // Hook recv函数 Interceptor.attach(Module.findExportByName("libc.so", "recv"), { onLeave: function (retval) { // 读取接收缓冲区数据 } });

5.3 Frida 反检测与对抗

当 App 检测 Frida 时,可采用以下方案:

  1. 修改 frida-server 二进制名,避免默认端口
  2. 使用 frida-gadget注入到 APK 内部
  3. Hook 检测函数返回假结果
  4. 使用Objection框架集成反检测

基础反检测脚本:

javascript

运行

// 隐藏Frida端口 Interceptor.attach(Module.findExportByName("libc.so", "connect"), { onEnter: function (args) { // 检测27042端口连接并阻断 } }); // 绕过/proc/pid/maps检测 // 绕过frida特征字符串检测

5.4 性能优化与批量 Hook

  • 使用Java.use()缓存类对象,避免重复查找
  • 减少console.log调用,使用批量输出
  • 针对性 Hook,不要全量 Hook 所有方法
  • 复杂逻辑使用 Python 端处理,JS 端只做数据采集

六、常用工具与框架推荐

6.1 Objection

基于 Frida 封装的高级工具,一键完成 SSL 绕过、内存漫游、类搜索等操作:

bash

运行

# 安装 pip install objection # 启动并自动SSL绕过 objection -g com.example.app explore

6.2 r0capture

安卓应用层通杀脚本,支持 HttpURLConnection、OkHttp、Volley 等多种网络库:

bash

运行

frida -U -f com.example.app -l r0capture.js --no-pause

6.3 OkHttpLogger-Frida

专门针对 OkHttp 的日志打印工具,自动适配不同版本 OkHttp,支持混淆识别。


七、常见问题排查

  1. Failed to spawn: unable to find process

    • 检查包名是否正确
    • 确认 frida-server 已启动且版本匹配
    • 尝试使用-D指定设备 ID
  2. Class not found

    • 类可能被混淆,用 jadx 反编译确认类名
    • 检查是否在正确进程中(多进程 App)
    • 使用Java.enumerateLoadedClasses()搜索
  3. Hook 不生效

    • 确认方法签名正确,使用overload指定参数
    • Spawn 模式下冷启动 App 再 Hook
    • 检查是否有加固或脱壳问题
  4. App 闪退

    • 可能触发了反检测机制
    • 检查脚本中是否有空指针异常
    • 逐步注释定位问题代码

八、总结

Frida Hook 网络请求是 Android 逆向分析的核心技能,从简单的 URL 打印到复杂的加密参数分析,再到 Native 层 socket 拦截,技术深度层层递进。掌握本文介绍的 HttpURLConnection 基础 Hook、OkHttp 全链路拦截、SSL 证书绕过、请求响应篡改等技术,足以应对绝大多数 App 的网络调试需求。

学习 Frida 的关键在于实战。建议从简单的 Demo App 入手,逐步尝试 Hook 真实商业应用,在实践中积累对抗经验。同时要持续关注 Frida 官方更新和社区优秀脚本,不断完善自己的工具库。

最后提醒:Frida 技术仅可用于合法的安全测试与学习研究,请勿用于非法用途。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 18:53:15

可信AI智能体开发:技术要点与实战指南

1. 赛事背景与核心价值2026年Nova AI挑战赛由全球顶尖科技企业发起&#xff0c;聚焦可信软件智能体这一前沿技术领域。这项赛事本质上是对下一代智能系统开发者的集中考验——如何构建既强大又可靠的AI助手。作为从业者&#xff0c;我深刻理解当前AI应用落地的最大瓶颈不是技术…

作者头像 李华
网站建设 2026/7/2 18:43:12

移动应用安全测试实战:基于OWASP MASTG的完整工具链与操作指南

1. 项目概述&#xff1a;为什么你需要一本移动安全的“实战手册” 如果你正在开发、测试或负责一款移动应用的安全&#xff0c;那么“OWASP MASTG”这个名字&#xff0c;你大概率已经听过&#xff0c;甚至可能已经对着它那几百页的英文文档发过愁。它被誉为移动应用安全测试的“…

作者头像 李华
网站建设 2026/7/2 18:36:59

工业数字化转型下,工业内窥镜检测的数据管理需求

随着工业数字化的持续推进&#xff0c;工业检测已经不再局限于“看一看、记一下”的目视检查模式&#xff0c;检测数据的归档、追溯、分析&#xff0c;逐渐成为检测工作的重要组成部分。工业内窥镜作为可视化检测设备&#xff0c;其数据管理能力的强弱&#xff0c;直接影响检测…

作者头像 李华
网站建设 2026/7/2 18:34:43

Mythos能力闸门:Anthropic的可编排AI基础设施解析

1. 项目概述&#xff1a;这不是一次普通更新&#xff0c;而是一次能力边界的实质性突破“TAI #200: Anthropic’s Mythos Capability Step Change and Gated Release”这个标题里藏着三个关键信号&#xff1a;TAI&#xff08;The AI Index&#xff09;是业内公认的AI能力演进风…

作者头像 李华
网站建设 2026/7/2 18:34:18

GPT-4稀疏激活原理:1.8万亿参数为何仅用2%计算量

1. 这不是参数堆砌&#xff0c;而是“动态稀疏激活”的工程革命 你可能已经看到过那条刷屏的推文&#xff1a;“GPT-4有1.8万亿参数&#xff0c;但每生成一个token只用其中2%。”——这句话像一道闪电劈开了大模型圈的认知惯性。它背后没有玄学&#xff0c;没有营销话术&#x…

作者头像 李华