当前位置:首页>安卓APP>安卓 App 抓包实战指南:从基础原理到内核级对抗

安卓 App 抓包实战指南:从基础原理到内核级对抗

  • 2026-03-24 10:03:33
安卓 App 抓包实战指南:从基础原理到内核级对抗

阅读提示:本文面向有一定 Android 开发基础或安全研究背景的读者,采用"原理 + 实操 + 攻防对抗"的三层结构撰写。建议按章节顺序阅读;如已熟悉基础知识,可直接跳至第六章开始阅读攻防部分。


摘要

本文系统梳理了 Android 应用抓包的完整知识体系,覆盖从入门到内核级对抗的全链路。

你能从本文学到什么:

  • 理解 HTTPS/TLS 握手、数字证书与 MITM 代理的底层原理,建立坚实的理论基础;
  • 掌握 Reqable、Charles、Burp Suite、r0capture、eCapture 等主流工具的使用场景与选型决策;
  • 彻底搞清 Android 7 / Android 14 系统证书信任机制的演变,以及对应的证书安装方案;
  • 深入理解代理检测、VPN 检测、SSL Pinning、双向认证(mTLS)四大反抓包防御的实现原理;
  • 掌握 Frida Hook、OkHttpLogger、r0capture、eBPF uprobe 等多维度绕过方案,附可直接使用的脚本;
  • 通过一个完整的加密接口逆向实战案例,串联抓包、静态逆向、动态 Hook、脚本重放的全流程。

目录

  • 一、引言:为什么抓包越来越难?
  • 二、必备前置知识:抓包的理论地基
  • 三、工具库:按场景选择合适的工具
  • 四、核心分水岭:Android 系统版本与证书信任策略
  • 五、基础抓包实操:以 Reqable 为例的完整流程
  • 六、魔高一尺:App 反抓包防御策略详解
  • 七、道高一丈:反抓包对抗手段(攻击侧全策略)
  • 八、底层降维打击:Hook 抓包与混淆对抗
  • 九、内核级终极方案:eBPF + eCapture
  • 十、加密协议实战:从抓包到还原加解密逻辑
  • 十一、总结与排查速查 SOP
  • 工具与资源汇总

一、引言:为什么抓包越来越难?

1.1 抓包的核心价值

"抓包"对于移动端开发者和安全研究者而言,是一项基础但极其强大的技术手段。理解 App 与服务端之间的通信,几乎是所有逆向分析工作的起点。具体来说,抓包能解决这些问题:

  • 接口逆向分析:还原影视解析网站、第三方数据 API 的真实请求格式,为自建服务或爬虫提供依据;
  • 数据篡改与修改:通过拦截并修改请求/响应数据包,在不重新打包 APK 的前提下实现屏蔽广告、解锁会员等功能;
  • 协议分析:研究 App 使用的私有协议格式、字段含义,为协议逆向工程打基础;
  • 安全评估:定位 App 是否存在敏感信息明文传输、越权访问、接口未鉴权等安全漏洞,是渗透测试工作中不可或缺的一步。

1.2 抓包的技术演进与阻碍

抓包从来不是"一劳永逸"的事,随着整个行业安全意识的提升,抓包这件事变得越来越难。

第一阶段(HTTP 明文时代):早期 App 普遍使用 HTTP 协议传输数据,数据包明文可见,任何网络设备都能直接读取。这个时代,抓包几乎毫无障碍——只需把手机接入同一局域网,Wireshark 一开就什么都看到了。

第二阶段(HTTPS 普及):HTTPS 在移动端全面铺开后,中间人(MITM)代理模式应运而生。代理工具通过重签证书实现"合法"的流量拦截,前提是客户端信任代理的 CA 根证书。这个时代,抓包变成了"安装一个证书就能解决"的问题。

第三阶段(Android 7.0 系统收紧):2016 年 Android 7.0 的发布是一道明显的分水岭。从这个版本开始,Google 修改了系统的网络安全配置(network_security_config),应用默认不再信任用户安装的 CA 证书,只有系统证书目录下的证书才有效。从此,单纯在手机里安装代理证书已无法奏效,必须想办法将证书提权到系统级别。

第四阶段(App 自我保护觉醒):面对日益严峻的逆向分析威胁,各大厂商开始在应用内构建多层防御体系:

  • 代理检测:主动检测系统代理配置,发现代理就拒绝网络请求;
  • SSL Pinning(证书固定):将服务端证书的公钥哈希硬编码进 App,即使安装了伪造的 CA 证书,握手时也会因指纹不匹配而失败;
  • 双向认证(mTLS):服务端要求验证客户端证书,代理工具因没有合法的客户端证书而无法建立连接;
  • VPN 检测:检测手机是否运行了 VPN 软件,发现后拒绝服务。

这四重防御叠加在一起,让传统的代理抓包方式几乎完全失效。

1.3 本文目标

本文提供一套完整的排查与对抗路径,从最简单的代理配置,到 Frida Hook,再到内核级 eBPF 方案,覆盖从 Android 4 到 Android 16 的所有版本,应对市面上所有主流的反抓包防御手段。


二、必备前置知识:抓包的理论地基

本节是理解后续所有对抗手段"为什么有效"的理论基础。如果你已经熟悉网络协议基础,可以快速浏览后直接进入第三章。

2.1 网络基础

数据包的本质 是网络通信中的信息单元,由两部分组成:Header(头部) 和 Payload(数据载荷)。头部包含路由、控制信息(如 IP 地址、端口号、协议类型),载荷则是真正要传输的业务数据。抓包工具本质上就是在特定节点捕获这些数据单元,并对其进行解码还原。

OSI 七层模型与 TCP/IP 四层模型的对应关系与抓包工具的关联:

OSI 层级
TCP/IP 层级
代表协议
对应抓包工具
应用层(7)
应用层
HTTP/HTTPS/DNS/FTP
Charles、Reqable、Burp(L7 代理工具)
传输层(4)
传输层
TCP/UDP
Wireshark、tcpdump(可捕获流)
网络层(3)
网络层
IP/ICMP/QUIC
Wireshark(数据包级别)
数据链路/物理层(1-2)
网络接口层
Ethernet/WiFi
Wireshark(帧级别)

代理工具(Charles/Reqable/Burp)工作在 L7 应用层,它们"理解"HTTP 协议的语义,能够解析、展示、修改请求/响应内容,但它们无法处理不经过代理的流量(如 App 直接通过 socket 绕过代理)。Wireshark/tcpdump 工作在更底层,可以捕获所有流量,但无法自动解密 TLS 内容。

常见协议速览:

  • TCP:面向连接的可靠传输,HTTP/HTTPS 基于 TCP;
  • UDP:无连接的快速传输,QUIC 协议(HTTP/3)基于 UDP;
  • QUIC:Google 发明的传输协议,HTTP/3 的底层,基于 UDP,有自己的加密实现;
  • DNS:域名解析协议,默认 UDP 53 端口,用于将域名转换为 IP 地址。

2.2 HTTP 深度解析

URL 结构剖析
URL 结构剖析

端口号在 HTTPS 下默认为 443,HTTP 下默认为 80,省略时使用默认值。

请求报文三要素

POST /api/v2/login HTTP/1.1          ← 请求行(方法 + URL + 协议版本)
Host: api.example.com                ← 请求头开始
Content-Type: application/json
Authorization: Bearer eyJhbGci...
User-Agent: MyApp/2.0 (Android 12)
                                     ← 空行:头部与正文的分隔符
{"username":"user","password":"xxx"} ← 请求体(Body)

常用 HTTP 方法语义

方法
语义
是否有 Body
是否幂等
GET
获取资源
否(参数在 URL)
POST
创建/提交数据
PUT
替换整个资源
PATCH
局部更新资源
DELETE
删除资源
可选

常见状态码速查

状态码
含义
抓包时的常见场景
200 OK
请求成功
正常响应
301/302
永久/临时重定向
抓包中可能看到 Location 头
401 Unauthorized
未授权
Token 失效或未携带认证信息
403 Forbidden
禁止访问
服务端检测到异常(代理、签名错误等)
404 Not Found
资源不存在
接口路径错误
500 Internal Server Error
服务端错误
服务端异常,与客户端无关

关键请求头解析

请求头
作用
抓包分析重点
Host
目标域名,代理路由依据
虚拟主机区分
Content-Type
请求体格式(JSON/Form/Multipart)
决定 Body 解析方式
Authorization
认证信息(Bearer Token / Basic Auth)
权限绕过重点关注字段
User-Agent
客户端标识(App 版本、设备信息)
服务端指纹识别依据
Cookie
会话状态携带
会话劫持的关键字段
X-Sign
 / X-Token
自定义签名字段
防重放设计,逆向重点

2.3 HTTPS 与 TLS 加密原理

HTTP vs HTTPS 的本质差异

HTTP 是明文协议,数据在传输过程中完全可读;HTTPS 则在 HTTP 之上叠加了三重保障:

HTTPS = HTTP + 通信加密 + 服务端身份认证 + 数据完整性保护

TLS(Transport Layer Security,传输层安全协议)是 HTTPS 的核心,负责以上三重保障的实现。

TLS 握手简化流程

TLS 握手简化流程

握手完成后,双方使用协商好的对称密钥(如 AES-256)加密所有后续通信。中间人代理正是在握手阶段介入,用自己的证书替换服务端证书,从而让客户端与代理之间建立一个 TLS 连接,代理再与真实服务端建立另一个 TLS 连接,实现对双向流量的解密。

2.4 数字证书与 CA 体系

数字证书(X.509 标准)是公钥基础设施(PKI)的核心组件,本质上是一份由权威机构(CA)签名的"身份证明文件",内容包括:

  • 持有者的身份信息(Common Name / Subject Alternative Names)
  • 持有者的公钥
  • 有效期
  • CA 的数字签名

证书格式速查表

格式
说明
典型用途
.pem
Base64 编码的 DER,通用格式
CA 根证书、服务端证书
.crt
 / .cer
公钥证书,不含私钥
服务端公钥证书
.p12
 / .pfx
PKCS#12,含公钥 + 私钥(有密码保护)
客户端证书(mTLS 场景)
.bks
BouncyCastle KeyStore,Android 专用
Android App 内置证书库
.der
二进制 DER 编码证书
部分工具使用
.csr
证书签名请求,申请证书用
CA 签发流程中间产物

系统证书目录 vs 用户证书目录的区别

证书目录对比:系统目录 vs 用户目录

2.5 中间人(MITM)抓包的核心原理

代理工具实现 HTTPS 解密的完整流程如下图所示:

MITM 中间人代理原理示意图

关键机制

  1. 用户将代理工具的 CA 根证书安装到手机,手机系统因此信任该 CA;
  2. 当 App 发起 HTTPS 请求时,流量被路由到代理工具;
  3. 代理工具动态生成针对目标域名的伪造证书,并用自己的 CA 私钥签名;
  4. App 收到伪造证书后,因为信任代理的 CA,验证通过,与代理建立第一段 TLS 连接;
  5. 代理同时与真实服务端建立第二段 TLS 连接(使用服务端的真实证书);
  6. 代理在两段连接之间转发数据,同时可以查看、修改双向的明文内容。

这就是为什么只要 App 信任代理的 CA 证书,HTTPS 流量就可以被解密——证书体系的信任传递机制被利用了。


三、工具库:按场景选择合适的工具

不同的对抗场景需要不同层次的工具。工欲善其事,必先利其器——在投入大量时间排查之前,选对工具能节省 80% 的时间。

抓包工具全景图

3.1 代理抓包工具(应用层 L7,主力场景)

这是日常使用频率最高的一类工具,工作在 HTTP/HTTPS 协议层,能够解析并展示请求/响应的完整内容。

Reqable(首推)

Reqable 是近年来国内影响力最大的抓包工具,由国内团队维护,具备完整的中文界面,桌面端和移动端均有良好支持,集代理抓包与 API 调试功能于一体。

Reqable

核心优势

  • 桌面端(macOS/Windows/Linux)+ 移动端(iOS/Android)协同工作;
  • 内置 API 调试、请求历史记录、接口对比等高级功能;
  • 对 HTTP/2、gRPC 协议有良好支持;
  • 移动端支持 VPN 模式,无需设置系统代理,天然绕过代理检测。

Charles

老牌抓包工具,经典且稳定,功能全面:

  • 断点(Breakpoints):在请求发出前或响应返回前暂停,允许手动修改数据;
  • Map Remote:将特定 URL 的请求重定向到另一个地址,常用于调试线上接口;
  • Throttle(弱网模拟):模拟 2G/3G/4G 等不同网络条件,测试 App 网络容错能力;
  • Rewrite:基于规则自动修改请求/响应的 Header 或 Body。

Burp Suite
Viewing the HTTP history in Burp Proxy

渗透测试领域的标准工具,功能远超普通抓包:

  • Repeater:手动重放和修改单个请求;
  • Intruder:自动化的 Fuzzing 与暴力测试;
  • Scanner(Pro 版):自动扫描常见 Web 漏洞(XSS、SQL 注入等);
  • Proxy + 插件生态:通过 BApp Store 扩展功能(如 JSON Beautifier、JWT 分析等)。

ProxyPin

ProxyPin

完全开源免费的跨平台方案(Flutter 开发),支持 iOS/Android/macOS/Windows/Linux 全平台。对 Flutter App 的抓包支持友好(基于 VPN 模式),适合开源环境或对 Charles 授权有顾虑的场景。

HTTP Toolkit

HTTP Toolkit 是一款开源的现代化 HTTP/HTTPS 调试工具,其最大亮点是一键式 Android 接入:通过 ADB 自动完成证书安装和代理配置,无需手动操作手机,极大降低上手门槛。

核心优势

  • ADB 一键接入:点击"Android device via ADB"后,工具自动推送 CA 证书、配置系统代理、安装伴侣 App,全程无需手动触碰手机;
  • 流量来源归因:能显示每条请求来自哪个 App 进程,在多 App 同时运行时快速定位目标流量;
  • 无需 Root:基于标准 MITM 代理 + ADB 自动化,不需要 Root 权限即可完成 HTTPS 解密;
  • 规则化 Mock:支持按 URL 规则自动返回自定义响应,方便本地模拟接口;
  • 开源免费:核心功能完全免费,Pro 版额外提供断点调试和高级重写规则。

典型使用场景

# 1. PC 端启动 HTTP Toolkit,选择 "Android device via ADB"
# 2. 工具自动执行以下操作(无需手动):
#    - adb push httptoolkit-ca.pem /data/local/tmp/
#    - 安装伴侣 APK(配置系统代理 + 证书信任)
# 3. 手机端流量自动路由到 HTTP Toolkit,开始抓包

局限性:与其他代理工具一样,若 App 部署了 SSL Pinning 或代理检测,仍需配合 Frida 等方案绕过;对 Flutter、QUIC 等非标准 TLS 栈的支持也受限。

3.2 本地 VPN 抓包(绕过代理检测的利器)

当 App 通过代码检测到系统代理并拒绝请求时,VPN 模式抓包就派上了用场。

核心原理:代理工具工作在 OSI L7 层(应用层),通过系统代理配置将流量转发;而 VPN 工作在 L2/L3 层(数据链路/网络层),通过虚拟网卡(tun0)在操作系统内核层面拦截所有流量。App 在 Java 层检测到的代理设置(http.proxyHost)为空,因此代理检测失效。

但需注意:部分 App 同时进行 VPN 检测(检测 tun0 网卡是否存在),这一点在第七章会详细介绍绕过方法。

  • HttpCanary(黄鸟):Android 端专用,VPN 隧道拦截,界面简洁,支持 HTTPS 解密,无需 Root,适合快速上手;
  • Reqable 移动端:功能最全面的移动端抓包方案,代理模式与 VPN 模式均支持,推荐首选。

3.3 底层协议分析工具(L3/L4,定位网络问题)

当应用层代理无法捕获流量时(例如 App 使用了私有协议、QUIC、WebSocket 等),需要下沉到网络层进行抓包。

Wireshark

Wireshark

业界最权威的图形化网络分析工具,能够捕获和分析所有协议的数据包:

# 在手机上 tcpdump 抓包,通过 adb 拉取到 PC 后用 Wireshark 分析
adb shell tcpdump -i any -w /data/local/tmp/capture.pcap
adb pull /data/local/tmp/capture.pcap ./capture.pcap
# 然后双击 capture.pcap 用 Wireshark 打开

tcpdump / ptcpdump

命令行抓包工具,直接运行在 Android 设备上:

  • tcpdump:传统的命令行抓包,需要 Root 权限或 adb 执行;
  • ptcpdump:基于 eBPF 的增强版 tcpdump,核心优势是支持按进程名过滤流量,精准定位目标 App 的网络请求,避免噪音干扰。
# ptcpdump 按进程名过滤
ptcpdump -i any --process-name com.example.app -w output.pcap

3.4 终极级:免证书 Hook 抓包工具

当以上所有方法都遭遇阻碍时,这两款工具提供了绕过一切证书校验机制的终极能力。

r0capture(Frida 方案)

由 r0ysue 大佬开发,基于 Frida 框架,直接 Hook OpenSSL/BoringSSL 的 SSL_write 和 SSL_read 函数,在 TLS 加密之前(发送侧)和解密之后(接收侧)截获明文数据流,以 PCAP 格式输出:

# 使用方式
python r0capture.py -U <package_name> -v -p output.pcap
# 然后用 Wireshark 打开 output.pcap 分析

能力边界

  • 仅限安卓平台,测试安卓7、8、9、10、11、12、13、14 、15、16可用 ;
  • 无视所有证书校验或绑定,不用考虑任何证书的事情;
  • 通杀TCP/IP四层模型中的应用层中的全部协议;
  • 通杀协议包括:Http,WebSocket,Ftp,Xmpp,Imap,Smtp,Protobuf等等、以及它们的SSL版本;
  • 通杀所有应用层框架,包括HttpUrlConnection、Okhttp1/3/4、Retrofit/Volley等等;
  • 无视加固,不管是整体壳还是二代壳或VMP,不用考虑加固的事情;

eCapture(旁观者,eBPF 方案)

最前沿的内核级 TLS 明文捕获工具,基于 Linux eBPF(Extended Berkeley Packet Filter)技术,通过 uprobe 探针在内核态直接钩住加密库的读写函数:

# 推送到设备并运行
adb push ecapture /data/local/tmp/ && adb shell chmod 777 /data/local/tmp/ecapture
adb shell /data/local/tmp/ecapture tls -p <pid> -m text

核心能力:eCapture 提供按功能组织的八个不同捕获模块:

模块
目的
主要钩子点
支持的版本
tls
OpenSSL/BoringSSL TLS 捕获
SSL_read
SSL_writeSSL_do_handshake
OpenSSL 1.0.2-3.5.x, BoringSSL Android 12-16
gotls
Go crypto/tls 捕获
crypto/tls.(*Conn).Write
crypto/tls.(*Conn).Read
Go 1.x,支持 register/stack ABI
gnutls
GnuTLS 库捕获
gnutls_record_recv
gnutls_record_send
GnuTLS 3.x
nss
NSS/NSPR 库捕获
PR_Write
PR_ReadPR_SendPR_Recv
Firefox, Thunderbird
bash
Bash 命令审计
readline
 库函数
Bash 4.x-5.x
zsh
Zsh 命令审计
zle_line_finish
 函数
Zsh 5.x
mysqld
MySQL 查询审计
dispatch_command
 函数
MySQL 5.6/5.7/8.0, MariaDB
postgres
PostgreSQL 查询审计
exec_simple_query
 函数
PostgreSQL 10+

每个模块独立运行,可以通过 cli/cmd/root.go 中定义的 CLI 命令结构启用。

核心优势:完全不修改目标 App,没有 Frida 运行时特征,极难被检测到。

设备要求:Android 13+ 或内核版本 5.10 以上。


四、核心分水岭:Android 系统版本与证书信任策略

这是实战的第一关,也是很多人卡住的地方。搞清楚不同版本的证书信任策略,能解决"为什么我安装了证书还是抓不到包"这个最常见的问题。

Android 各版本证书信任策略演进

4.1 Android 7.0 以下(API < 24):用户证书黄金时代

在 Android 7.0 之前,系统默认信任用户安装的所有 CA 证书,抓包只需三步:

实战 SOP(Android 6 及以下)

  1. 手机连接到与 PC 同一局域网的 WiFi;
  2. 在 WiFi 高级设置中配置手动代理(IP 为 PC 局域网地址,端口如 8888);
  3. 在手机浏览器访问代理工具提供的证书下载地址(如 http://charlesproxy.com/getssl),下载并安装 CA 证书;
  4. 打开目标 App 开始抓包。

4.2 Android 7.0 及以上:用户证书失效

从 Android 7.0 开始,Google 引入了网络安全配置(Network Security Config)机制。应用层的默认配置变更为:不信任用户安装的 CA 证书

具体表现在 App 的 AndroidManifest.xml 中引用的 res/xml/network_security_config.xml 文件,默认配置等效于:

<!-- Android 7+ 默认行为,应用不信任用户证书 -->
<network-security-config>
<base-configcleartextTrafficPermitted="false">
<trust-anchors>
<!-- 只信任系统证书目录,不信任用户目录 -->
<certificatessrc="system"/>
</trust-anchors>
</base-config>
</network-security-config>

这意味着即使你在手机系统设置里安装了代理的 CA 证书(安装到用户证书目录),App 发出的 HTTPS 请求依然会因"证书不受信任"而失败。

针对这个问题,有三种解决方案:

方案 A:修改 APK 的 network_security_config(无需 Root)

原理:解包 APK,修改网络安全配置文件,使 App 信任用户证书,重新签名打包。

操作步骤

# 1. 使用 apktool 解包
apktool d target.apk -o target_decompiled

# 2. 查看 AndroidManifest.xml 中是否已有 networkSecurityConfig 属性
# <application android:networkSecurityConfig="@xml/network_security_config" ...>
# 如无,在 application 标签中添加该属性

# 3. 修改或创建 res/xml/network_security_config.xml
<!-- res/xml/network_security_config.xml:添加用户证书信任 -->
<network-security-config>
<base-configcleartextTrafficPermitted="true">
<trust-anchors>
<certificatessrc="system"/>
<!-- 添加这一行,信任用户安装的证书 -->
<certificatessrc="user"/>
</trust-anchors>
</base-config>
</network-security-config>
# 4. 重新打包并签名(需要 Java 环境)
apktool b target_decompiled -o target_patched.apk
# 生成调试签名
keytool -genkey -v -keystore debug.keystore -alias androiddebugkey \
    -keyalg RSA -keysize 2048 -validity 10000
# 签名 APK
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
    -keystore debug.keystore target_patched.apk androiddebugkey

注意事项

  • 如果 App 有签名校验(一些金融类 App 会检测),重签后可能会闪退;
  • 部分 App 有加固/混淆保护,apktool 可能无法正常解包;
  • 适用场景:无 Root 设备,且 App 本身没有额外签名校验。

方案 B:Root 设备手动推送系统证书

原理:获取 Root 权限后,将代理 CA 证书以系统证书格式推送到系统证书目录,让所有 App 均信任。

操作步骤

# 1. 将代理的 CA 证书(PEM 格式)保存到本地,假设文件名为 ca.crt

# 2. 计算 OpenSSL Subject Hash(旧式,Android 使用此格式)
openssl x509 -inform PEM -subject_hash_old -in ca.crt | head -1
# 输出示例:a1b2c3d4

# 3. 将证书重命名为 <hash>.0 格式
cp ca.crt a1b2c3d4.0

# 4. 推送到系统证书目录(需要 Root)
adb root
adb remount  # 重新挂载为可写
adb push a1b2c3d4.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/a1b2c3d4.0
adb reboot   # 重启生效

注意事项

  • Android 10 及以上版本的系统分区通常是只读的,adb remount 可能无法执行;
  • 在这种情况下,需要配合 Magisk 的方案(见方案 C)。

方案 C:Magisk 模块自动挂载(推荐)

MoveCertificate 模块是目前最优雅的解决方案:它会在系统启动时,自动将用户证书目录下的证书"挂载"到系统证书目录,无需修改实际的系统分区文件,完全安全可回滚。

安装步骤

  1. 确保设备已安装 Magisk 并获取 Root;
  2. 在手机系统设置中正常安装代理工具的 CA 证书(安装到用户证书目录);
  3. 在 Magisk Manager 中搜索并安装 MoveCertificate 模块;
  4. 重启设备,模块会在开机时自动将用户证书挂载为系统证书。

4.3 Android 14 及以上:APEX 挂载机制的新挑战

Android 14 引入了一个更为复杂的机制:系统证书目录由 APEX(Android Pony EXpress)模块动态挂载管理,而不再是一个静态的文件目录。这使得传统的 adb push 和简单 Magisk 模块推送方式都失效了。

根本原因:APEX 在系统启动阶段会将证书目录挂载到特定位置,覆盖掉之前对 /system/etc/security/cacerts/ 目录的任何修改。

解决方案:需要在 APEX 挂载之后、Zygote 启动之前这个窗口期,强制将证书注入进去,以下两种方案可以尝试:

方案A(推荐):MoveCertificate 模块

MoveCertificate 是一个专为此问题设计的 Magisk / KernelSU / APatch 模块,支持 Android 7–16,原理是在 post-fs-data 阶段将用户证书目录 mount --bind 覆盖到 APEX 的系统证书路径,一次安装永久生效。

安装步骤:与上文一致。

方案B:手动内置 / remount(自编译 ROM)

如果使用的是自行编译的 AOSP 镜像,可以直接将证书内置到源码或在启动后 remount system 手动复制:

# remount system 为可写后直接推送(需要 userdebug/eng 构建)
adb root && adb remount
adb push charles-proxy-ssl-proxying-certificate.pem \
    /system/etc/security/cacerts/<hash>.0
adb shell chmod 644 /system/etc/security/cacerts/<hash>.0
adb reboot

Tips:如果以上方案都嫌麻烦,可以直接跳过证书信任问题,使用第八章介绍的 r0capture 在 SSL 底层捕获明文,彻底绕开系统证书校验链路。


五、基础抓包实操:以 Reqable 为例的完整流程

本章用 Reqable 作为演示工具,完整演示一次标准的 HTTPS 抓包流程。Reqable 对国内用户最友好,但流程对 Charles、Burp 同样适用。

5.1 工具安装与证书配置

第一步:安装 PC 端 Reqable

从 reqable.com 下载适合你操作系统的版本(macOS/Windows/Linux),安装后首次启动会引导你生成 CA 根证书。证书会被保存在 ~/.reqable/ 目录下。

第二步:导出并安装证书到手机

不同的桌面端平台(这里主要是Windows/MacOS/Linux),证书安装方式有所不同,为了简化安装过程,Reqable提供了一键安装证书的功能。证书的安装入口位于顶部操作栏,点击盾牌图标打开弹窗。

安装安卓证书:

Android证书分为两种:用户证书和系统证书。用户目录不需要权限即可添加和删除CA证书,系统目录需要Root权限才可以添加和删除CA证书。

Reqable要求用户事先已经在电脑上安装了ADB工具,Reqable会使用ADB工具检查连接到电脑的Android设备的证书安装状态,包括系统证书安装状态和用户证书安装状态。

只有Root的设备Reqable才可以一键安装证书(支持Android 5.0 - 15系统)。

如果已经安装了系统证书,可以跳过用户证书的安装。如果系统证书安装失败,则需用户手动安装用户证书,在手机端打开设置进行如下步骤的操作:

手机设置 → 安全 → 更多安全设置 → 加密与凭据 → 安装证书 → CA 证书

注意:不同 Android 版本和手机品牌的菜单路径略有差异,关键词是"安装证书"或"信任凭据"。另外Reqable无法检测到非Root设备的用户证书安装状态,会一直显示未知证书安装状态

第三步:配合 Magisk 模块提升为系统证书(Android 7+ 必须)

如第四章所述,安装 MoveCertificate 模块并重启,使用户证书在系统级别生效。

5.2 代理配置与连接

获取 PC 的局域网 IP

# macOS/Linux
ifconfig | grep "inet " | grep -v 127.0.0.1

# Windows
ipconfig | findstr "IPv4"

手机 WiFi 代理设置

手机设置 → WiFi → 长按已连接的 WiFi → 修改网络 → 代理 → 手动
  主机名:<PC 的局域网 IP,如 192.168.1.100>
  端口:9000(Reqable 默认端口)

验证连通性:在手机浏览器访问 http://reqable.com/install,如果可以正常加载且 HTTPS 请求能被拦截,说明配置成功。

5.3 请求与响应的解析

在 Reqable 中点击任意一条已捕获的请求,可以看到完整的请求/响应详情:

请求结构解析

Body 格式识别

Content-Type
 值
Body 格式
说明
application/json
JSON
最常见,可读性强
application/x-www-form-urlencoded
Form 键值对
传统表单提交
multipart/form-data
Multipart
文件上传
application/protobuf
Protocol Buffers
二进制,需要 proto 文件解码
application/octet-stream
原始二进制
私有协议

当遇到 Protobuf 格式的数据时,Reqable 和 Burp 都支持内置或插件方式的 Protobuf 解码,但需要先找到对应的 .proto 文件(通常在 APK 中可以找到)。

5.4 实用调试功能

断点(Breakpoints)重放

设置断点后,当匹配的请求/响应触发时,工具会暂停并允许你手动修改数据后再继续:

Reqable → 右键请求 → 断点 → 选择"在响应返回时暂停"
# 再次触发该请求,Reqable 会弹出编辑界面
# 修改响应 JSON 中的 vip 字段为 true,点击继续

这是不修改 APK 实现"破解"某些功能的常见手段。

重写规则(Rewrite Rules)

自动化版本的断点,基于规则匹配对请求/响应进行固定改写:

Reqable → 重写规则 → 添加规则
  匹配:URL 包含 /api/user/vip
  操作:响应 Body 替换(将 "vip":false 替换为 "vip":true

弱网模拟(Throttle)

模拟不同网络环境,验证 App 的网络容错能力:

预设
带宽
延迟
用途
2G
100 Kbps
300ms
弱网极限测试
3G
750 Kbps
100ms
普通弱网测试
4G
10 Mbps
30ms
常规测试
WiFi
100 Mbps
5ms
正常网络

六、魔高一尺:App 反抓包防御策略详解

当你发现某个 App 即使配置了代理和证书也无法抓包时,说明 App 部署了主动防御机制。本章深度剖析四大防御体系的实现原理,为第七章的对抗手段打下基础。

理解防御侧的实现,才能找到对应的突破口。这里展示的都是真实存在于生产 App 中的防御代码。

SSL Pinning 四大防御机制与完整绕过方案

6.1 代理检测(Proxy Detection)

防御原理

Java 层的代理检测非常简单直接——读取系统属性,如果发现代理配置就拒绝请求:

// 检测方式一:读取系统代理属性
String proxyHost = System.getProperty("http.proxyHost");
String proxyPort = System.getProperty("http.proxyPort");
if (proxyHost != null && !proxyHost.isEmpty()) {
// 检测到代理,记录日志并拒绝本次网络请求
    Log.w("Security""Proxy detected: " + proxyHost + ":" + proxyPort);
thrownew SecurityException("Proxy not allowed");
}

// 检测方式二:构造请求时强制不走代理
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(Proxy.NO_PROXY)  // 强制绕过系统代理
    .build();

第二种方式更为彻底:即使手机设置了代理,OkHttpClient 也会直接连接目标服务器,完全绕过代理工具。这种情况下,代理工具根本收不到任何请求。

检测代码的常见变体

// Kotlin 写法
val proxyHost = System.getProperty("http.proxyHost")
val httpsProxyHost = System.getProperty("https.proxyHost")
if (!proxyHost.isNullOrEmpty() || !httpsProxyHost.isNullOrEmpty()) {
// 发送安全告警,中断请求
    reportSecurityEvent("proxy_detected")
}

6.2 VPN 检测(VPN Detection)

防御原理

VPN 检测通过枚举网络接口来识别 VPN 的存在:

// 方式一:检查网卡名称
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
    NetworkInterface ni = interfaces.nextElement();
    String name = ni.getName().toLowerCase();
// tun0/ppp0/p2p0 是常见的 VPN 虚拟网卡名
if (name.startsWith("tun") || name.startsWith("ppp") || name.startsWith("p2p")) {
        Log.w("Security""VPN interface detected: " + name);
returntrue// VPN 已激活
    }
}

// 方式二:通过 NetworkCapabilities 检测(Android 5+)
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
Network activeNetwork = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(activeNetwork);
if (caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// 传输类型包含 VPN(能力值 4)
returntrue;
}

6.3 SSL Pinning(证书固定)

SSL Pinning 是目前最常见、最有效的反抓包手段之一。其核心思想是:将服务端证书的公钥哈希(或完整证书)硬编码进 App,在 TLS 握手完成后额外验证一次,确保与己方预期的服务端完全一致。

即使攻击者的代理 CA 证书被系统信任,SSL Pinning 也会因"公钥不匹配"而拒绝连接。

SSL Pinning 校验机制:TLS 握手后的第二道关卡

实现方式一:OkHttp CertificatePinner(公钥 Hash 校验)

这是主流 Android App(使用 OkHttp 框架)最常见的实现方式:

// 预先将服务端证书的公钥 Base64 哈希硬编码进代码
// 格式:sha256/<Base64 编码的公钥 SHA-256 哈希>
CertificatePinner pinner = new CertificatePinner.Builder()
    .add("api.example.com""sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .add("api.example.com""sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="// 备用
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(pinner)
    .build();

获取服务端证书 Hash 的命令

# 用 openssl 提取服务端证书的公钥 Base64 SHA256 哈希
openssl s_client -connect api.example.com:443 2>/dev/null | \
    openssl x509 -pubkey -noout | \
    openssl pkey -pubin -outform der | \
    openssl dgst -sha256 -binary | \
    openssl enc -base64

实现方式二:自定义 TrustManager(证书公钥比对)

更底层的实现,直接在 X509TrustManager 的 checkServerTrusted 方法中手动比对:

publicclassPinnedTrustManagerimplementsX509TrustManager{
// 从 res/raw 中预置的证书提取的公钥
privatestaticfinal String EXPECTED_PUBLIC_KEY =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...";

@Override
publicvoidcheckServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException 
{
// 提取服务端证书的公钥,转换为 Base64
        String serverPublicKey = Base64.encodeToString(
            chain[0].getPublicKey().getEncoded(), Base64.DEFAULT);
// 与预置值比较,不匹配则抛出异常中断连接
if (!EXPECTED_PUBLIC_KEY.equals(serverPublicKey.trim())) {
thrownew CertificateException("Certificate pinning failure: public key mismatch");
        }
    }
// ...
}

实现方式三:HostnameVerifier 域名校验

通过限制可信域名来防止 MITM:

client.setHostnameVerifier(new HostnameVerifier() {
@Override
publicbooleanverify(String hostname, SSLSession session){
// 只允许指定的域名通过
return"api.example.com".equals(hostname) ||
"cdn.example.com".equals(hostname);
    }
});

Android 常见网络框架汇总

框架
类型
备注
OkHttp
底层 HTTP 客户端
Android 最主流,Retrofit 基于此
Retrofit
声明式 HTTP 客户端
基于 OkHttp,接口定义简洁
Volley
Google 官方
老项目常见,新项目较少
HttpURLConnection
系统内置
原生 Java API
xUtils
第三方框架
老项目可见

6.4 双向认证(mTLS / Mutual TLS)

普通 TLS 只验证服务端的证书;mTLS(双向 TLS)要求双方互相验证证书——服务端也要验证客户端证书的合法性。

抓包工具因为没有合法的客户端证书,连接在 TLS 握手阶段就被服务端拒绝,根本无法看到任何内容。

mTLS 双向认证 vs 普通 TLS 单向认证

防御实现

// 加载内置的客户端证书(存放在 assets/ 或 res/raw/ 中)
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream p12Stream = getAssets().open("client_cert.p12");
// 密码通常硬编码在代码中,jadx 搜索即可找到
keyStore.load(p12Stream, "certificate_password".toCharArray());

// 创建 KeyManagerFactory
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "certificate_password".toCharArray());

// 构建支持 mTLS 的 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), trustManagers, null);

OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
    .build();

证书格式速查(mTLS 场景)

格式
包含内容
用途
.p12
 / .pfx
公钥 + 私钥(密码保护)
客户端证书,导入 Burp/Charles 使用
.cer
 / .crt
仅公钥证书
服务端验证客户端用
.bks
BouncyCastle KeyStore
Android 专用,等价于 JKS

七、道高一丈:反抓包对抗手段(攻击侧全策略)

本章是全文的核心。针对第六章介绍的每一种防御机制,提供完整的绕过方案,并附带可直接使用的 Frida Hook 脚本。

前提准备:Frida 相关方案需要设备安装并运行 frida-server(需 Root)。

7.1 对抗代理检测

方案一:VPN 模式抓包(最省力)

使用 Reqable 移动端或 HttpCanary 的 VPN 模式,完全绕过代理检测:

HttpCanary → 启动抓包 → App 检测不到 http.proxyHost
Reqable 移动端 → 连接 → 选择 VPN 模式

原理:VPN 在内核层面拦截流量,Java 层的 System.getProperty("http.proxyHost") 返回 null,代理检测逻辑失效。

方案二:透明代理(iptables,对 App 完全无感)

在路由器或 Linux 主机上通过 iptables 强制转发流量,无需在手机端配置任何代理:

# 在运行 Clash 等代理工具的主机/路由器上执行
# 将所有来自手机 IP 的 HTTP/HTTPS 流量强制转发到代理端口
iptables -t nat -A PREROUTING -s 192.168.1.100 -p tcp --dport 80 \
    -j REDIRECT --to-ports 7890
iptables -t nat -A PREROUTING -s 192.168.1.100 -p tcp --dport 443 \
    -j REDIRECT --to-ports 7890

# Clash 透明代理(tproxy 模式)配置示例
# tproxy-port: 7893
# mode: tproxy

这种方案下,手机端的代理设置为空,App 完全感知不到代理的存在。

方案三:Frida Hook 系统属性(直接绕过检测逻辑)

当 App 的代理检测代码在 Java 层,可以直接 Hook System.getProperty() 方法,让代理相关的属性查询返回 null

// frida hook: 隐藏代理配置
Java.perform(function({
var System = Java.use("java.lang.System");
var getPropertyOverload = System.getProperty.overload("java.lang.String");

    getPropertyOverload.implementation = function(key{
// 拦截代理相关的属性查询
if (key.indexOf("http.proxyHost") >= 0 ||
            key.indexOf("http.proxyPort") >= 0 ||
            key.indexOf("https.proxyHost") >= 0 ||
            key.indexOf("https.proxyPort") >= 0) {
console.log("[+] Hiding proxy property: " + key);
returnnull// 返回 null,欺骗代理检测逻辑
        }
// 其他属性正常返回
returnthis.getProperty(key);
    };

console.log("[+] Proxy detection bypass activated");
});
# 运行方式
frida -U -n <process_name> -l bypass_proxy.js
# 或在 spawn 模式下注入(App 启动前注入,避免初始化时的检测)
frida -U -f <package_name> -l bypass_proxy.js --no-pause

7.2 对抗 VPN 检测

方案一:Hook NetworkInterface.getName() 隐藏 VPN 网卡名

// frida hook: 隐藏 VPN 网卡特征
Java.perform(function({
var NetworkInterface = Java.use("java.net.NetworkInterface");

    NetworkInterface.getName.implementation = function({
var name = this.getName();
// 将 VPN 虚拟网卡名替换为普通数据网卡名
if (name === "tun0" || name === "tun1" ||
            name === "ppp0" || name === "p2p0") {
console.log("[+] Hiding VPN interface: " + name + " -> rmnet_data0");
return"rmnet_data0"// 伪装成普通数据网卡
        }
return name;
    };

console.log("[+] VPN interface detection bypass activated");
});

方案二:Hook NetworkCapabilities.hasTransport() 屏蔽 VPN 标志

// frida hook: 屏蔽 TRANSPORT_VPN 能力标志
Java.perform(function({
var NetworkCapabilities = Java.use("android.net.NetworkCapabilities");

    NetworkCapabilities.hasTransport.implementation = function(transportType{
// TRANSPORT_VPN = 4,拦截对 VPN 传输类型的检测
if (transportType === 4) {
console.log("[+] Hiding TRANSPORT_VPN capability");
returnfalse// 告诉 App:没有 VPN 传输层
        }
returnthis.hasTransport(transportType);
    };
});

方案三:透明代理(完全不产生 VPN 网卡,根本绕过)

如 7.1 中的透明代理方案,完全不在手机端创建 VPN 虚拟网卡,因此 VPN 检测也失效。这是最彻底的方案,但需要额外的网络基础设施(路由器或中间主机)。

7.3 对抗 SSL Pinning

方案一:JustTrustMe Xposed 模块(最省力,一键通杀)

JustTrustMe 是一个 Xposed 框架模块,安装后自动 Hook 所有主流 HTTPS 框架的证书验证逻辑,无需针对每个 App 单独分析:

  • Hook 范围:HttpsURLConnectionOkHttp 1/3/4RetrofitVolleyWebViewClientApache HttpClient 等;
  • 安装方式:在 LSPosed/Xposed Manager 中搜索安装,激活后重启 App;
  • 适用场景:有 Root + Xposed 框架,且 App 未做 Xposed 检测。

类似模块还有 SSLUnpinning,原理相同。

方案二:Frida Hook CertificatePinner.check(针对 OkHttp 指纹校验)

// frida hook: 绕过 OkHttp CertificatePinner 的指纹校验
Java.perform(function({
try {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");

// check 方法有多个重载,需要分别处理
        CertificatePinner.check.overload(
"java.lang.String""java.util.List"
        ).implementation = function(hostname, peerCertificates{
// 直接返回,跳过所有指纹验证
console.log("[+] Bypassing SSL Pinning (OkHttp) for: " + hostname);
return// void 方法,直接返回即绕过
        };

// 兼容旧版 OkHttp 的另一个重载
        CertificatePinner.check.overload(
"java.lang.String",
"[Ljava.security.cert.Certificate;"
        ).implementation = function(hostname, certs{
console.log("[+] Bypassing SSL Pinning (OkHttp legacy) for: " + hostname);
return;
        };

    } catch(e) {
console.log("[-] OkHttp CertificatePinner not found: " + e.message);
    }
});

方案三:Frida 注入空 TrustManager(针对自定义证书校验)

对于使用自定义 X509TrustManager 实现证书固定的 App,需要通过注入一个"空的"TrustManager 来绕过:

// frida hook: 注入空 TrustManager,绕过 SSLContext.init 中的证书校验
Java.perform(function({
// 动态注册一个什么都不做的 TrustManager
var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager");
var TrustManager = Java.registerClass({
name"com.bypass.TrustManager",
implements: [X509TrustManager],
methods: {
// checkClientTrusted: 不做任何检查,接受所有客户端证书
checkClientTrustedfunction(chain, authType{
console.log("[+] checkClientTrusted bypassed");
            },
// checkServerTrusted: 不做任何检查,接受所有服务端证书
checkServerTrustedfunction(chain, authType{
console.log("[+] checkServerTrusted bypassed for: " +
                    chain[0].getSubjectDN().getName());
            },
// 返回空的接受列表,表示接受所有 CA
getAcceptedIssuersfunction({
return Java.array("java.security.cert.X509Certificate", []);
            }
        }
    });

// Hook SSLContext.init,将我们的空 TrustManager 注入进去
var SSLContext = Java.use("javax.net.ssl.SSLContext");
    SSLContext.init.overload(
"[Ljavax.net.ssl.KeyManager;",
"[Ljavax.net.ssl.TrustManager;",
"java.security.SecureRandom"
    ).implementation = function(keyManagers, trustManagers, secureRandom{
console.log("[+] SSLContext.init hooked, injecting empty TrustManager");
// 替换原有的 TrustManager 数组,注入我们的空实现
this.init(keyManagers,
            Java.array("javax.net.ssl.TrustManager", [TrustManager.$new()]),
            secureRandom);
    };

console.log("[+] TrustManager bypass activated");
});

方案四:重打包修改 network_security_config.xml(无需 Root)

如第四章方案 A 所述,在 APK 中删除 <pin-set> 节点或添加用户证书信任,重签打包:

<!-- 修改前(有 SSL Pinning)-->
<domain-config>
<domainincludeSubdomains="true">api.example.com</domain>
<pin-set>
<pindigest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin>
</pin-set>
</domain-config>

<!-- 修改后(删除 pin-set 节点即可解除 SSL Pinning)-->
<domain-config>
<domainincludeSubdomains="true">api.example.com</domain>
<!-- pin-set 节点已删除 -->
</domain-config>

7.4 对抗双向认证(mTLS)

mTLS 的对抗核心是提取 App 内置的客户端证书,然后将其导入抓包工具,让抓包工具能以合法客户端的身份与服务端握手。

步骤一:静态定位证书文件

# 解压 APK(APK 本质是 ZIP 格式)
unzip -d apk_extracted target.apk

# 在解压目录中搜索证书格式文件
find apk_extracted -name "*.p12" -o -name "*.bks" -o -name "*.cer" -o -name "*.pfx"
# 注意:证书可能伪装为其他格式(.png/.dat/.bin 等),
# 可以用 file 命令检查真实格式
find apk_extracted/assets -type f | xargs file | grep -i pkcs

# 常见存放位置
# assets/ssl/client.p12
# res/raw/keystore.bks
# assets/cert/client_certificate.dat(伪装格式)

步骤二:Frida 动态 Dump 运行时证书流

如果静态分析找不到,或证书在运行时才解密,可以在运行时捕获:

// frida hook: 在 KeyStore.load 时 dump 证书输入流到本地文件
Java.perform(function({
var KeyStore = Java.use("java.security.KeyStore");

    KeyStore.load.overload(
"java.io.InputStream",
"[C"// char 数组密码
    ).implementation = function(stream, password{
// 打印密码(通常是硬编码字符串)
if (password !== null) {
var pwd = Java.use("java.lang.String").$new(password);
console.log("[+] KeyStore password: " + pwd);
        }

if (stream !== null) {
// 将 InputStream 数据读出并写入本地文件
var ByteArrayOutputStream = Java.use("java.io.ByteArrayOutputStream");
var baos = ByteArrayOutputStream.$new();
var buffer = Java.array("byte"newArray(4096).fill(0));
var bytesRead;
while ((bytesRead = stream.read(buffer)) !== -1) {
                baos.write(buffer, 0, bytesRead);
            }
var data = baos.toByteArray();

// 写入到应用私有目录
var FileOutputStream = Java.use("java.io.FileOutputStream");
var fos = FileOutputStream.$new("/data/data/<package>/files/client_cert.p12");
            fos.write(data);
            fos.close();
console.log("[+] Certificate dumped to /data/data/<package>/files/client_cert.p12");

// 重置 stream 供原方法使用(需要重新创建 InputStream)
var ByteArrayInputStream = Java.use("java.io.ByteArrayInputStream");
            stream = ByteArrayInputStream.$new(data);
        }

// 调用原始 load 方法
this.load(stream, password);
    };
});

步骤三:通过 jadx 获取证书密码

# 反编译 APK
jadx -d jadx_output target.apk

# 在反编译代码中搜索 KeyStore 相关代码
grep -r "KeyStore" jadx_output/sources/ | grep -E "load|password"
# 或搜索 .p12/.bks 文件名关键字
grep -r "client" jadx_output/sources/ --include="*.java" | grep -E "p12|bks|cert"

密码通常以字符串字面量或常量的形式出现在紧邻 keyStore.load() 的代码处,例如:

// jadx 反编译结果(示例)
keyStore.load(getAssets().open("client.p12"), "P@ssw0rd123".toCharArray());

步骤四:将证书导入抓包工具

提取到 .p12 文件和密码后:

Charles

Proxy → SSL Proxying Settings → Client Certificates
  → 添加域名:api.example.com
  → 选择证书文件:client.p12
  → 输入密码

Burp Suite

User options → SSL → Client TLS Certificates
  → Add → Destination Host: api.example.com
  → Certificate type: PKCS
#12 file
  → File: client.p12,Password: 输入

八、底层降维打击:Hook 抓包与混淆对抗

当 App 代码经过高强度混淆(ProGuard/R8/DexGuard),或使用了非标准网络框架时,以上基于类名的 Hook 方法可能会因为找不到目标类而失败。此时需要下沉到更底层的 Hook 层次。

r0capture 底层降维打击架构图

8.1 OkHttp 拦截器动态注入(适用于混淆对抗)

OkHttp 内部采用责任链模式(Interceptor Chain),所有请求/响应都会依次经过已注册的拦截器。如果能在运行时动态注入一个日志拦截器,就能在不知道混淆类名的前提下捕获所有 HTTP 流量。

OkHttpLogger-Frida 方案

# 1. 下载工具
# git clone https://github.com/siyujie/OkHttpLogger-Frida

# 2. 推送辅助 DEX 到设备
adb push okhttpfind.dex /data/local/tmp/
adb shell chmod 777 /data/local/tmp/okhttpfind.dex

# 3. 启动 Frida 并加载脚本
frida -U -f <package_name> -l okhttp_poker.js --no-pause
// okhttp_poker.js(核心逻辑)
// 通过反射动态定位 OkHttpClient 类(即使被混淆也能找到)
functionfindOkHttpClient({
// 遍历所有已加载的类,寻找包含 newCall 方法的类
var clazzes = Java.enumerateLoadedClassesSync();
for (var i = 0; i < clazzes.length; i++) {
try {
var clazz = Java.use(clazzes[i]);
if (clazz.newCall !== undefined) {
return clazzes[i]; // 找到了 OkHttpClient
            }
        } catch(e) {}
    }
returnnull;
}

// 找到后,通过 Builder 动态添加日志拦截器
// 具体实现参见 OkHttpLogger-Frida 项目 README

8.2 Java 层 Socket 自吐(HTTP 明文流量)

当 App 绕过系统代理直接使用 Socket 时,可以 Hook Java 层的 Socket 原生方法:

// frida hook: 截获 SocketOutputStream.socketWrite0
Java.perform(function({
// Hook 原生方法(native method)
var SocketOutputStream = Java.use("java.net.SocketOutputStream");
    SocketOutputStream.socketWrite0.implementation = function(fd, buf, off, len{
// 将写入的字节流转换为字符串打印
var bytes = Java.array("byte", buf);
var data = "";
for (var i = off; i < off + len && i < bytes.length; i++) {
var c = bytes[i] & 0xFF;
if (c >= 32 && c < 127) {
                data += String.fromCharCode(c);
            } else {
                data += ".";
            }
        }
if (data.indexOf("HTTP") >= 0 || data.indexOf("GET ") >= 0 ||
            data.indexOf("POST ") >= 0) {
console.log("[Socket Write] " + data.substring(0500));
        }
returnthis.socketWrite0(fd, buf, off, len);
    };
});

8.3 Java 层 SSL Socket 自吐(HTTPS 解密后明文)

在 TLS 层解密完成之后、数据到达应用逻辑之前截获,这是 Java 层最接近底层的 Hook 点:

// frida hook: 截获 ConscryptFileDescriptorSocket 的 SSL 读写
Java.perform(function({
try {
// Android 系统 TLS 实现(Conscrypt 库)
var SSLOutputStream = Java.use(
"com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLOutputStream");
var SSLInputStream = Java.use(
"com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream");

// Hook HTTPS 请求发送(TLS 解密后的明文)
        SSLOutputStream.write.overload("[B""int""int")
            .implementation = function(buf, offset, len{
var data = Java.use("java.lang.String")
                .$new(Java.array("byte", buf), offset, len, "UTF-8");
console.log("[SSL Write] " + data.substring(01000));
returnthis.write(buf, offset, len);
        };

// Hook HTTPS 响应接收
        SSLInputStream.read.overload("[B""int""int")
            .implementation = function(buf, offset, len{
var result = this.read(buf, offset, len);
if (result > 0) {
var data = Java.use("java.lang.String")
                    .$new(Java.array("byte", buf), offset, result, "UTF-8");
console.log("[SSL Read] " + data.substring(01000));
            }
return result;
        };

    } catch(e) {
console.log("[-] SSL Socket hook failed: " + e.message);
    }
});

8.4 Native 层 sendto/recvfrom Hook(原始 HTTP 流量)

调用链:java.net.SocketOutputStream.socketWrite0 → libopenjdk.so NET_Send → libc.so sendto

在 libc.so 的 sendto 函数处 Hook,可以捕获所有通过 Socket 发送的原始字节:

// frida hook: Hook Native 层 libc.so sendto/recvfrom
Interceptor.attach(Module.findExportByName("libc.so""sendto"), {
onEnterfunction(args{
var fd = args[0].toInt32();
var buf = args[1];
var len = args[2].toInt32();

// 读取缓冲区内容(可能是 HTTP 明文或加密后的 TLS 数据)
var data = buf.readByteArray(Math.min(len, 512));
var str = "";
for (var i = 0; i < data.length; i++) {
var c = data[i] & 0xFF;
            str += (c >= 32 && c < 127) ? String.fromCharCode(c) : ".";
        }
if (str.indexOf("HTTP") >= 0 || str.indexOf("GET ") >= 0) {
console.log("[sendto fd=" + fd + "] " + str);
        }
    }
});

8.5 Native 层 SSL_write/SSL_read Hook(r0capture 核心原理)

这是整个 Hook 体系中层次最深、最有效的方案——直接在 libssl.so 的 SSL_write 和 SSL_read 函数处截获:

// r0capture 核心 Hook 逻辑(简化版)
// 完整版请参考 https://github.com/r0ysue/r0capture

functionhook_ssl_write({
var sslWrite = Module.findExportByName("libssl.so""SSL_write");
if (!sslWrite) {
        sslWrite = Module.findExportByName("libssl.so""ssl3_write");
    }

    Interceptor.attach(sslWrite, {
onEnterfunction(args{
// args[0]: SSL* (SSL 上下文指针)
// args[1]: buf(明文数据缓冲区)
// args[2]: num(数据长度)
var ssl = args[0];
var buf = args[1];
var len = args[2].toInt32();

// 获取文件描述符(用于关联到具体连接)
var getFd = Module.findExportByName("libssl.so""SSL_get_rfd");
var fd = new NativeFunction(getFd, "int", ["pointer"])(ssl);

// 读取明文数据
var data = buf.readByteArray(Math.min(len, 4096));
console.log("[SSL_write fd=" + fd + "] " +
newUint8Array(data).reduce((s, b) =>
                    s + (b >= 32 && b < 127 ? String.fromCharCode(b) : "."), ""));
        }
    });
}

hook_ssl_write();

r0capture 的实际使用

# 基本使用
python r0capture.py -U com.example.app -v

# 输出为 PCAP 文件(可用 Wireshark 分析)
python r0capture.py -U com.example.app -v -p capture.pcap

# spawn 模式(推荐,在 App 启动前注入)
python r0capture.py -U -f com.example.app -v -p capture.pcap

r0capture 能力矩阵

维度
支持情况
Android 版本
7 - 16
通杀证书校验类型
SSL Pinning / 自定义 TrustManager / 双向认证
支持协议
HTTP/S、WebSocket/S、FTP/S、XMPP、IMAP、SMTP、Protobuf
支持框架
HttpURLConnection、OkHttp 1/3/4、Retrofit、Volley
不支持场景
WebView(Chromium TLS 栈)、Flutter(Dart TLS 栈)、小程序

九、内核级终极方案:eBPF + eCapture

9.1 eBPF 原理简介

eBPF(Extended Berkeley Packet Filter) 是运行在 Linux 内核中的虚拟机技术,允许用户在不修改内核代码、不加载内核模块的前提下,将自定义程序"注入"到内核的各种事件钩子点上运行。

eBPF 程序的执行由特定事件触发,支持的挂载点包括:

  • kprobe/kretprobe:内核函数的入口/出口
  • uprobe/uretprobe:用户态库函数的入口/出口(eCapture 使用这种方式)
  • tracepoints:内核静态追踪点
  • XDP(eXpress Data Path):网卡驱动层的数据包处理钩子
  • perf event:性能事件

eBPF 的核心优势对安全研究场景极为重要:

  1. 不修改目标程序:纯旁路观察,目标 App 无法感知;
  2. 性能开销极低:在内核中执行,比用户态 Hook 效率高出数倍;
  3. 极难被检测:没有 Frida 的运行时特征(ptrace、frida-server 进程等);
  4. 无需修改内核:通过标准系统调用加载 eBPF 程序即可。

9.2 eCapture 工作原理

eCapture 通过 uprobe 钩子挂载在 Android 系统中的加密共享库(OpenSSL/BoringSSL/NSS/GnuTLS)的关键读写函数上,在 TLS 解密完成后立即捕获明文数据。

eCapture eBPF 内核级 TLS 明文捕获原理

工作流程

  1. eCapture 用户态进程启动,解析目标进程的内存映射,找到 libssl.so 的加载地址;
  2. 加载 eBPF 程序到内核,在 SSL_write 和 SSL_read 的函数入口/出口处注册 uprobe 探针;
  3. 探针触发:当目标 App 调用 SSL_write(发送数据)或 SSL_read(接收数据)时,eBPF 程序被执行;
  4. 数据捕获:eBPF 程序读取函数参数中的明文数据缓冲区,通过 perf event 环形缓冲区传递给用户态收集器;
  5. 输出:eCapture 用户态收集器将捕获的数据以指定格式(文本/PCAP)输出。

整个过程中,目标 App 毫无察觉——没有任何进程注入,没有 ptrace 调用,没有额外的系统调用痕迹。

9.3 设备要求与版本检查

# 检查 Android 版本
adb shell getprop ro.build.version.release

# 检查内核版本(需要 >= 5.10)
adb shell cat /proc/version
# 或
adb shell uname -r

# 示例输出:Linux version 5.15.104-android14-... 表示内核 5.15,满足要求

目前 eCapture 对 Android 的支持情况:

  • Android 13+(内核 5.10+):完整支持,推荐使用;
  • Android 12(内核 5.10):部分设备支持,取决于内核配置;
  • Android 12 以下:内核版本通常低于 5.10,一般不支持。

9.4 使用操作

# 1. 下载 eCapture Android 版本(ARM64 架构)
# 从 https://github.com/gojue/ecapture/releases 下载对应版本

# 2. 推送到设备
adb push ecapture /data/local/tmp/
adb shell chmod 777 /data/local/tmp/ecapture

# 3. 获取目标 App 的 PID
adb shell pidof com.example.app
# 或通过 ps 过滤
adb shell ps | grep example

# 4. 启动 eCapture,捕获指定进程的 TLS 流量
adb shell /data/local/tmp/ecapture tls -p <PID> -m text

# 5. 输出为 PCAP 文件(可用 Wireshark 分析)
adb shell /data/local/tmp/ecapture tls -p <PID> -m pcap -o /data/local/tmp/output.pcap
adb pull /data/local/tmp/output.pcap ./

常用参数说明

参数
说明
tls
子命令,TLS 流量捕获模式
-p <PID>
指定目标进程 PID
-m text
文本输出模式,直接打印明文
-m pcap
PCAP 文件输出,配合 Wireshark 分析
-o <path>
PCAP 输出文件路径
--libssl <path>
手动指定 libssl.so 路径(自动检测失败时使用)

9.5 eCapture vs r0capture 横向对比

维度
r0capture(Frida)
eCapture(eBPF)
实现层次
用户态 Frida Hook
内核态 eBPF uprobe
Root 要求
需要(frida-server 需 Root)
部分场景不需要
设备兼容性
Android 7-14(更广泛)
Android 13+ / 内核 5.10+(更受限)
反检测风险
有(frida-server 进程、ptrace 特征)
极低(无运行时进程注入)
上手难度
低(Python 脚本一键运行)
中(需要熟悉 Linux 命令)
性能开销
中等
极低
App 修改
无需
无需
适用场景
广泛兼容,首选调试工具
高安全目标,规避 Frida 检测

选型建议

  • 设备是 Android 13+ 且内核 >= 5.10,且目标 App 有 Frida 检测 → 优先 eCapture;
  • 需要广泛兼容(Android 7-14),或快速上手 → 优先 r0capture;
  • 两者都可以与 Wireshark 配合,进行更深入的流量分析。

十、加密协议实战:从抓包到还原加解密逻辑

本章是全文的综合演练环节,将前面所有技术集中应用于一个典型的"加密接口逆向"场景:目标接口使用 AES-CBC 加密数据,并附带时间戳 + HMAC 签名防重放。

10.1 实战场景描述

目标接口:

POST https://api.example.com/get_coin
Content-Type: application/json

{
"user_data""u2FsdGVkX1+xxxxx...",
"timestamp": 1710000000,
"sign""a1b2c3d4e5f6..."
}

分析目标:

  1. 弄清 user_data 字段的加密方式(Key、IV);
  2. 理解 sign 的签名算法;
  3. 用 Python 脚本还原完整的请求生成逻辑,实现接口调用自动化。

10.2 第一步:抓取加密原始包

如果 App 有代理检测或 SSL Pinning,优先使用 r0capture 在 SSL 底层直接获取明文:

# 启动 r0capture
python r0capture.py -U com.example.app -v -p raw_capture.pcap

# 在 App 内触发目标接口(如点击签到获取金币)

# 打开 Wireshark 分析 raw_capture.pcap
# 过滤条件:http.request.uri contains "get_coin"

在 Wireshark 中可以看到完整的明文 HTTP 请求,得到密文字段后,再通过 jadx 逆向找出 Key 和 IV。

10.3 第二步:jadx 逆向 APK 定位加解密逻辑

# 使用 jadx-gui 打开 APK(GUI 模式搜索更方便)
jadx-gui target.apk

关键字搜索策略:在 jadx 搜索框中依次搜索 AESCBCencryptHMACsha256,定位加密函数位置。

典型的 AES 加密代码(jadx 反编译后)

// jadx 反编译后的加密函数(示例)
publicclassCryptoUtils{
// 硬编码的 Key 和 IV(可能在常量中,也可能动态下发)
privatestaticfinal String AES_KEY = "AbCdEfGhIjKlMnOp"// 16 字节 AES-128
privatestaticfinal String AES_IV  = "OpMnLkJiHgFeDcBa"// 16 字节 IV

publicstatic String encrypt(String plaintext)throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes("UTF-8"), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(AES_IV.getBytes("UTF-8"));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
return Base64.encodeToString(encrypted, Base64.DEFAULT);
    }
}

签名函数

// HMAC-SHA256 签名生成
publicstatic String generateSign(String data, long timestamp){
    String toSign = data + timestamp + "secret_key_here";
    Mac hmac = Mac.getInstance("HmacSHA256");
    SecretKeySpec keySpec = new SecretKeySpec("secret_key_here".getBytes(), "HmacSHA256");
    hmac.init(keySpec);
byte[] result = hmac.doFinal(toSign.getBytes("UTF-8"));
return bytesToHex(result);
}

10.4 第三步:Frida Hook 动态验证提取的密钥

静态分析提取的 Key 可能是动态计算的,通过 Frida 动态验证是最保险的方式:

// frida hook: 动态打印 AES 加密的 Key、IV 和明文数据
Java.perform(function({
var Cipher = Java.use("javax.crypto.Cipher");

    Cipher.init.overload(
"int",
"java.security.Key",
"java.security.spec.AlgorithmParameterSpec"
    ).implementation = function(mode, key, params{
if (mode === 1) { // 只关注加密操作
var keyBytes = key.getEncoded();
var keyHex = Array.from(newUint8Array(keyBytes))
                .map(b => b.toString(16).padStart(2"0")).join("");
console.log("[AES Cipher] Key (hex): " + keyHex);

try {
var IvParameterSpec = Java.use("javax.crypto.spec.IvParameterSpec");
var ivSpec = Java.cast(params, IvParameterSpec);
var ivBytes = ivSpec.getIV();
var ivHex = Array.from(newUint8Array(ivBytes))
                    .map(b => b.toString(16).padStart(2"0")).join("");
console.log("[AES Cipher] IV (hex): " + ivHex);
            } catch(e) {}
        }
returnthis.init(mode, key, params);
    };

// Hook doFinal 打印明文
    Cipher.doFinal.overload("[B").implementation = function(input{
var inputStr = Java.use("java.lang.String").$new(input, "UTF-8");
console.log("[AES doFinal] Input plaintext: " + inputStr);
var result = this.doFinal(input);
return result;
    };
});

运行后输出示例:

[AES Cipher] Key (hex): 4162436445664768496a4b6c4d6e4f70
[AES Cipher] IV (hex):  4f704d6e4c6b4a6948674665446342 61
[AES doFinal] Input plaintext: {"uid":"123456","action":"get_coin"}

10.5 第四步:Python 脚本重放接口

确认加密算法、Key、IV 和签名方式后,用 Python 完整还原请求生成逻辑:

# 接口重放脚本:还原 AES-CBC 加密 + HMAC-SHA256 签名
# 依赖:pip install pycryptodome requests

import json
import time
import hmac
import hashlib
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

# ===== 加密参数(从逆向分析中提取)=====
AES_KEY  = b"AbCdEfGhIjKlMnOp"# 16 字节 AES-128 密钥
AES_IV   = b"OpMnLkJiHgFeDcBa"# 16 字节 IV
HMAC_KEY = "secret_key_here"# HMAC 签名密钥


defaes_encrypt(plaintext: str) -> str:
"""AES-CBC 加密,返回 Base64 编码结果"""
    cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    padded = pad(plaintext.encode("utf-8"), AES.block_size)  # PKCS7 填充
    encrypted = cipher.encrypt(padded)
return base64.b64encode(encrypted).decode("utf-8")


defaes_decrypt(ciphertext_b64: str) -> str:
"""AES-CBC 解密"""
    ciphertext = base64.b64decode(ciphertext_b64)
    cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    decrypted = unpad(cipher.decrypt(ciphertext), AES.block_size)
return decrypted.decode("utf-8")


defgenerate_sign(data: str, timestamp: int) -> str:
"""HMAC-SHA256 签名生成"""
    to_sign = data + str(timestamp) + HMAC_KEY
    signature = hmac.new(
        HMAC_KEY.encode("utf-8"),
        to_sign.encode("utf-8"),
        hashlib.sha256
    ).hexdigest()
return signature


defcall_get_coin(uid: str, token: str) -> dict:
"""构造并发送 get_coin 接口请求"""
    payload = json.dumps({"uid": uid, "action""get_coin"}, separators=(","":"))
    encrypted_data = aes_encrypt(payload)

    timestamp = int(time.time())
    sign = generate_sign(encrypted_data, timestamp)

    request_body = {
"user_data": encrypted_data,
"timestamp": timestamp,
"sign": sign
    }

    headers = {
"Content-Type""application/json",
"User-Agent""ExampleApp/3.2.1 (Android; en-US)",
"Authorization"f"Bearer {token}",
    }

    response = requests.post(
"https://api.example.com/get_coin",
        json=request_body,
        headers=headers,
        timeout=10
    )

    resp_json = response.json()
if"data"in resp_json:
return json.loads(aes_decrypt(resp_json["data"]))
return resp_json


if __name__ == "__main__":
    result = call_get_coin(uid="123456", token="your_token_here")
    print("接口响应:", json.dumps(result, ensure_ascii=False, indent=2))

通过以上四步,完成了从"只能手动操作 App"到"Python 脚本全自动化"的完整逆向分析链路。


十一、总结与排查速查 SOP

11.1 抓包排查决策树

当抓包遇到问题,按下图流程逐步排查,定位根因后选择最低成本的解法:

抓包排查决策树

11.2 工具选型速查表

场景
推荐工具
备注
日常 HTTP/HTTPS 调试
Reqable PC 端
功能全面,首选
快速接入 Android(免手动配证书)
HTTP Toolkit
ADB 一键自动化配置
App 有代理检测
HttpCanary / Reqable 移动端
VPN 模式无感绕过
需要渗透测试功能
Burp Suite
Repeater/Intruder 强大
SSL Pinning 绕过(无 Root)
重打包 + network_security_config
无需 Root
SSL Pinning 绕过(有 Root)
JustTrustMe Xposed / Frida
一键通杀
混淆 App / 非 OkHttp 框架
OkHttpLogger-Frida / r0capture
反射定位
底层自吐通杀
r0capture(Android 7-14)
SSL 层 Hook
内核级无侵入捕获
eCapture(Android 13+)
eBPF uprobe
分析原始 TCP/UDP 流量
Wireshark + tcpdump
pcap 格式
按进程过滤底层流量
ptcpdump
eBPF 进程级过滤

11.3 最佳实践原则

原则一:优先成本最低方案

最佳实践原则一:优先成本最低方案

不要一开始就使用"核武器"——优先尝试最简单的方案,遇到阻碍再升级,这样能节省大量时间。

原则二:遇到加密协议先抓后逆

① 先用 r0capture 抓取原始包,确认请求/响应格式
② 再用 jadx 逆向找加密函数位置
③ Frida 动态验证 Key/IV 等参数
④ 最后 Python 脚本实现自动化重放

原则三:抓包工具与 Frida 配合

抓包工具负责观察数据结构(字段名、加密前后格式、响应逻辑);Frida 负责定位加密位置(在哪里加密、Key/IV 是什么、签名怎么生成)。两者配合能最快速地还原加密协议。

11.4 合规与红线警示

重要声明:本文涉及的所有技术均属于安全研究领域的通用技术手段,在合法授权的范围内使用具有重要的安全价值。

严格禁止的行为

  • 对未经授权的网络/系统进行抓包、爬取、攻击;
  • 利用抓包手段非法获取他人隐私数据、账号信息;
  • 将还原的 API 接口用于商业爬虫、黑产工具、刷单等非法用途;
  • 绕过版权保护进行盗版传播。

合法使用场景:自己或有授权的 App 安全评估、个人技术学习、负责任的漏洞披露、授权范围内的自动化测试。


工具与资源汇总

工具
地址
说明
Reqable
reqable.com
国产全能抓包工具
HTTP Toolkit
httptoolkit.com
开源现代抓包,ADB 一键接入 Android
Charles
charlesproxy.com
经典 macOS 抓包工具
Burp Suite
portswigger.net/burp
渗透测试必备
ProxyPin
github.com/wanghongenpin/network_proxy_flutter
开源全平台
JustTrustMe
github.com/Fuzion24/JustTrustMe
SSL Pinning 一键绕过
SSLUnpinning
github.com/ac-pm/SSLUnpinning_Xposed
Xposed SSL 绕过模块
OkHttpLogger-Frida
github.com/siyujie/OkHttpLogger-Frida
OkHttp 拦截器动态注入
r0capture
github.com/r0ysue/r0capture
Frida SSL 底层抓包
eCapture(旁观者)
github.com/gojue/ecapture
eBPF 内核级 TLS 捕获
Wireshark
wireshark.org
图形化流量分析
ptcpdump
github.com/mozillazg/ptcpdump
eBPF 进程级 tcpdump
jadx
github.com/skylot/jadx
Android APK 反编译
apktool
github.com/iBotPeaches/Apktool
APK 打包/解包工具
Frida
frida.re
动态插桩框架

文章版本:2026 年 3 月
适用系统版本:Android 4 - 16
风险提示:本文所有内容仅供安全学习与研究使用,请在授权范围内使用相关技术。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-03-25 20:04:41 HTTP/2.0 GET : https://c.mffb.com.cn/a/478122.html
  2. 运行时间 : 0.168654s [ 吞吐率:5.93req/s ] 内存消耗:4,533.55kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=5759a2895f95184abf78203ec5084b0e
  1. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/runtime/temp/cefbf809ba1a84190cb04b0cb7abcf79.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000788s ] mysql:host=127.0.0.1;port=3306;dbname=c_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000769s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000290s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000255s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000496s ]
  6. SELECT * FROM `set` [ RunTime:0.000214s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000532s ]
  8. SELECT * FROM `article` WHERE `id` = 478122 LIMIT 1 [ RunTime:0.000662s ]
  9. UPDATE `article` SET `lasttime` = 1774440281 WHERE `id` = 478122 [ RunTime:0.018026s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000332s ]
  11. SELECT * FROM `article` WHERE `id` < 478122 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000643s ]
  12. SELECT * FROM `article` WHERE `id` > 478122 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000389s ]
  13. SELECT * FROM `article` WHERE `id` < 478122 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000749s ]
  14. SELECT * FROM `article` WHERE `id` < 478122 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001119s ]
  15. SELECT * FROM `article` WHERE `id` < 478122 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000613s ]
0.170261s