Skip to content

实战:抓 HTTP/1.1 明文 ​

这篇用 --selftest 抓一个最干净的 HTTP/1.1 明文样本,并完整还原请求和响应(含 gzip 解压)。

为什么用 selftest ​

真实 App(如 F-Droid)用 HTTP/2,是二进制帧,看着不直观。--selftest 让 App 进程内主动发一个 HttpsURLConnection 请求到 example.com——它默认走 HTTP/1.1,明文可读,最适合学习。

抓包 ​

bash
PID=$(adb -s 192.168.1.90:5555 shell "pidof org.fdroid.fdroid" | tr -d '\r')
python3 r0capture.py -H 127.0.0.1:27042 $PID --selftest -v -p http1.pcap

抓到的明文 ​

请求(SSL_write) ​

GET / HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 13; redroid13_x86_64 Build/TQ3A.230805.001.S1)
Host: example.com
Connection: Keep-Alive
Accept-Encoding: gzip

一行行全是明文!连 User-Agent 里的设备型号 redroid13_x86_64 都看得到。

响应(SSL_read) ​

HTTP/1.1 200 OK
Date: Wed, 01 Jul 2026 07:41:33 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Server: cloudflare
last-modified: Tue, 30 Jun 2026 20:58:35 GMT
allow: GET, HEAD
Age: 11523
cf-cache-status: HIT
Content-Encoding: gzip
CF-RAY: a143c4dc3f42b1b4-SJC

184        ← chunked: 第一个块大小 hex=0x184=388字节
<388字节 gzip 二进制>
0          ← 结束标记

解压 gzip 响应体 ​

响应是 Transfer-Encoding: chunked + Content-Encoding: gzip,要两步解:

python
import gzip
# body 是 chunked 编码
nl = body.find(b'\r\n')
chunk_size = int(body[:nl], 16)      # 0x184 = 388
chunk = body[nl+2:nl+2+chunk_size]
html = gzip.decompress(chunk)        # 解压
print(html.decode())                 # 明文 HTML

解压结果:

html
<!doctype html>
<html lang="en">
<head>
  <title>Example Domain</title>
  ...
</head>
<body>
  <div>
    <h1>Example Domain</h1>
    <p>This domain is for use in documentation examples...</p>
  </div>
</body>
</html>

关键观察 ​

这就是 r0capture 的核心价值——把加密的 HTTPS 还原成可读的 HTTP。

下一篇:抓真实 App 流量 →

基于 VitePress 构建 · 教学用途