灵寒谷
某App 抓包全流程技术文档

某App 抓包全流程技术文档

对 Android 端 xxx App 进行 HTTPS 抓包,获取其商品列表、商品详情、购买信息等核心业务 API 的请求与响应数据。

灵谷2026-04-08107321Markdown 发布

一、项目目标

对 Android 端 xxx App 进行 HTTPS 抓包,获取其商品列表、商品详情、购买信息等核心业务 API 的请求与响应数据。

二、难点分析

xxx App 采用了梆梆安全加固方案(Bangcle),拥有业内顶级的多层防护体系,几乎封堵了所有常规抓包手段:

防护层技术实现效果
代理检测libbangcle_risk.so 检测系统 HTTP 代理设置检测到代理后弹窗退出
VPN 检测检测 VPN 网络接口(tun0 等)检测到 VPN 后弹窗退出
SSL Pinning代码级 SSL 证书锁定(非 network_security_config.xml)HTTPS 请求无法被中间人解密
注入检测检测 Frida、Xposed 等注入框架的进程特征检测到后 native crash(fault addr 0xdeadcab1)
Root 检测检测 su 二进制、Magisk 等 Root 痕迹检测到后弹窗"设备异常"退出
模拟器检测libemulator_check.so + XOX SDK 多层检测x86 翻译层/内核特征/硬件特征全覆盖
完整性校验APK 签名校验 + SO 文件完整性校验修改 APK 或 SO 后闪退
风控 SDKcom.bangcle.everisk 运行时风控引擎采集设备信息并动态判定风险

核心挑战:这些防护层相互配合,要成功抓包必须同时绕过所有防护,单独突破任何一层都不够。

三、环境准备

3.1 硬件

设备规格说明
MacApple Silicon (macOS 15)抓包主机
Pixel 4 XLAndroid 11, 序列号 99111FFBA00BP3目标设备(必须真机,模拟器无法绕过检测)
USB 数据线USB-C连接 Mac 和手机

3.2 手机端软件

软件版本用途
Magiskv28.1 (28100)Root 方案 + 模块管理
Zygisk内置于 Magisk 28.1Shamiko 运行依赖
Shamikov1.2.1 (383)Root 隐藏(blacklist 模式)
LSPosedv1.9.2Xposed 框架(Zygisk 版,仅安装未对茅台启用模块)
xxxv1.9.4目标 App

3.3 Mac 端软件

软件版本用途
ADBAndroid SDK Platform-Tools设备通信
mitmproxy / mitmwebv12.2.1HTTPS 中间人代理 + Web 可视化界面
Python3.12+脚本工具 & ELF Patch

3.4 Magisk 关键配置

Zygisk:           已启用
Enforce DenyList: 已关闭 ← Shamiko 要求必须关闭
DenyList:         com.xxx.mall 及所有子进程已加入
Magisk App 包名:  已隐藏(随机化)

为什么用 Shamiko 而不是 DenyList?
Magisk 自带的 DenyList 隐藏能力较弱,梆梆安全的检测能穿透。Shamiko 通过 Zygisk 在更底层实现进程隔离,能有效隐藏 Root 和 Magisk 痕迹。但 Shamiko 要求关闭 Enforce DenyList(由 Shamiko 自己接管)。

四、失败的方案(踩坑记录)

在找到最终方案前,经历了大量尝试。记录这些失败对理解 App 的防护强度非常有价值。

4.1 模拟器方案(全部失败)

#方案失败原因
1MuMu 模拟器 + Frida hookXOX SDK 检测到 x86 翻译层,native crash
2MuMu + LSPosed + Device EmulatorXOX native 层检测绕不过
3MuMu + Shamiko同上
4AVD ARM64 (API 34, 干净)弹窗"非安全场景"(模拟器内核特征被检测)
5AVD + Magisk + LSPosedXOX 检测到 root,crash
| 6 | AVD + Frida Server | 被检测,crash (state=543) |
| 7 | AVD + Frida Gadget (改名 libhelper.so) | XOX 通过文件内容特征识别 Frida,crash |

| 8 | AVD + resetprop 改属性 | 部分属性改成功,但内核级特征改不了 | | 9 | AVD + patch libemulator_check.so | 绕过完整性校验后,libhaotiansec.so 内部还有检测 | | 10 | AVD + patch 所有安全 so 的 init_array | 加固壳不工作,app 卡住 | | 11 | AVD + 选择性 patch init_array | 每个 init 函数都是加固壳需要的,不能动 |

结论:模拟器路线完全不可行,必须使用真机。

4.2 真机方案演进

#方案结果
1Magisk 23.0 + MagiskHide旧版 XOX 检测到 root,crash
2Magisk 26.4 + DenyList不够强,还是被检测
3Magisk 26.4 + Shamiko v1.0.1还是被检测
4Magisk 28.1 + Shamiko v1.2.1旧版 正常运行 ✓
5更新apk后新版 everisk 检测到异常,10 秒退出

4.3 抓包方案(早期全部失败)

方案失败原因
mitmproxy + 系统代理App 检测到代理设置
VPN 模式抓包App 检测到 VPN
Xposed SSL Bypass 模块被 App 检测到 Xposed 注入,直接退出

五、最终成功方案(分层绕过)

最终的方案是多层协同绕过,每一层解决一个特定的防护问题,且不触发其他防护:

┌─────────────────────────────────────────────────────┐
│                    i茅台 App                         │
├─────────────────────────────────────────────────────┤
│  Layer 5: 风控 Activity 禁用                        │ ← pm disable
│  Layer 4: 代理/VPN 检测绕过                         │ ← patch libbangcle_risk.so
│  Layer 3: SSL Pinning 绕过                          │ ← patch libssl.so
│  Layer 2: Root 隐藏                                 │ ← Shamiko v1.2.1
│  Layer 1: Root 权限                                 │ ← Magisk 28.1
├─────────────────────────────────────────────────────┤
│  Android 11 (Pixel 4 XL)                            │
└─────────────────────────────────────────────────────┘
```###
5.1 Layer 1 & 2:Root + Root 隐藏

**Magisk 28.1 + Shamiko v1.2.1 (blacklist mode)**

-   Magisk 提供 root 权限和模块管理
-   Shamiko 在 Zygisk 层面对 i茅台进程隐藏所有 Root 痕迹
-   DenyList 中加入 `com.xxx.mall` 及其所有子进程
-   Magisk App 自身包名也做了隐藏(随机化)

### 5.2 Layer 3:SSL Pinning 绕过 —— Patch libssl.so + Mount Bind

这是最关键的技术环节。app没有使用 `network_security_config.xml`,SSL Pinning 在代码中通过 BoringSSL 的验证函数实现。

#### 原理

Android 11 使用 **conscrypt APEX** 模块提供 SSL/TLS 实现,其中的 `libssl.so` 包含证书验证函数。通过 patch 这些函数,可以让所有 SSL 验证都变成"不验证"模式。

#### 步骤

**① 从手机拉取原始 libssl.so**

```bash
# 找到 conscrypt APEX 中的 libssl.so
adb shell "su -c 'find /apex/com.android.conscrypt -name libssl.so'"
# 输出: /apex/com.android.conscrypt/lib64/libssl.so

# 拉取到本地
adb shell "su -c 'cp /apex/com.android.conscrypt/lib64/libssl.so /data/local/tmp/libssl_orig.so && chmod 644 /data/local/tmp/libssl_orig.so'"
adb pull /data/local/tmp/libssl_orig.so /tmp/libssl_orig.so

② 用 Python 脚本 Patch(patch_libssl.py)

脚本解析 ELF 文件的动态符号表,找到 4 个 SSL 验证函数,将每个函数的第一条 ARM64 指令替换为 MOV W1, #0:

# ARM64 指令: mov w1, #0
# 将 SSL 验证模式参数强制设为 SSL_VERIFY_NONE (0)
MOV_W1_0 = struct.pack('<I', 0x52800001)

# 目标函数
targets = [
    'SSL_CTX_set_verify',       # 设置 SSL 上下文验证模式
    'SSL_set_verify',           # 设置 SSL 连接验证模式
    'SSL_CTX_set_custom_verify', # 设置自定义验证回调
    'SSL_set_custom_verify',     # 设置自定义验证回调
]

为什么 patch W1 而不是直接 RET? ARM64 调用约定中 W1 是第二个参数(mode),将其设为 0 即 SSL_VERIFY_NONE。函数仍然正常执行后续逻辑(设置回调指针等),只是验证模式变成了"不验证",这比直接 RET 更稳定。

③ 推送并用 Mount Bind 替换

# 推送 patched 文件到手机
adb push /tmp/libssl_patched.so /data/local/tmp/libssl_patched.so

# 使用 Magisk 的 --mount-master 进行 mount bind
# 这样不修改原始文件,绕过完整性校验
adb shell "su --mount-master -c 'mount --bind /data/local/tmp/libssl_patched.so /apex/com.android.conscrypt/lib64/libssl.so'"

④ 验证 mount bind 生效

# 比较 MD5,应该一致
adb shell "su -c 'md5sum /apex/com.android.conscrypt/lib64/libssl.so /data/local/tmp/libssl_patched.so'"

为什么用 Mount Bind 而不是直接替换文件?
APEX 模块是只读挂载的,无法直接修改文件。Mount Bind 在文件系统层面将一个路径"覆盖"到另一个路径上,读取目标路径时实际读到的是我们的 patched 文件。这完全不影响原始文件,App 的完整性校验检查的是 APK 签名,不会发现 SO 被替换了。

5.3 Layer 4:代理/VPN 检测绕过 —— Patch libbangcle_risk.so

新版增加了 libbangcle_risk.so(梆梆风控 SDK),其中包含代理和 VPN 检测逻辑。

Patch 方案(patch_bangcle.py)

脚本解析 ELF 的 DYNAMIC 段(因为 section header 被混淆),通过字符串引用搜索找到 JNI_OnLoad 函数入口,patch 为直接返回 JNI_VERSION_1_6:

# 找到 JNI_OnLoad 的函数序言 (STP x29, x30, [sp, #imm]!)
# 替换为:
#   movz w0, #6         → 0x528000c0
#   movk w0, #1, lsl #16 → 0x72a00020  (w0 = 0x10006 = JNI_VERSION_1_6)
#   ret                  → 0xd65f03c0

同时 patch .init_array 和 DT_INIT 中的初始化函数为 RET,禁止风控 SDK 在库加载时执行任何初始化逻辑。

部署方式同样用 Mount Bind:

adb push /tmp/libbangcle_risk_patched.so /data/local/tmp/libbangcle_risk_patched.so
adb shell "su --mount-master -c 'mount --bind /data/local/tmp/libbangcle_risk_patched.so /data/app/<包路径>/lib/arm64/libbangcle_risk.so'"
```###
5.4 Layer 5:禁用 Everisk 风控 Activity

即使 patch 了 `libbangcle_risk.so`,风控 SDK 仍可能通过 Java 层检测到异常并启动退出页面。解决方案极其巧妙——**直接禁用风控 Activity 组件**:

```bash
adb shell "su -c 'pm disable com.moutai.mall/com.bangcle.everisk.core.c'"

原理:风控检测发现异常后,会尝试启动 com.bangcle.everisk.core.c 这个 Activity 来显示"设备异常"的退出页面。禁用这个组件后,Activity 无法启动,但 App 的主进程不会因此崩溃——它只是无法显示退出弹窗了,于是静默地继续运行。

注意:每次重启手机后需要重新执行此命令。

5.5 CA 证书安装

mitmproxy 的 CA 证书通过 Magisk 模块安装到系统级信任存储:

# 在手机上创建 Magisk 模块目录
mkdir -p /data/adb/modules/mitm_cert/system/etc/security/cacerts/

# 将 mitmproxy CA 证书(~/.mitmproxy/mitmproxy-ca-cert.cer)
# 转换为 Android 系统证书格式并推送到该目录
# 文件名格式: <hash>.0

安装后重启,证书出现在"系统" → “安全” → "信任的凭据"中。

六、抓包操作步骤

所有绕过措施准备好后,每次抓包的操作流程如下:

6.1 启动流程

# 1. 连接手机(USB)
adb devices -l
# 确认: 99111FFBA00BP3  device  usb:0-1  ...

# 2. 禁用风控 Activity(每次重启后需要)
adb shell "su -c 'pm disable com.xxx.mall/com.bangcle.everisk.core.c'"

# 3. 验证 SSL mount bind 是否还在(重启后会失效)
adb shell "su -c 'md5sum /apex/com.android.conscrypt/lib64/libssl.so /data/local/tmp/libssl_patched.so'"
# 如果 MD5 不一致,需要重新 mount bind:
# adb shell "su --mount-master -c 'mount --bind /data/local/tmp/libssl_patched.so /apex/com.android.conscrypt/lib64/libssl.so'"

# 4. 设置 USB 端口转发
adb reverse tcp:8080 tcp:8080

# 5. 设置系统代理
adb shell "settings put global http_proxy 127.0.0.1:8080"

# 6. 启动 mitmweb(带可视化 Web 界面)
mitmweb -p 8080 --web-port 8081 \
  --set block_global=false \
  --set web_password='你的密码' \
  --showhost \
  --no-web-open-browser

# 7. 浏览器打开 http://127.0.0.1:8081 查看抓包界面

# 8. 启动 App
adb shell "monkey -p com.xxx.mall -c android.intent.category.LAUNCHER 1"
```###
6.2 代理工作原理

┌──────────────┐ USB (adb reverse) ┌──────────────┐ │ Pixel 4 XL │ ──── 127.0.0.1:8080 ──→ │ Mac │ │ │ │ │ │ App │ │ mitmweb │ │ ↓ 系统代理 │ │ :8080 代理 │ │ 127.0.0.1 │ │ :8081 Web UI │ │ :8080 │ │ │ └──────────────┘ └──────────────┘ ↑ ↑ patched libssl.so 浏览器查看流量 (SSL 验证已禁用) http://127.0.0.1:8081


**关键点**:

-   `adb reverse tcp:8080 tcp:8080` 让手机的 `127.0.0.1:8080` 映射到 Mac 的 `8080` 端口
-   系统代理设为 `127.0.0.1:8080`,所有 HTTP(S) 流量都走代理
-   因为 `libssl.so` 已被 patch,App 不会拒绝 mitmproxy 的证书
-   因为 `libbangcle_risk.so` 已被 patch,App 不会检测到代理

### 6.3 停止抓包

```bash
# 关闭系统代理
adb shell "settings put global http_proxy :0"

# 移除端口转发
adb reverse --remove tcp:8080

# 停止 mitmweb (Ctrl+C 或)
kill $(pgrep -f mitmweb)
```##
七、已抓到的关键 API

### 7.1 商品详情(静态 CDN,无需登录)

```GET
https://static.xxxx.com.cn/mt-backend/xhr/front/mall/item/detailV2/{spuId}
```-
返回:商品名称、价格、SKU 信息、图片、评论数据

### 7.2 购买信息(H5 WebView,需登录)

```POST
https://h5.xxx.com.cn/xhr/front/mall/item/purchaseInfoV2
Body: {"hot": true, "spuId": "IMTP1000313", "jt": "anonymous"}
```-
返回:库存数量、开售时间、限购数量、购买资格
-   **注意**:此接口使用 H5 WebView 的 Token(`MT-Token-Wap`),与 Native App 的 `MT-Token` 不同

### 7.3 认证方式区别

| API 来源 | Token 类型 | 传递方式 |
| --- | --- | --- |

| Native App API (app.xxx.com.cn) | MT-Token | HTTP Header | | H5 WebView API (h5.xxx.com.cn) | MT-Token-Wap | Cookie |

Token 需要从抓包中的 Cookie 字段获取。

## 八、自动化脚本

### 8.1 项目文件结构

frida/ ├── patch_libssl.py # Patch libssl.so 脚本 ├── patch_bangcle.py # Patch libbangcle_risk.so 脚本 ├── export_apis.py # mitmproxy 流量导出脚本 ├── captured_apis.json # 抓包导出的 API 数据 ├── PROJECT_STATUS.md # 项目状态文档 ├── TECHNICAL_GUIDE.md # 本文档 └── login/ ├── login.py # 登录 & 签名工具 ├── credentials.json # Native App 登录凭证 ├── h5_token.json # H5 WebView Token ├── item_detail.py # 商品详情 API 调用脚本 ├── get_items.py # 资源配置获取 └── shop_items.py # 门店商品查询

8.2 使用方法

```bash
# 查询商品详情和购买信息
cd frida/login
python3 item_detail.py

# 查询单个商品
python3 item_detail.py product_id
```##
九、注意事项

### 9.1 重启后需要恢复

手机重启后以下设置会失效,需要重新执行:

1.  **Mount Bind**:`libssl.so` 和 `libbangcle_risk.so` 的 mount bind 都会丢失
2.  **风控 Activity 禁用**:`pm disable` 的状态会被重置
3.  **系统代理**:需要重新设置

### 9.2 时间同步

手机没有 SIM 卡时自动时间同步可能不工作,需要手动同步:

```bash
adb shell "su -c 'date $(date +%m%d%H%M%Y.%S)'"
```###
9.3 mitmweb 认证

mitmproxy 12.x 默认对 Web UI 启用认证,启动时需要设置 `--set web_password='密码'`,然后在浏览器中输入密码。

### 9.4 Token 有效期

```-
Native Token (`MT-Token`):有有效期,过期需要重新登录
-   H5 Token (`MT-Token-Wap`):每次 App 打开 WebView 时自动获取,需要从抓包中更新
```##
十、技术原理总结

### 为什么这个方案能成功?

1.  **真机 + Shamiko**:从进程级别隐藏 Root,梆梆安全无法通过常规检测手段发现
2.  **Mount Bind**:在文件系统层面替换 SO,不修改 APK,绕过完整性校验
3.  **Patch 验证函数而非直接 RET**:保持函数正常执行,只改变验证模式参数,减少崩溃风险
4.  **禁用风控 Activity**:不阻止检测本身,而是阻止检测结果的"执行"——让 App 检测到异常但无法退出
5.  **USB + adb reverse**:代理流量走 USB 而非 WiFi,减少网络层面的检测面

### 每一层的不可替代性

-   去掉 Shamiko → Root 被检测 → App 退出
-   去掉 libssl patch → SSL Pinning → 无法解密 HTTPS
-   去掉 bangcle patch → 代理被检测 → App 退出
-   去掉 pm disable → 风控弹窗 → App 强制退出
-   去掉 mitmproxy CA → 证书不被信任 → 连接失败

**五层缺一不可。**

留言互动

共 0 条