Files
live-hub-py/docs/Frida绕过配方.md
T

69 lines
5.0 KiB
Markdown

# Frida 绕过配方 — 虎牙 com.duowan.kiwi (13.4.22 arm64)
> ⚠️ **当前可用配方 = RE 仓库三脚本两阶段流程** (hook_final_capture.py 同款, 实测唯一稳定):
> `bypass_msaoaid_maps_art_callsite.js` + `mask_frida_maps_only.js` 挂起中加载 → resume → 11s → `patch_guard_block_termination.js`
>
> ⚠️ **`tools/frida/bypass_all.js` (合并版) 未通过验证 (R40)**: 三层健康检查显示卡加载页/延迟死亡,
> 最小化测试 A1-only 也不通, 与原版的实质差异未定位 (emit 死锁已修但仍有问题)。**别用**。
> `scripts/bypass_healthcheck.py` = 三层判定工具 (pid/界面轨迹/崩溃ANR+冻结探针), 可复用。
## 一、标准用法 (runner 模板)
```python
import frida, time
d = frida.get_device_manager().add_remote_device("127.0.0.1:31878") # frida-server -l 0.0.0.0:31878
pid = d.spawn(["com.duowan.kiwi"])
s = d.attach(pid)
from bypass_loader import load_bypass # scripts/ 在 sys.path (同目录运行即可)
load_bypass(s) # ← 唯一的绕过步骤, 可传参
d.resume(pid)
# 之后挂业务钩子 (挂业务 JS 的时机不再敏感 — patch_guard 已内置延迟)
sc = s.create_script(business_js)
sc.on("message", on_msg)
sc.load()
```
**参数** (经 `globalThis.BYPASS_OPTS` 注入):
| 参数 | 默认 | 说明 |
|---|---|---|
| `patch_guard_delay_ms` | 3000 | B 层 (终止拦截) 延迟安装毫秒数。App 启动期被杀 → 调大到 5000-11000; 启动卡死/合法退出被吞 → 调小到 1500 |
| `persist` | false | true 时写 `/data/user/0/<pkg>/cache/bypass-all-<pid>.jsonl` 调试日志 (每次掩盖/补丁事件) |
**设备侧前提**: root (magisk su) + `frida-server -l 0.0.0.0:31878` (必须 0.0.0.0, 否则 connection closed) + `adb forward tcp:31878 tcp:31878`
## 二、三层各自防什么
| 层 | 生效时机 | 对抗点 |
|---|---|---|
| **A1 msaoaid 补丁** | 立即 (dlopen 双路触发) | `libmsaoaidsec.so`: 线程名探测 (`gmain`/`gum-js-loop`/`linjector``pool-worker`), fd 扫描 (`linjector` 掩写), frida 检出后的清理/退出分支 (`0x1c4a0` → 直接跳继续路径), ART 完整性周期 callsite (`0x1ceec` NOP) |
| **A2 maps 内容掩盖** | 立即 | libc `open/open64/fopen/openat` 记录 maps fd → `read/pread64` 时把 `frida-agent`/`gum-js-loop`/`linjector` 掩写成无害串 (比 A1 更底层的兜底) |
| **B 终止拦截** | 延迟 (默认 3s) | `kill/tgkill/exit/_exit/_Exit/abort/raise` 对自身进程一概吞掉 (turing 检出后 `_exit` 静默退出的最后防线) + msaoaid crash-guard `0x20ca8` 补丁 |
**为什么 B 层要延迟**: 终止拦截会无差别吞掉 App 自己的 `exit/abort`。启动初期 (0-2s) 有合法退出路径 (初始化失败重试等), 过早替换会卡死/异常。之前 11s 是保守值, 实测 3s 即可; **如果换 App 版本后启动期就被杀, 优先把 `patch_guard_delay_ms` 调回 11000 再排查**
## 三、实战教训清单 (每条都付出过时间)
1. **绕过必须 spawn 挂起中加载**, attach 已启动进程 = 6/6 死 (登录态下更敏感)。
2. **spawn 实例"安静退出"无 crash 日志** = msaoaid `_exit` 静默退, 说明绕过没生效或时序错 — 先检查是否 resume 前加载、frida-server 是否带 `-l 0.0.0.0`
3. **别 hook GL/EGL 驱动里的同名导出** (libllvm-glnext/eglSubDriver 也有 `deflate`, 非 zlib ABI, 读错内存直接崩) — hook 系统库符号前先确认模块名。
4. **别 hook 热路径** (libz `inflate` = 图片解码): 首屏卡死、注册超时。要过滤: backtrace 含目标库才转储。
5. **OLLVM/无帧指针下 `Backtracer.ACCURATE` 会给假帧** — 用 `Interceptor``this.returnAddress` (真实立即调用方) 逐级爬, 或以必经外部导出 (如 libz `deflate`) 为锚点反查。
6. **sret 约定**: `md5(out&, in)` 的 x0 是输出槽, onEnter 读必空; 输入在 x1+。R34 曾因此误判"输入为空"。
7. **std::string 判读**: `b0&1==0` → SSO (len=b0>>1, data=+1); 否则 len@+8, data@*(+16)。
8. 业务 JS 里 **Java MessageDigest 钩子要在 8 分钟窗口类 runner 里限量** (证书解析会刷几千条)。
## 四、已知边界
- offset 表 (0x1c4a0/0x1ceec/0x20ca8 等) 对应 **13.4.22 arm64**`libmsaoaidsec.so`; App 升级需重新定位 (以绕过事件日志 + IDA 对照)。
- 模拟器上 A1 补丁因 EGL 竞争会崩 (原配方注释), 仅真机验证。
- 需要"清 turing 状态触发重注册"时: `rm -rf /data/data/com.duowan.kiwi/{app_turingdfp,app_turingfd}/*` + 删 `resinfo*` (**保留登录态, 别 pm-clear**)。
- 设备被风控限流 (登录超时) 时静置即可恢复; 与 frida 绕过无关。
## 五、历史配方存档
- 三脚本两阶段原版: RE 仓库 `evidence/scripts/{bypass_msaoaid_maps_art_callsite,mask_frida_maps_only,patch_guard_block_termination}.js`, 流程见 `scripts/hook_final_capture.py` (11s 稳定窗)。
- `bypass_msaoaid_maps_skip_cleanup.js`: 旧单脚本, 匿名启动路径可用, **登录态启动路径不可靠** (R38 实测秒死) — 已被 bypass_all.js 取代, 留作对照。