# 虎牙登录系统全流程定案(R35-R39 终态) > 日期: 2026-08-29 · 状态: 纯协议账号密码登录无卡点, 一号一设备成立 > 本文是全链路终态总结; 算法细节见 `HUYA_HDID_ALGORITHM_GEN.md` §11.44-45 / §11.66-67。 ## 一、总体架构: 三个库, 三条链 ``` com.duowan.kiwi (13.4.22) │ ┌─────────────────────┼──────────────────────┐ ▼ ▼ ▼ libudbauthunify.so libhydeviceid.so libturingmfa/ga.so 账号登录(UDB) ★核心枢纽★ 腾讯turing SDK md5/AES/xxtea/OTP ├─ hdid 生成 (XXTEA 属 hdid 子系统, 账号级凭据 ├─ turing SDK 静态链接 与 dfpReport 无关) └─ dfpReport 加密(RC4) ``` `libhydeviceid.so` 是枢纽 — "45 个钩子零调用"之谜的答案: turing SDK 整个被静态 链接进该库, dfpReport 加密走库自身路径; `libz.deflate` 是它的必经外部导出 (R36 以此为锚点定位)。 ## 二、密钥/身份常量总账 (全部实锤) | 常量 | 值 | 存放位置 | 用途 | |---|---|---|---| | dfpReport RC4 key | `865a4924a40897ac1fcfe6b4c2abc798` | libhydeviceid .data (datadiv 加密) 字符串表 @3912240, 紧邻 "dfpReport" | 报文流加密。**APK 内嵌常量, 与设备无关** (R39) | | k1 | `865a4924a40897ac1fcfe6b4c2cbb0e3` | BusinessCfg+0x10 (同在 datadiv) | appSign 派生 + 登录 AESkey 派生 | | channelKey | `865a4924a40897ac1fcfe6b4c2cbb045` | resinfo (AES-ECB, key=`HuyaUdb1928374650qwertyuiop` 前16B), 服务端下发 | t1 设备指纹 | | appSign | `ed0db8334cadd236c00cadf7e11ab5a5` | 运行时算出 | = MD5("5008_13.4.22_" + k1), 跨账号稳定 (R15) | | hdid | 40hex (`7c5387e0...85ee`) | 设备派生 | getHDID / 登录身份 | | getkey 表 | (1,2)=`MKDKeridjing7avnsasdSDHI`, (1,3)=`nskdI7MDGKSDJsnadjdoonvs` | libudbauthunify .data | AESkeyMgr 按 (1,cnt) 取盐 | | xxtea key | 账号 UID (如 `1199666914671`) | 登录时填入 | UDB OTP 内层加密 | | Perseus 会话密钥 | 16字符 `[A-Za-z0-9]`, SecureRandom | 内存 (RSA 信封上行) | 独立通道, 与 dfpReport 无关 (R34) | ## 三、登录链 (UDB, 账号密码 → cred) 1. **WUP 封装**: 登录请求走 taf/wup POST `wsapi.huya.com`; `createWupRequestData@0x38dab0` 构造, t1.t0 = appSign 2. **OTP 生成** (全链语义 100% 定案 §11.44): `getOtp(uid, 2, 2, "5008", k1, cred, cnt, nonce)`, 明文 = `02 0c00 [12B xxtea(uid)] 7200 [114B cred]`, **AESkey = md5_char16(k1 + getkey(1,cnt))**, AES-ECB 3. **cred 凭据**: 账号级, 每次登录轮换; `cred0`/`credAnonymous` 落盘 (加密) 4. **会话密钥链**: `Perseus.a()` SecureRandom 16字符 → RSA 公钥封装 → guava{seq, env, KEY, d, expire} 上行 ## 四、dfpReport 链 (风控上报, R35-R37 完全攻破) ``` 采集指纹 JSON (~7-8KB: Athena + deviceinfo/Hebe_D1-D5 + guid + signature + terminal + version) → gzip (level 9, 头 1f8b08 00 00000000 02 03) → RC4(865a...c798) keystream 逐字节 XOR ← 密钥是 APK 常量! → wire body = [10B "magic"(=keystream⊕gzip头, 非真魔数)] + [密文] (+尾部10B) → taf/wup → POST wsapi.huya.com /dfpReport ``` - 触发配方: 清 `app_turingdfp/app_turingfd` + `resinfo*` (保留登录) → spawn → ~40s 自动重注册上报 - 服务端判定 (差分实验定论): 三元组在设备库 + collection 完整 → 回显 hdid; 否则动态随机 token - collection (行为数据) 不影响设备身份判定, 只影响动态/静态分级 - 历史验证: 12/12 历史密文解密 + 3 轮伪造密文逐字节一致 (`tools/dfp_rc4.py` selftest) ## 五、纯协议登录现状 (无卡点定案) 生产链已存在且跑通: ``` core/huya/dfp_register.py 每次登录前: getDfpConfig → selectOperator → dfpReport(零设备伪造) → 服务端签发 safedeviceid(t2) + device_id(t5, 40hex) core/huya/app_login.py WUP hypasswordLogin (账号密码, t2/t5 填入登录帧) → 正常: 直出新鲜 cred(114B) → 风控: safe_auth 滑块自动过验 (pt_auth JS 逆向闭环) → 重发直出 ``` ### R35-R39 带来的两个实质升级 1. **旧链隐形枷锁解除**: 旧伪造方式 = "一帧真实 wire 的 keystream 做 XOR 差分改明文", 受限于捕获帧 3625B 长度且共用捕获 keystream。现在密钥是 APK 常量, gzip+RC4 离线无限 生成, 伪造报文与真机**密码学不可区分** (同 app 版本真机每轮 keystream 也相同 — "magic" 恒定的原因)。 2. **伪造质量升级**: R36 解出的 12 份真实指纹 JSON (Athena/Hebe/guid/signature/terminal/ version 完整结构) 即标准模板, 可构造字段级真实 collection。 ### 一号一设备方案 - 每账号一套设备画像 (hdid 40hex, guid, Hebe_D1-D5, CDID) → 跑一次注册链 → 服务端签发该"设备"的 safedeviceid/device_id → 登录绑定 - 同一账号后续 dfpReport 保持同一套画像值 (自洽); 不同账号画像互不相同 - 滑块风控已有自动过验兜底 ### 留意点 (非卡点) 登录帧 t1.t0 的 32hex hdid 是"服务端硬锚" (libhydeviceid 设备 ID 体系), 注册链目前 用随机占位 — 实测服务端照常签发; 若风控升级开始校验 t1.t0, 需补 hdid 真实派生算法 (仓库最初主课题)。 ## 六、离线复原能力清单 **✅ 纯离线可做 (无设备)**: dfpReport 全伪造 (`tools/dfp_rc4.py`) · appSign 计算 · resinfo 加解密 · OTP 引擎 (V2 模型) · WUP 编解码 (`huya_wup_encoder.py`/`taf_decode.py`) · 历史密文批量解密 (12/12) **⚠️ 仍需真机**: 绕过配方 (唯一实测稳定 = RE 仓库三脚本两阶段流程; 合并版 bypass_all.js 未通过三层健康检查已弃用, 见 `Frida绕过配方.md`) · collection 完整采集逻辑 (Poseidon 反检测字段) · 换版本时 datadiv 常量重提取 (unidbg hydev harness 可离线做) ## 七、工具索引 | 工具 | 说明 | |---|---| | `tools/dfp_rc4.py` | dfpReport 编解码器 (rc4_keystream/decrypt/encrypt/gzip_wrap + CLI) | | `scripts/bypass_healthcheck.py` | 三层判定: pid 稳定 / 界面轨迹 / 崩溃 ANR + 主线程冻结探针 | | `scripts/hook_*.py` | 各钩子 runner; `hook_final_capture.py` 的两阶段时序为模板 | | `tools/frida/hook_deflate.js` | libz deflate 锚点钩 (只挂 libz.so; GL 驱动同名符号禁挂) | | `tools/frida/hook_hy.js` | RC4 key 捕获 (libhydeviceid!0x60e6c x1) | | `evidence/dfp_live/dec_*.json` | 12 份真实指纹明文 (伪造模板) | | `tools/unidbg/hydev/` | libhydeviceid 离线 harness (datadiv 解密) | ## 八、设备绑定实弹验证与 sdid 前缀定论 (R40 补充) - GUI 批量 App 登录实弹全通: 滑块过验 → cred(114B) → Cookie(720B) → 渠道记录。 - **sdid 前 22 字符 (`0UnHUgv0_qmfD4KAKlwzhq`) = hydevice SDK 协议常量**: 16 字节固定 密文头 (固定 key + 固定载荷头) 的 base64 前缀 — 所有使用 hydevice-prod-1.2.45 的 客户端 (含真机) 都相同, **不是设备关联信号**。决定性实验: 两套完全不同的设备参数 (xiaomi/samsung, 不同 UA/屏幕) 前缀依旧一致, 而 40hex hdid 每次全异。 - 一号一设备的三道真实隔离 (均已实装): 1. 画像: data/huya_device_profiles.json (机型/屏幕/CDID40/guid32/Hebe, 幂等补齐) 2. 采集输入: data/huya_fp_states/<账号>/device.json → env.js makeEnv(overrides) (UA/屏幕/机型按绑定画像生成, 决定性改变 collect 载荷) 3. 状态: data/huya_fp_states/<账号>/localstorage.json (df/token 持久化)