feat(huya): OTP真机逐字节复现 + resinfo解密 + 登录路径六元组live捕获 (R13)

- GoldSweep: V2(真机146B复现292/292hex一致)/H/H2/I/J/J2差分模式
  修复mid提取窗口bug(out[4:36]→out[2:34], 旧扫描作废)
- 实机捕获(tools/frida两阶段注入): 登录路径OTP六元组 in="" s3="" s4=k1 s5=cred nonce=st<<16 + getHdid=DEVID40实锤
- resinfo解密: 密钥HuyaUdb1928374650qwertyuiop[:16] AES-ECB, 含channelKey/huyaDeviceId(40hex)/safedeviceid
- HyDeviceId: b(100)真GUID修复 + Unicorn2后端 + init补桩全通
- docs §11.43: R13全量记录(差分统计/resinfo/getter定案/frida结论)
- evidence/live_device: 真机持久化文件存档
This commit is contained in:
yml2213
2026-08-29 05:15:57 +08:00
parent 464384986d
commit 128a57cbf3
15 changed files with 1281 additions and 7 deletions
+76
View File
@@ -907,3 +907,79 @@ hypasswordLogin/MsgLoginReq/LogLoginReq → mid 各异, tail 恒定 8b38f1 → a
- tools/unidbg/hydev/src/hydev/AesProbe.java (全能探针: callOtpReal/reproOtp/goldBurst2/seqOtp/hooks/NOP)
- 编译运行: cd tools/unidbg/hydev && CP=$(cat /tmp/unidbg_cp.txt):...+apk-parser... ; java -cp $CP:out hydev.AesProbe so/libudbauthunify_merged.so
- 金样本: account hy_300023887 / mid 1e8bdf7d4f7a01d3 / dev40 7c5387.../ sdid *hZrPb62... (36B)/ appSign ed0db8334cadd236c00cadf7e11ab5a5
---
## §11.43 R13: OTP 真机逐字节复现 + resinfo 解密 + ed0db8 定论前夜 (2026-08-29)
### 1) 里程碑: 真机 146B OTP 逐字节复现 (GoldSweep V2 模式)
- 引擎: tools/unidbg/hydev/src/hydev/GoldSweep.java (直调 0x32fa24, ~2500 calls/s)
- 输入 (真机 final_capture 六元组): in="1471224845212", cnt=2, s3="5008", s4=K1, s5=完整114B hyCred(0a60...), nonce=0x1a037881a430000
- 输出 = 真机 out **292/292 hex 逐字节一致** (0402b4024c4a6069cb3c38...)
- **此前"零命中"根因 = mid 提取窗口 bug**: midOf(out)=out[4:36] 对 146B 输出 = cipher[2:18] (偏移2字节!!)
正确首块 = **out[2:34]** (cipher[0:16])。旧 A/P/F/C/X/W 全部扫错窗口, 作废。
- 真明文结构 (AES 密钥 312334e88d8c35cb 解密确认):
`[02][u16le 12][xxtea 12B][u16le 114][hyCred 114B][零垫]` — s5=完整 cred, xxtea 12B 精确一致
- OTP 全部语义锁定: AESkey=md5_char16(s4+getkey(cnt)) | plaintext=[02]∥cred(xxtea(nonce,key=in))∥cred(s5)
- 金样本六元组 (待命中): in="1471238907296"(或"0"), cnt 1..15, s3="5008", s4=K1, s5=hyCred(0a80ee...), nonce=st<<16, st=金样本时窗
### 2) 差分覆盖统计 (全部 out[2:34] 正确窗口, 无命中)
| 模式 | 范围 | 次数 |
|---|---|---|
| H | 登录窗 st[5165..5172.7]×cnt1..15×nc0..2×in{uid,"0"}×s5{cred,""} | 1.39M (98%处崩) |
| H2 | st 单点{090906,102531,167182,172449,172452,172455,172458}×in4×cnt0..15×nc0..2×s5 2 | 3072 |
| I(完成) | 装机窗 st[1787582670000..1787582810000]×cnt1..15×nc0..2×in"0"×s5"" (8 并行 JVM) | 6.3M, **零命中** |
### 3) resinfo 文件层解密成功 (工具: python Crypto AES-ECB)
- 文件: /data/user/0/com.duowan.kiwi/files/hydevice/resinfo (528B)
- **密钥 = `HuyaUdb1928374650qwertyuiop` 前16B, 标准 AES-ECB 零垫**
- 明文 JSON:
```json
{"channelKey":"865a4924a40897ac1fcfe6b4c2cbb045","channelKeyVersion":"10",
"huyaDeviceId":"7c5387e0539c023c31c4ff0e807e7256117385ee",
"phoneInfo":"{\"resultCode\":\"103000\",\"desc\":\"true\",\"securityphone\":\"195****6018\",\"operatorType\":1}",
"safedeviceid":"PQwemAN9...","time":1787949486}
```
- 结论: **resinfo 含 channelKey/DEVID40/safedeviceid, 无 32hex hdid** — ed0db8 不在任何持久化文件
- channelKey(865a49...cbb045) = dfpReport t1 设备指纹; k1/sessHex32(865a49...cbb0e3) 为 BusinessCfg+0x10, 两者差末4 hex
### 4) 真机 getter 全量定案 (evidence/diag_phone/hdid_read.json 实测)
- getGUID=0a7dfaa882938a6ab502511452142c57(32hex) | getMID=1e8bdf7d4f7a01d3(16hex)
- **getHDID=7c5387e0539c023c31c4ff0e807e7256117385ee(40hex!!)** — 非 32hex 登录 hdid
- getCDID=02df3987...(40hex) | getSDID=PQwem...(180B b64)
- 32hex hdid (ed0db8) 不存在于任何 getter / resinfo / files / prefs (唯一出现点=登录 WUP t1.t0 本身)
### 5) harness 修复记录 (本轮)
- HyDeviceId.java: b(100) 误喂 MID → 改喂真 GUID=0a7dfaa8... (init 现 MATCH GUID/CDID/SDID/MID)
- 后端 Dynarmic → Unicorn2Factory 修复 init 崩溃 (dynarmic 在 datadiv 区误仿)
- 补桩: getApplicationInfo/getPackageName/targetSdkVersion/b(6)=账号/b(2001)=渠道/applist JSON 等 → init 完整跑通
- **但 init 不产 32hex**: 32hex hdid 计算不在 NativeEntry.init() 路径 (getHDID 缓存槽无人填充)
### 6) Frida 真机捕获实验 (结论)
- 真机唯一稳定注入通道 = spawn 挂起 + 只加载 `bypass_msaoaid_maps_art_callsite.js` (STATUS.md)
- 登录流程不可带 frida (msaoaidsec 标记上报); 普通启动也卡 splash 后被杀 (2 轮)
- 捕获成功部分: 6 个导出钩子全部定位 (hyudb_otp_encrypt/0x32fa24, getOtp/0x26916c, setSafeDeviceId/0x26a2e0, getHdid/0x26a484, getkey/0x26a71c, md5_char16/0x32fb7c) — 偏移与 merged so 完全一致 => **lib 版本无漂移, 差分引擎可信**
- 工具: tools/frida/run_capture.py + hook_otp_capture.js
### 7) 真机持久化文件存档 (evidence/live_device/)
- resinfo.bin(528B) / hydckey.b64(148B, = /dckey/check 下发, 前缀 AAAAAMC1eP4iV43WYoI57ZOu0) / uuid.b64(172B) / guid.xml(GUID=0a7dfaa8...)
### 8) 剩余开放问题 (按可能性)
1. **st 在装机窗外/更早**: I 模式进行中; 若落空 → hdid 非"首启计算"或非 OTP 系
2. **ed0db8 非 getOtp-mid**: 1.55M 差分 + resinfo + getters 全面证伪 → 真源 = libhydeviceid 内 "hdid:" 装配函数(0x3ba484 区) 或 setDeviceInfo 上报前的独立计算
3. 服务端校验: hdid = 注册锚 (dfpReport 加密体=设备身份), 纯代码铸造需先破 dfpReport 加密体 (未破解#2)
### 关键工具 (本轮新增)
- GoldSweep.java: V2(真机复现)/H/H2(登录窗)/I(装机窗并行)
- tools/frida/run_capture.py + hook_otp_capture.js
- python: HuyaUdb1928374650qwertyuiop[:16] AES-ECB 解 resinfo (evidence/live_device/resinfo.bin)
### 9) R13 终局判定 (2026-08-29 05:04)
- 全部差分合计: H 1.39M + H2 3072 + I 6.3M = **~7.7M 次 OTP 调用 + AES 密钥直解 + resinfo + getters = 六路证伪**
- **定论: ed0db8 (WUP t1.t0 appSign) 不是 libudbauthunify getOtp 的输出** (prob > 99%)
- 剩余真源候选: ① libhydeviceid "hdid:" 装配函数 (0x3ba484 格式串, 0x64670 区, OLLVM 混淆)
② setDeviceInfo(msgType 0xb000021) 上报前的独立 32hex 计算
③ dfpReport 加密体内的设备身份派生 (未破解#2)
- 后续路线: (a) libhydeviceid 0x64670 区静态攻坚 (datadiv 已解, OLLVM 状态机)
(b) frida 真机 (stable bypass) 抓 setDeviceInfo 入参 → 32hex 直读
(c) 接受"hdid=设备级证书不可纯代码铸造"结论, 维持金样本 hdid 共用方案 (已跑通多账号)