继续破解进度

This commit is contained in:
yml2213
2026-08-26 18:28:33 +08:00
parent da2cf5a61d
commit 36325cf639
11 changed files with 608 additions and 15 deletions
+144
View File
@@ -127,3 +127,147 @@ t=3695: 17 f9 70 f9 b1 3c 4c be 77 74 14 ee 5e 7c e0 88 3a e2 c3 2c 72 63 8c 10
**验证 keystream 种子**:evidence/dfp_pair_sync.json 有 5 组同步 pair,
两组 keystream 差 vs 时间戳差 → 判断种子是否时间戳/计数器。
---
## 八、本会话重大发现(新!)
### 1. 输入结构确定: [恒定JSON 554B][collection ~3400B 每轮变化]
- 恒定 JSON(554B,已有全部字段,含 hdid/deviceId):`{"appId":"5008",...,"widthPixels":"1080"}`
- collection 是大 JSON:`{"touch_events":[...],"net_intfs":"...","phoneInfo":"{...}","qimei16/36":"...","risk_apps":"com.topjohnwu.magisk|bin.mt.plus|","scanned_appname":"<binary ~2900B>",...}`
- collection 尾部含 **Poseidon 反 frida 检测字段**:`"Poseidon_D1":"libhydeviceid.so|hooked:libhydeviceid.so|hooked:libc.so|"`, `Poseidon_D3:"zygisk|"`, `Poseidon_D5:"/product/bin/su\n|"`, `adb_input_list:"device_name=Virtual|"`(huyaudb 读 /proc/self/maps 检测 hook)
- collection 每轮变化(触摸事件/权限/网络/反检测结果/扫描二进制)
### 2. keystream 每轮变化,但跨轮/跨会话有强共享结构(非纯随机!)
多 session(6+ 个 pipeline 证据文件)9+ 轮 ks[0..553]=cipher[:554]^JSON 分析:
- **跨会话模板复用**:相同 10B 前缀在多个独立 session 反复出现!
- `07f970f9b8bc50be774e` ×3(155601-r1, 160316-r1, 160316-r2)
- `17f97019b93c6cbe7764` ×3(155601-r3, 160316-r3, 160855-r2, 170031-r2)
- `17f97ef9b83c6cbe774a` ×3(args session 多轮)
- `07f870f9b8bc50be774e` ×2(v2)
- 同一 session 连续轮次可完全相同(160316: r1 = r2 = `07f970f9b8bc50be774e`)
- 每位置 ks 值域很小:8 轮样本中大部分位置只有 2~8 个不同值(随机期望 8),前 6 字节仅 2~3 个值
- **高共享对**:r2(160855,t=18273) vs r5(170031,t=100816) 共享 140/554B(25%;随机期望 0.4%),最长连续 20B;r0 vs r4 共享 80B
- 结论:**keystream 不是每会话随机种子动态生成,而更像 固定模板库 + 状态选择**(生成器需进一步确认,但"所有字节每轮全新随机"的假设被推翻)
### 3. 反 frida 检测: hook 了 libhydeviceid 的事件, collection JSON 的 Poseidon 字段值相应变化(每轮检测结果不同)
### 4. 骨架 pipeline hook 已稳定(轻量,符合约定)
- `scripts/hook_dfp_pipeline.py` 只 hook 6 函数(topA_20e924/midA_5a938/cryptoA_5b1f4/copy_61098/pktA_7f744/pktB_92128)
- **必须遵守 hook 约定**:spawn → bypass x2 → resume+11s → patch_guard → **最后**加载主 hook JS(顺序颠倒会卡启动界面,已踩坑多次)
- 事件每轮:copy_61098 ×2(MAGIC 缓冲)、pktA/pktB(MAGIC + taf 段)、wire(密文全长)、jsonhits(内存搜 JSON 完整 554B)
- **GOT 桩方案已放弃**:144 个 br x17 桩 hook 太重,App 卡启动/卡点击(动态间接调用表 0x3ba000/0x3b9000 运行时才解密,静态也解不出)
### 5. 本地 capstone 反汇编(ELF vaddr==fileoff)
- cryptoA_5b1f4: 16 个 bl 目标(0x5f1b4 首调、0x45aa0×26、0x76ab0×9、0x461c0×6、0x6ec68×4、0x7398c×3、0x1f07ec×2…)
- 0x461c0/0x45aa0 = **间接调用桩**(adrp x16;ldr x17,[x16,#off];br x17),GOT 表运行时解密失败静态解析
- 0x5f1b4 = 字符串构建函数(状态机混淆),非生成器;cryptoA 主体无标量/NEON XOR 循环 → XOR 内核在间接调用或查表中
### 6. 下一步(铸造路线评估,优先!)
- 服务端旧结论:重放任意 wire body → HTTP 200,hdid/device_id = 明文回显
- 若 keystream 真是模板库,铸造新设备 = 改明文 JSON(hdid/deviceId) + 复用任意一轮 keystream XOR → 重放
- **行动**:纯 Python 构造新设备 t2(改明文 + 模板 ks)重放验证 200 → 若成功,铸造路线打通,生成器破解降级为可选
---
## 九、铸造路线实验(本会话最新,部分成功!)
### 1. 纯 Python 重放 100% 可行(不需要 keystream!)
- `scripts/forge_replay.py`:取证据里一帧完整 wire → 重构 HTTP/1.1 POST(Content-Length 等长) → socket+TLS 直连 `wsapi.huya.com:443`**原样重放返回 `HTTP/1.1 200 OK` + 344B 响应**(稳定复现)
- **XOR 自反性铸造**:`新密文 = 原密文 XOR (原JSON XOR 新JSON)`,JSON 区(554B)等长替换 hdid/deviceId/appkey,collection 区不动 → 不需要 ks、不需要生成器、不需要设备!
- 服务端**确实解析 t2 明文**(见下),不是纯透传 200
### 2. 响应结构(344B taf/wup 包)
- 4B 总长 + 头 + `huyaudbwebui` `dfpReport` + 字段:
- **t1 (tag22)**: `865a4924a40897ac1fcfe6b4c2cbb045` + `&` + base64(~43B,每次变化,像会话加密数据)
- **tag70**: `actionV(<40hex>` (设备标识回显)
- 40hex 之后有 taf 尾字段(0x0b 8c... 未解析)
### 3. 服务端行为(受控实验)
| 请求 | actionV(40hex) |
|---|---|
| baseline 原样 | `7c5387e0...17385ee`(**= 明文 hdid!**) |
| 只改 hdid | 新值(≠ 新 hdid,每次实验都不同) |
| 只改 deviceId | 新值(≠ 新 deviceId) |
| 用 actionV1 当 hdid 再上报 | 又一个新值(不稳定) |
- actionV 对 hdid/deviceId 变化均敏感 → **服务端解密解析了 t2 明文**
- baseline 时 actionV == 明文 hdid(服务端回显/认可当前设备)
- 改身份后 actionV 每次都是新值且不稳定 → 未确认"下发新设备身份"机制,可能 actionV 含时间戳/会话随机,或需配合后续登录流程
### 4. 待验证决策点
1. actionV 是否 = HMAC/带时间戳编码(需要多次同明文请求对照:两次同明文 → actionV 相同则与明文确定性相关;不同则含随机)
2. 需要抓完整登录流程(登录请求也用同一 hdid?)确认铸造出的新身份能否通过登录
3. 若 actionV 含随机/时间戳 → 服务端可能靠 t1 或其它字段做设备绑定 → 需重新审视铸造入口
---
## 十、29 轮 keystream 全量分析(决定性结论!)
合并 6+ session、29 轮 ks[0..553] 分析:
### 1. keystream 前缀模板复用(铁证)
```
17f97019b93c6cbe7764 x4: 160316r3, 160855r2, 170031r2, 175740r2 ← 4 个不同 session 同轮次位置!
07f970f9b8bc50be774e x3: 155601r1, 160316r1, 160316r2
17f97ef9b83c6cbe774a x3: args.j r3/4/5
07f870f9b8bc50be774e x2: v2 r1/r2
```
- 完整 10B 前缀跨 session 精确重复,**不是随机**
### 2. 同 session 完全重复
- **args.j r3 = r4 = r5: ks[0..553] 全部 554 字节相同!**(shared=554)
- v2 r1≈r2(51 共享),160316 r1≈r2(36 共享)
### 3. 高共享对(跨 session)
- 160855r2 vs 170031r2: **140/554 共享,最长连续 20B**
- 170031r3 vs 175740r3: 97 共享
- 170031r2 vs 175740r2: 70 共享,最长连续 31B
- 160855r1 vs 160855r4: 80 共享(同 session 首尾)
### 4. 结论
- **keystream 与"轮次序号/状态"强相关,同一序号位置在多个 session 复用相同(或高相似)ks**
- 不是每 session 随机种子;更像 **固定生成器 + 状态/序号选择**(同轮次位置 → 同 ks)
- 对铸造的含义:任意一帧真实 ks 即可加密伪造明文(服务端行为见下节,这是关键限制)
### 5. 服务端铸造验证(forge_replay.py 实测,重要!)
- **原样重放**:HTTP 200,344B 响应稳定,actionV = `7c5387...`(= 真 hdid,稳定回显)
- **改明文 JSON 任何身份字段(hdid/deviceId/appkey)**:200 OK,但 actionV 变为
`[32hex 类MD5] + "10" + [6hex]` 动态 token,同明文两次上报 token 不同
- 响应 t1(tag22)恒定 `865a4924a40897ac1fcfe6b4c2cbb045&base64`(base64 部分每次变化)
- **推论**:服务端识别"真设备"靠 明文三元组 (hdid, deviceId, appkey) 与库匹配;
纯改明文不匹配 → 动态 token → **铸造新设备需同时伪造三元组一致的完整设备身份**
(可能还要 collection 里 qimei/device_id 对应)否则服务端不认可
### 6. 下一步两个方向
A. **铸造**:找出服务端设备三元组的匹配逻辑(抓真实 App 首次注册流程/或抓登录后的完整身份链),
纯 Python 全真伪造(JSON+collection 齐改)重放验证 actionV 稳定性
B. **生成器**:既然 ks 与轮次序号相关,继续定位生成函数(0x5f1b4 初始化 + cryptoA 调用链),
复现 keystream 生成,任意轮次任意长度可算
---
## 十一、服务端设备绑定校验(差分实验定论!)
对 t2 密文做逐区差分修改重放,观察服务端响应:
| 修改内容 | actionV 结果 |
|---|---|
| baseline 原样 | **稳定回显真 hdid** `7c5387...` |
| JSON 非身份字段(widthPixels 1080→1081) | **稳定回显真 hdid**(不受影响!) |
| JSON 身份字段 hdid | 动态 token `[MD5样式32hex]10[6hex]`,每次不同 |
| JSON 身份字段 deviceId | 动态 token |
| JSON 身份字段 appkey | 动态 token |
| collection 区任意 1 字节(@560/@617/@753/@953 等) | 动态 token(波及全 collection) |
**结论:服务端绑定校验 = (hdid, deviceId, appkey 三元组) + (collection 完整性)**
- 服务端解密 t2 → 解析 JSON 三元组 + collection → 与库中设备匹配 → 匹配则回显设备 hdid,不匹配则返回动态 token
- **动态 token 不可复用**(同明文两次上报不同)→ 不是"注册下发",更像"未知设备拒绝标记"
- 铸造的真正瓶颈不是加密(已破解),而是**服务端以 (三元组, collection) 识别设备**
- collection 含 qimei16/36、scanned_appname 等指纹 → 需与三元组自洽才能被服务端认可
### 后续(铸造完整方案待定)
1. 抓真实 App **首次注册/重置设备后**的第一帧 dfpReport(看服务端如何初始分配设备 id)
2. 或逆向 collection 的指纹算法(哪些字段参与绑定)
3. 验证"设备上等长 patch hdid + App 自行生成 t2"路线(修复 patch 崩溃:可能因 JSON 长度校验/内存写坏)