feat(huya): 证书算法完全闭环 - 差分法证明标准AES-128-ECB并复现铸证
- NativeFunction直调差分: FIPS-197 KAT逐位一致, UdbAESUtil无魔改 - 证书 = b64([0x0C][key_idx][AES128-ECB(key16, zeropad(P1_187B))]) - P1结构: [010400][5008][u16+20B随机][u16+40B指纹hex][u16+114B hyCred] - 密钥: rodata默认三条(AESkeyMgr id=3/4/5) + 服务端下发会话钥(key_idx区分) - tools/cert_forge.py 重铸证书与活体密文 FULL MATCH
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# 虎牙 udb 登录证书(biz_token)算法 — 差分法完全闭环(2026-08-25)
|
||||
|
||||
> 状态:**加密算法 100% 复原,Python 重铸与活体密文逐位一致**
|
||||
> 方法:静态反汇编(objdump) + Frida NativeFunction 直调差分 + C1 构造器抓钥
|
||||
> 工具:`tools/udb_aes.py`(参考实现) `tools/cert_forge.py`(解析/铸造) —— 自检均通过
|
||||
> 证据:`evidence/aes_diff.json` `evidence/cert_keycap.json`
|
||||
|
||||
---
|
||||
|
||||
## 一、结论一句话
|
||||
|
||||
```
|
||||
证书 = base64( [0x0C][key_idx][ AES-128-ECB(key16, zeropad(P1_187B)) ] )
|
||||
```
|
||||
|
||||
- **UdbAESUtil 是教科书级标准 AES-128-ECB**,无任何魔改:
|
||||
- FIPS-197 KAT 直调逐位一致:`Cipher(00112233..ff, key000102..0f) = 69c4e0d8...`
|
||||
- KeyExpansion 标准展开,轮密钥按「字表转置」存储(176B @ this+0x208)
|
||||
- 对象布局:+0x00 vptr | +0x08 S-box拷贝 | +0x108 InvS-box拷贝 | +0x208 轮密钥
|
||||
- ZeroPadding:补 `\0` 到 16 倍数,**不追加整块**(187→192)。
|
||||
- 此前"标准解密对不上"的原因:**拿错了密钥**(真钥不是 HuyaUdb 主密钥字符串本身)。
|
||||
|
||||
## 二、P1 明文结构(187B,两份活体样本逐字段对齐)
|
||||
|
||||
| 字段 | 长度 | 说明 |
|
||||
|---|---|---|
|
||||
| `[01][04][00]` | 3 | 固定头 |
|
||||
| `"5008"` | 4 | appId |
|
||||
| `[u16_le=20]` + rnd | 22 | 每次生成随机(os.urandom 即可) |
|
||||
| `[u16_le=40]` + fp | 42 | 设备指纹 ASCII hex `02df39879743...`,设备绑定跨会话不变 |
|
||||
| `[u16_le=114]` + cred | 116 | **hyCred 二进制**(=base64(udb_cred) 解码),账号绑定 |
|
||||
|
||||
## 三、密钥机制(AESkeyMgr)
|
||||
|
||||
- rodata `0x1bc810` 内置三条 24 字符默认密钥(`AESkeyMgr::C2` 注册 id=3/4/5):
|
||||
```
|
||||
4VYcPdvKKqjBHZtCmbroRXHk ← 本次活体实测在用(encode_aes 收整条,C1 只取前16字节)
|
||||
xXEDWqiKLGwEZ6HubEiswCqK
|
||||
3FMHubdKosFrhmXNLHTNHZwe
|
||||
```
|
||||
- 证书第二字节 = **key_idx**:今日样本 `0x20` ↔ 上表第一条;更早样本 `0x50`
|
||||
用三条默认钥均解不开 ⇒ 存在**服务端下发的会话密钥**(对应 dckey/check 的
|
||||
NEWKEY/key_id 老线索)。服务端按 idx 选钥解密。
|
||||
- ⚠️ `HuyaUdb1928374650qwertyuiop` 是本地登录态文件加密用的主密钥,
|
||||
**不是**证书密钥(此前误判的根源)。
|
||||
|
||||
## 四、调用链(函数地址级)
|
||||
|
||||
```
|
||||
HandlerGetH5InfoEx::onHandler @0x38d548
|
||||
└ BusinessCfg::getOtp @0x2689f4
|
||||
└ gen_biz_token(BIZTOKEN,...) @0x3307e4 # P1 组装(enpack_header/body,cred_packls,xxtea)
|
||||
└ encode_aes(P1, key24str, out) @0x330218 # out.assign(常量); C1(key.data())
|
||||
├ UdbAESUtil::C1(uchar* key16) @0x24eb08 # ★抓钥点: 每次必经
|
||||
└ UdbAESUtil::encrypt @0x250038 # 补零逐块 -> _encrypt@0x24f9f0 -> Cipher@0x24f314(10轮)
|
||||
└ CBase64::Encode
|
||||
```
|
||||
|
||||
全部符号在 `.dynsym` 导出(binary stripped 但 dynsym 完整),可直接 NativeFunction。
|
||||
|
||||
## 五、复现步骤
|
||||
|
||||
```bash
|
||||
# 1) 差分验证(直调 C1/Cipher, FIPS-197 KAT)
|
||||
/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0/.venv/bin/python scripts/hook_aes_diff.py
|
||||
# 2) 抓当前会话证书密钥 + 完整 wupData
|
||||
/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0/.venv/bin/python scripts/hook_cert_keycap.py
|
||||
# 3) 离线重铸自检
|
||||
.venv/bin/python tools/cert_forge.py # FULL MATCH: True
|
||||
# 4) 参考实现自检
|
||||
.venv/bin/python tools/udb_aes.py
|
||||
```
|
||||
|
||||
frida 注意事项:手机端 frida-server 14.2.18,必须用 RE 项目 venv(frida==14.2.18);
|
||||
时序不可变:force-stop → spawn挂起 → bypass_msaoaid_maps_art_callsite +
|
||||
mask_frida_maps_only 双脚本 → resume → 10s → patch_guard → 业务脚本。
|
||||
直调 libc++ string 时**禁止让 push_back 触发 realloc**(会对 frida 缓冲区
|
||||
operator delete 导致 abort——第一次闪退即此因,非反调试)。
|
||||
|
||||
## 六、剩余开放项
|
||||
|
||||
1. **key_idx↔密钥映射的服务端语义**:0x20/0x50 的生成规则、下发通道
|
||||
(dckey/check? 登录态 JSON?)、轮换周期。工程上可绕过:直接 hook C1 取当期钥。
|
||||
2. **任意账号 hyCred 获取**(硬骨头②):APP WUP 密码登录已通,
|
||||
待从登录态/HA.getCred 提取目标账号 114B cred 即可离线铸其证书。
|
||||
3. 铸造证书的活体验证:新随机数重建证书 → bindQrLoginUser(下一步)。
|
||||
Reference in New Issue
Block a user