SSL/TLS Hook 机制
这是 r0capture 最核心的原理:为什么 hook
SSL_read/SSL_write就能拿到明文。
TLS 加密的"分界线"
理解 r0capture,先要理解 TLS 在数据链路里的位置。SSL_read 和 SSL_write 这两个函数,正好是明文与密文的分界线:
SSL_write(明文)内部把明文加密成 TLS record,交给下层 TCP 发出去SSL_read()内部把 TLS record 解密,返回明文给调用方
在它们身上下钩子,拿到的天然是明文——这就是 r0capture 的全部秘密。
hook 的精确位置
r0capture 不是 hook Java 方法,而是 hook native 层的 OpenSSL/BoringSSL 符号:
SSL_write / SSL_read 是 libssl.so 导出的 C 函数。r0capture 用 Frida 的 Module.findExportByName 找到它们的地址,挂上 Interceptor.attach:
javascript
// script.js 简化示意
const ssl_write = Module.findExportByName(null, 'SSL_write')
Interceptor.attach(ssl_write, {
onEnter(args) {
// args[0]=SSL*, args[1]=buf, args[2]=len
this.buf = args[1]
this.len = args[2].toInt32()
},
onLeave(retval) {
// SSL_write 返回后,buf 里就是刚写入的明文
send({ type: 'ssl_write', src, dst }, this.buf.readByteArray(this.len))
}
})为什么绕过证书校验
证书校验/Pinning 发生在 SSL 握手阶段,而 SSL_read/write 是握手完成后才被调用的:
r0capture 的 hook 点在握手之后。所以:
- 校验通过 → 正常通信 → r0capture 抓到明文 ✅
- 校验没通过(Pinning 拒绝)→ App 根本不会调
SSL_write发业务数据 → 但这跟 r0capture 无关,App 自己连不上
Pinning 是"能不能通信"的问题,r0capture 是"通信了就抓得到"的问题,两者正交。
多版本 SSL 库的适配
不同安卓版本、不同 App,SSL 符号的位置和命名不同。r0capture 用通配符匹配 + 多候选:
这也是为什么 WebView/Flutter 抓不到——它们静态链接了自己的 BoringSSL,符号不导出到动态符号表,findExportByName 找不到。
下一篇:pcap 文件格式 →