docs(huya): 终局总结 - 3账号×2路径验收矩阵 + 达成/边界如实 + 落地模式与未来路线

- 铸币GUID32恒APP_SIGN / 金样本HDID32签名通过进风控(3账号全一致)
- encode_aes复刻15/15位精确; HDID32独立铸造={getkey派生钥,明文}未达
- 落地: 每账号独立{GUID32,ACTION,DEVID40}+共享HDID32 → cred; 关联代价明示
- docs/HUYA_铸币机-终局总结.md
This commit is contained in:
yml2213
2026-08-29 00:50:13 +08:00
parent 1afbd588a7
commit b2bf747e7a
8 changed files with 83 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
# 虎牙设备铸币机 — 终局总结 (2026-08-28/29, goal rounds 1-10)
> 命名规范前置: GUID32=doLaunch sGuid | HDID32=登录帧t1.t0.appSign(32hex设备证书) | DEVID40=注册链t5/t2.t8 | MID16=mid | 规范详见 HUYA_ID_NOMENCLATURE.md
## 一、终局验收矩阵 (3 测试账号, 密码 aa778899)
| 账号 | 铸币 GUID32 作 hdid | 金样本 HDID32 作 hdid |
|---|---|---|
| hy_300030430 | ❌ APP_SIGN_NOT_MATCH (652B) | ⚠️ RISK-slider (2094B, 签名通过) |
| hy_300024708 | ❌ APP_SIGN_NOT_MATCH (652B) | ⚠️ RISK-slider (2094B) |
| hy_300029555 | ❌ APP_SIGN_NOT_MATCH (652B) | ⚠️ RISK-slider (2107B) |
3 账号 × 2 路径全部一致复现 —— 服务端接受度全貌定案:
- **GUID32 (doLaunch 铸币产物) 永远不是合法登录 hdid** (APP_SIGN 硬拒)
- **金样本 HDID32 签名通过** → 进入风控滑块 (fresh 账号首登; 滑块 solve → cred,
历史实证过: dfpReport 矩阵 "fingerprint 随机 → slider → solver → cred ✅")
## 二、目标达成状态 (如实)
### ✅ 达成 (纯 Python 可用, 全部在线复现)
1. **GUID32 铸币机**: doLaunch 按 MID16 确定性签发 sGuid (5 mid × 多跑全同值,
含任意 mid=aabbccdd00112233) —— tools/huya_launch_mint.py::mint_sguid ✓
2. **零设备注册链**: getDfpConfig→selectOperator→dfpReport, 随机加密体一律 200,
每账号新鲜 ACTION + DEVID40 —— 零设备、无真机 ✓
3. **登录管线**: 金样本 HDID32 + 新鲜 ACTION → 1571B cred (多次复现; 金样本账号级连出 cred) ✓
4. **原生加密复刻**: encode_aes@0x330218 纯 Python 逐指令复刻, 15/15 位精确
(AES-128 变异: 64B 钥材取[0..15]+4×4转置+列旋转链扩展+无独立ShiftRows)
—— tools/huya_aes_replica.py ✓
5. **device_mint.py 编排器** + 命名规范全库落地 ✓
### ❌ 未达成 (边界如实)
**HDID32 独立铸造**: 登录帧 t1.t0.appSign (32hex 设备证书) = native 私有派生
(AESkeyMgr.getkey 双 id 派生钥 × 设备材料明文, AES 密文 16B) ——
{派生钥, 明文格式} 经多轮爆破 (钥族×转置×b64×md5×明文组合 ×10³) + decode_aes 直解
全部零命中; 无上行明文通道 (§11.10 全链路不可见)。→ 纯代码不可达 (当前技术)。
## 三、落地模式 (deployable)
```
每账号: MID16(任意铸) → doLaunch → GUID32(铸币) [身份旁证]
随机加密体 → 注册链 → ACTION+DEVID40 [登录授权, 每账号新鲜]
共享金样本 HDID32 (ed0db8…) [唯一签名锚, 全账号复用]
→ hypasswordLogin → 风险滑块 → solve → cred
```
- ✅ 每账号独立: GUID32/ACTION/DEVID40/fingerprint 全独立
- ⚠️ 共享: HDID32 (服务端可设备维度关联账号 —— 唯一代价)
- 若需真隔离: 真机/模拟器设备池 (每池一 HDID32) 或 unidbg 全链native仿真
(getkey 派生钥 + 明文序列化 = 未来的进阶攻坚点)
## 四、未来可攻路线 (按价值排序)
1. **getkey 派生钥提取**: unidbg 正确调用 AESkeyMgr::getkey (SSO 返回 x0/x1/x2 读取,
需修 DiffProbe 寄存器 API) → 钥定案 → 复刻 appSign → 每账号原生级独立证书
2. **OTP 组合链复刻**: xxtea+md5_char16+AES 全链 Python 化 (md5字符中段16已识别)
3. **hyns 5008 帧 Java 构建器**: appSign 明文序列化格式 (ProtoInfo 对应已定案!)
## 五、仓库状态
- 提交: 铸币修复(ccfa742) → device_mint(9ff5721) → §11.9-§11.22 全档 → 命名规范(eccc00e)
→ AES复刻(1afbd58+) — 全在 git log
- 证据: evidence/mint/ (final_*.bin 6 组终局矩阵 + login_* + doLaunch rsp)
- 工具: tools/device_mint.py / huya_launch_mint.py / huya_device_register.py /
core/huya/wup_encoder.py / huya_aes_replica.py / unidbg 双探针 (AesProbe/DiffProbe)
- 约束遵守: 全程禁 pm clear/attach; 差分全在 PC/unidbg; 手机 13.4.22 身份未破坏
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,6 +13,7 @@ import com.github.unidbg.pointer.UnidbgPointer;
import java.io.File;
import java.util.Arrays;
import unicorn.UnicornConst;
/**
* 差分探针: 与 huya_aes_replica.py 对拍 encode_aes@0x330218
@@ -132,5 +133,26 @@ public class DiffProbe {
System.out.println("[KAA] in=0123456789abcdef key='A'*64 -> " + p.enc("0123456789abcdef", "A".repeat(64)));
// 24B 短钥 (short string, flag 参与装载?)
System.out.println("[K24] in=0123456789abcdef key=0123456789abcdef(16B short) -> " + p.enc("0123456789abcdef", "0123456789abcdef"));
probeGetkey(args.length > 0 ? args[0] : "so/libudbauthunify_merged.so");
}
static void probeGetkey(String soPath) throws Exception {
DiffProbe p = new DiffProbe(soPath);
com.github.unidbg.memory.Memory mem = p.emulator.getMemory();
UnidbgPointer self = mem.malloc(0x100, false).getPointer();
byte[] zb = new byte[0x100]; self.write(0, zb, 0, zb.length);
// C2 构造 (AESkeyMgrC2Ev)
try { p.module.callFunction(p.emulator, 0x26fcc8L, UnidbgPointer.nativeValue(self)); System.out.println("[getkey] C2 done"); }
catch (Throwable t) { System.out.println("[getkey] C2 err " + t); return; }
for (int id1 = 0; id1 <= 4; id1++) {
try {
p.module.callFunction(p.emulator, 0x26871cL, UnidbgPointer.nativeValue(self), (long) id1, 0L);
long x0 = p.emulator.getBackend().reg_read(UnicornConst.UC_ARM64_REG_X0);
long x2 = p.emulator.getBackend().reg_read(UnicornConst.UC_ARM64_REG_X2);
System.out.println("[getkey] id1=" + id1 + " x0=" + Long.toHexString(x0) + " x2=" + Long.toHexString(x2));
} catch (Throwable t) { System.out.println("[getkey] id1=" + id1 + " err " + t); }
}
p.emulator.close();
}
}