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

11 KiB
Raw Permalink Blame History

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
  • 目标 UID10409
  • root 方案SukiSU Ultra
  • 已授权 root 的 APPbin.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 shellsu 不可见,这是本设备的正常现象:

adb shell id
adb shell su -c id

预期现象:

uid=2000(shell)
su: inaccessible or not found

正确方式是通过已授权 root 的 bin.mt.termex 进入同一 root 授权上下文:

adb shell 'run-as bin.mt.termex id'
adb shell 'run-as bin.mt.termex /system/bin/su -c id'

成功时第二条应返回类似:

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

确认设备在线:

adb devices

确认目标 UID

adb shell 'cmd package list packages -U | grep com.ct.client'

部署 eCapture 二进制和启动脚本:

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

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

直接运行项目脚本:

adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx.sh'

成功时输出:

ecapture_pid=<pid>

脚本实际执行内容:

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 &

检查进程:

adb shell 'ps -A | grep ecapture || true'

4.2 pcapng 模式:还原 HTTP/2 path/header

text 模式足够抽 JSON body但 HTTP/2 的 :authority/:path 依赖 HPACK 状态,文本日志不适合可靠还原。

需要闭合真实业务 URL 时,用 pcapng 模式:

adb shell 'run-as bin.mt.termex /system/bin/su -c /data/local/tmp/run_ecapture_dx_pcap.sh'

默认网卡是 wlan0。如果需要指定接口:

adb shell 'run-as bin.mt.termex /system/bin/su -c "/data/local/tmp/run_ecapture_dx_pcap.sh wlan0"'

可先用 root 查看设备接口:

adb shell 'run-as bin.mt.termex /system/bin/su -c "ip -o link show"'

pcap 脚本实际执行:

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 模板:

$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 -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
  • CookieSet-Cookie
  • 表单体:如 appId/pk/ps/sign
  • JSON 业务 codeoneKeyLogin

注意APP 大量接口走 HTTP/2。-m text 模式下HTTP/2 头压缩帧和 JSON body 可能混在一行,看到二进制乱码是正常现象;直接按 JSON 关键字抽取即可。

如果本轮采集了 pcapng用 Wireshark/tshark 抽 HTTP/2 头:

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

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

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 能进入:

com.ct.client/.activity.MainActivity

代表性产物:

  • out/ecapture_nohook_20260720_081836

7.2 进入“我”页

底部“我”tab 坐标约:

x=972 y=2253

命令:

adb shell 'input tap 972 2253'

代表性产物:

  • out/ecapture_mytab_20260720_082333

7.3 点击“一键登录”

“一键登录”按钮坐标约:

x=174 y=411

命令:

adb shell 'input tap 174 411'

已抓到运营商预认证链:

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 侧业务上报:

getAccessCodeDaily

代表性产物:

  • out/ecapture_login_tap_20260720_082514

7.4 点击“确认登录”

确认登录前要保持 eCapture 正在运行。登录页有 FLAG_SECURE,截图可能是黑屏,但 uiautomator 仍能看到控件。

登录页控件状态示例:

Activity: com.ct.client/.login.activity.SwitchUserActivity
tab: 本机登录
button: 确认登录
checkbox: 我已阅读并同意...

已抓到最终确认登录链:

userLoginNormal
getAccessCodeDaily
oneKeyLogin
custIdInfo
loginNetworkReport

其中 oneKeyLogin 请求的字段结构为:

{
  "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>"
    }
  }
}

登录成功后,后续业务接口会带登录态字段:

provinceCode=600101
token=<TOKEN>
userLoginName=<USER>
account=<ACCOUNT>
userId=<USERID>

代表性产物:

  • out/ecapture_confirm_login_20260720_082947

8. 常见问题

普通 adb shell 里找不到 su

本设备就是这种状态。不要卡在 adb shell su,直接使用:

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 崩溃:

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 会混杂。现阶段优先用:

Select-String -LiteralPath ecapture_dx.log -Pattern 'oneKeyLogin|userLoginNormal|ticket|token'

如果后续需要 Wireshark 级别解析,切换到 pcapng 模式:

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