# 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= ``` 脚本实际执行内容: ```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= ``` 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": "", "accountType": "c2000004", "operatorType": "CU", "loginAuthCipherAsymmertric": "", "deviceUid": "", "shopId": "20002", "source": "110003", "systemVersion": "16", "androidId": "" } } } ``` 登录成功后,后续业务接口会带登录态字段: ```text provinceCode=600101 token= userLoginName= account= 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`。