ksjsb/docs/ecapture_android_runbook.md
2026-07-30 20:25:56 +08:00

439 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Android eCapture 抓包 runbook
本文记录本项目中已验证可复现的 Android eCapture 抓包流程。核心结论:
- 不需要代理、不需要安装 CA、不需要 Hook APP。
- 依赖设备 root、eBPF/uprobe 和 eCapture hook BoringSSL/Conscrypt。
- 当前设备普通 `adb shell` 看不到 `su`,但可通过 `bin.mt.termex` 的 root 授权间接执行。
## 1. 已验证环境
- 目标包名:`com.ct.client`
- 目标 UID`10409`
- root 方案SukiSU Ultra
- 已授权 root 的 APP`bin.mt.termex`
- eCapture 版本:`v2.5.2`
- 设备 eCapture 路径:`/data/local/tmp/ecapture`
- 设备 text 启动脚本:`/data/local/tmp/run_ecapture_dx.sh`
- 本地 text 启动脚本:`tools/ecapture/run_ecapture_dx.sh`
- 设备 pcap 启动脚本:`/data/local/tmp/run_ecapture_dx_pcap.sh`
- 本地 pcap 启动脚本:`tools/ecapture/run_ecapture_dx_pcap.sh`
- eCapture 目标 TLS 库:
- `/apex/com.android.conscrypt/lib64/libssl.so`
## 2. root 权限获取方式
普通 `adb shell``su` 不可见,这是本设备的正常现象:
```sh
adb shell id
adb shell su -c id
```
预期现象:
```text
uid=2000(shell)
su: inaccessible or not found
```
正确方式是通过已授权 root 的 `bin.mt.termex` 进入同一 root 授权上下文:
```sh
adb shell 'run-as bin.mt.termex id'
adb shell 'run-as bin.mt.termex /system/bin/su -c id'
```
成功时第二条应返回类似:
```text
uid=0(root) gid=0(root) ... context=u:r:ksu:s0
```
如果这里失败,优先检查:
1. SukiSU Ultra 是否仍启用。
2. `bin.mt.termex` 是否仍有 root 授权。
3. 命令必须走 `/system/bin/su`,不要依赖普通 shell PATH。
## 3. 一次性部署 eCapture
确认设备在线:
```sh
adb devices
```
确认目标 UID
```sh
adb shell 'cmd package list packages -U | grep com.ct.client'
```
部署 eCapture 二进制和启动脚本:
```sh
adb push tools/ecapture/ecapture-v2.5.2-android-arm64/ecapture /data/local/tmp/ecapture
adb shell 'chmod 755 /data/local/tmp/ecapture'
adb push tools/ecapture/run_ecapture_dx.sh /data/local/tmp/run_ecapture_dx.sh
adb shell 'chmod 755 /data/local/tmp/run_ecapture_dx.sh'
adb push tools/ecapture/run_ecapture_dx_pcap.sh /data/local/tmp/run_ecapture_dx_pcap.sh
adb shell 'chmod 755 /data/local/tmp/run_ecapture_dx_pcap.sh'
```
可选:检查设备是否支持 eBPF/uprobe
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c "mount | grep -E \"tracefs|bpf\"; zcat /proc/config.gz | grep -E \"CONFIG_BPF=|CONFIG_UPROBES=|CONFIG_DEBUG_INFO_BTF=\" 2>/dev/null"'
```
## 4. 启动抓包
### 4.1 text 模式:日常抽明文 body
直接运行项目脚本:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx.sh'
```
成功时输出:
```text
ecapture_pid=<pid>
```
脚本实际执行内容:
```sh
nohup /data/local/tmp/ecapture tls \
-m text \
--uid=10409 \
--libssl=/apex/com.android.conscrypt/lib64/libssl.so \
--ssl_version="boringssl 1.1.1" \
> /data/local/tmp/ecapture_dx.log \
2> /data/local/tmp/ecapture_dx.err &
```
检查进程:
```sh
adb shell 'ps -A | grep ecapture || true'
```
### 4.2 pcapng 模式:还原 HTTP/2 path/header
`text` 模式足够抽 JSON body但 HTTP/2 的 `:authority/:path`
依赖 HPACK 状态,文本日志不适合可靠还原。
需要闭合真实业务 URL 时,用 pcapng 模式:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx_pcap.sh'
```
默认网卡是 `wlan0`。如果需要指定接口:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c "/data/local/tmp/run_ecapture_dx_pcap.sh wlan0"'
```
可先用 root 查看设备接口:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c "ip -o link show"'
```
pcap 脚本实际执行:
```sh
nohup /data/local/tmp/ecapture tls \
-m pcap \
-i wlan0 \
-w /data/local/tmp/ecapture_dx.pcapng \
--uid=10409 \
--libssl=/apex/com.android.conscrypt/lib64/libssl.so \
--ssl_version="boringssl 1.1.1" \
tcp port 443 \
> /data/local/tmp/ecapture_dx_pcap.log \
2> /data/local/tmp/ecapture_dx_pcap.err &
```
注意pcap 脚本启动时会覆盖
`/data/local/tmp/ecapture_dx.pcapng`。如果要保留上一轮,先拉回本地。
## 5. 停止并拉取日志
PowerShell 模板:
```powershell
$stamp=Get-Date -Format 'yyyyMMdd_HHmmss'
$out="out\ecapture_case_$stamp"
New-Item -ItemType Directory -Force -Path $out | Out-Null
adb shell 'run-as bin.mt.termex /system/bin/su -c "pkill -f /data/local/tmp/ecapture || true; chmod 644 /data/local/tmp/ecapture_dx.log /data/local/tmp/ecapture_dx.err 2>/dev/null || true"'
adb pull /data/local/tmp/ecapture_dx.log "$out\ecapture_dx.log"
adb pull /data/local/tmp/ecapture_dx.err "$out\ecapture_dx.err"
adb pull /data/local/tmp/ecapture_dx.pcapng "$out\ecapture_dx.pcapng" 2>$null
adb pull /data/local/tmp/ecapture_dx_pcap.log "$out\ecapture_dx_pcap.log" 2>$null
adb pull /data/local/tmp/ecapture_dx_pcap.err "$out\ecapture_dx_pcap.err" 2>$null
adb shell 'uiautomator dump /sdcard/window_after_case.xml >/dev/null 2>&1'
adb pull /sdcard/window_after_case.xml "$out\window.xml"
adb shell screencap -p /sdcard/screen_after_case.png
adb pull /sdcard/screen_after_case.png "$out\screen.png"
adb shell 'dumpsys activity activities | grep -E "topResumedActivity|mResumedActivity" | head -n 20' |
Set-Content -LiteralPath "$out\activity.txt"
adb shell 'logcat -d -v time' | Set-Content -LiteralPath "$out\logcat.txt"
```
说明:
- `pkill` 只停止本次 eCapture 进程。
- 启动脚本会清空 `/data/local/tmp/ecapture_dx.log``.err`,所以每次启动前先确认上轮日志已拉回。
- 不要在用户点击流程中途停止 eCapture确认登录等动作必须在 eCapture 正在运行时执行。
## 6. 解析日志
本项目提供文本解析脚本:
```powershell
powershell -ExecutionPolicy Bypass -File tools\ecapture\parse_ecapture_text.ps1 `
-Log out\ecapture_case_xxx\ecapture_dx.log `
-OutJson out\ecapture_case_xxx\summary.json |
Set-Content -LiteralPath out\ecapture_case_xxx\summary.txt
```
解析输出会汇总:
- HTTP 请求method、host、path
- 302 跳转链:`Location`
- Cookie`Set-Cookie`
- 表单体:如 `appId/pk/ps/sign`
- JSON 业务 code`oneKeyLogin`
注意APP 大量接口走 HTTP/2。`-m text` 模式下HTTP/2 头压缩帧和 JSON body 可能混在一行,看到二进制乱码是正常现象;直接按 JSON 关键字抽取即可。
如果本轮采集了 pcapng用 Wireshark/tshark 抽 HTTP/2 头:
```powershell
powershell -ExecutionPolicy Bypass -File tools\ecapture\extract_http2_from_pcap.ps1 `
-Pcap out\ecapture_case_xxx\ecapture_dx.pcapng `
-OutTsv out\ecapture_case_xxx\http2.tsv
```
重点看:
- `http2.headers.authority`
- `http2.headers.path`
- `http2.headers.method`
- `http2.data.data`
业务登录已通过 pcapng 闭合以下 endpoint
```text
POST https://appgologinsz.189.cn/login/client/userLoginNormal
POST https://appgologinsz.189.cn/login/client/getAccessCodeDaily
POST https://appgologinsz.189.cn/login/client/oneKeyLogin
POST https://appgologinsz.189.cn/login/custIdInfo
```
## 7. 已验证抓包流程
### 7.1 无 Hook 启动 APP
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx.sh'
adb shell 'monkey -p com.ct.client -c android.intent.category.LAUNCHER 1'
```
已验证 APP 能进入:
```text
com.ct.client/.activity.MainActivity
```
代表性产物:
- `out/ecapture_nohook_20260720_081836`
### 7.2 进入“我”页
底部“我”tab 坐标约:
```text
x=972 y=2253
```
命令:
```sh
adb shell 'input tap 972 2253'
```
代表性产物:
- `out/ecapture_mytab_20260720_082333`
### 7.3 点击“一键登录”
“一键登录”按钮坐标约:
```text
x=174 y=411
```
命令:
```sh
adb shell 'input tap 174 411'
```
已抓到运营商预认证链:
```text
POST id6.me /auth/presdk.do
302 -> yw.wosms.cn /unicomAuth/openapi/qc
302 -> nisportal.10010.com:9001 /api
302 -> enrichgw.10010.com /d93222629f52ec79/api
302 -> yw.wosms.cn /unicomAuth/openapi/callback
302 -> ne189.21cn.com /openapi/networkauth/nm/spcallback/...
Set-Cookie: gw_auth=<COOKIE>
```
APP 侧业务上报:
```text
getAccessCodeDaily
```
代表性产物:
- `out/ecapture_login_tap_20260720_082514`
### 7.4 点击“确认登录”
确认登录前要保持 eCapture 正在运行。登录页有 `FLAG_SECURE`,截图可能是黑屏,但 `uiautomator` 仍能看到控件。
登录页控件状态示例:
```text
Activity: com.ct.client/.login.activity.SwitchUserActivity
tab: 本机登录
button: 确认登录
checkbox: 我已阅读并同意...
```
已抓到最终确认登录链:
```text
userLoginNormal
getAccessCodeDaily
oneKeyLogin
custIdInfo
loginNetworkReport
```
其中 `oneKeyLogin` 请求的字段结构为:
```json
{
"headerInfos": {
"code": "oneKeyLogin",
"clientType": "#13.3.0#channel45#OnePlus PJZ110#",
"source": "110003",
"sourcePassword": "Sid98s",
"timestamp": "yyyyMMddHHmmss",
"token": "",
"userLoginName": ""
},
"content": {
"attach": "test",
"fieldData": {
"pswType": "04",
"accessCode": "nm...",
"gwAuth": "<COOKIE_VALUE>",
"accountType": "c2000004",
"operatorType": "CU",
"loginAuthCipherAsymmertric": "<LONG_SECRET>",
"deviceUid": "",
"shopId": "20002",
"source": "110003",
"systemVersion": "16",
"androidId": "<ANDROID_ID>"
}
}
}
```
登录成功后,后续业务接口会带登录态字段:
```text
provinceCode=600101
token=<TOKEN>
userLoginName=<USER>
account=<ACCOUNT>
userId=<USERID>
```
代表性产物:
- `out/ecapture_confirm_login_20260720_082947`
## 8. 常见问题
### 普通 adb shell 里找不到 su
本设备就是这种状态。不要卡在 `adb shell su`,直接使用:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c id'
```
### eCapture 没有输出
按顺序检查:
1. `bin.mt.termex` 是否仍有 root 授权。
2. `run-as bin.mt.termex /system/bin/su -c id` 是否返回 root。
3. 目标 UID 是否仍是 `10409`
4. 目标是否使用 `/apex/com.android.conscrypt/lib64/libssl.so`
5. `/data/local/tmp/ecapture_dx.err` 是否有错误。
### 截图黑屏
登录页设置了安全窗口。黑屏不代表 APP 崩溃:
```sh
adb shell 'uiautomator dump /sdcard/window.xml'
```
`window.xml` 判断真实 UI。
### 为什么不用代理
这个 APP 在 Hook/代理场景容易卡启动或被壳逻辑干扰。eCapture 是内核侧 uprobes 抓 BoringSSL 明文绕过代理、CA、证书锁定和 APP 内部网络栈差异。
### HTTP/2 日志有乱码
正常。`-m text` 能拿到明文,但 HTTP/2 帧、HPACK 头和 JSON body 会混杂。现阶段优先用:
```powershell
Select-String -LiteralPath ecapture_dx.log -Pattern 'oneKeyLogin|userLoginNormal|ticket|token'
```
如果后续需要 Wireshark 级别解析,切换到 pcapng 模式:
```sh
adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx_pcap.sh'
```
再拉取 `/data/local/tmp/ecapture_dx.pcapng`,用
`tools/ecapture/extract_http2_from_pcap.ps1``:authority/:path`