From 26dc74a6611223a510f6f8632f0a950359c6c1cc Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 01:29:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20decode=E5=85=A811=E9=92=A5=3D?= =?UTF-8?q?=E5=85=A8=E4=BA=8C=E8=BF=9B=E5=88=B6=E5=9E=83=E5=9C=BE=20-=20ap?= =?UTF-8?q?pSign=E9=92=A5=E2=88=89=E5=B7=B2=E7=9F=A5=E7=9B=AE=E5=BD=95,=20?= =?UTF-8?q?=E6=96=B9=E5=90=91=E4=BF=AE=E6=AD=A3(=E6=89=BEhdid=E7=9C=9F?= =?UTF-8?q?=E7=94=9F=E4=BA=A7=E6=96=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/HUYA_HDID_ALGORITHM_GEN.md | 6 ++++++ tools/unidbg/hydev/src/hydev/AesProbe.java | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 15cb78c..5da742e 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -745,3 +745,9 @@ UdbAESUtilC1(…) + encrypt ← 后段 wup 请求加密器 (消息名入串池, 参与 md5/xxtea/AES 组合!) — 纯协议路线的关键拼图 - 各对象 = std::string (data/cap/len/ptr) 排布, 与§11.23 堆节点同区 - 下步: 消息名 + 请求字段序列化 进入 OTP 组合的完整还原 (md5_char16 输入=消息级结构) + +## §11.25 decode_aes 全 11 钥直解 ed0db8 = 全二进制垃圾 (R2) +- ybEWdvk…→576ead68… / HuyaUdb27B→c336e348… / xXED/4VYc/3FMH/owNMia/KFWAH/ZMHAV = 全无明文 +- **appSign 加密钥 ∉ AESkeyMgr 24B 目录(11把) ∪ 文件钥(27B list)** +- decode_aes 输出 = 32B (16B 入双块) → ed0db8 = 16B 密文块 (32hex ✓) 但钥 = 他处 +- 方向修正: 找 32hex-hdid 的真正生产方 (encode_aes 之调用者三处已列: OTP/文件/encode — 若 hdid 不走 encode_aes → 查 GetHDID 注册原语周边 + initSDID 的 Java 侧回填) diff --git a/tools/unidbg/hydev/src/hydev/AesProbe.java b/tools/unidbg/hydev/src/hydev/AesProbe.java index 116f431..915344c 100644 --- a/tools/unidbg/hydev/src/hydev/AesProbe.java +++ b/tools/unidbg/hydev/src/hydev/AesProbe.java @@ -311,6 +311,22 @@ public class AesProbe { return -1; } + String callDecodeAesRawHex(String inHex, String key) { + byte[] inb = new byte[inHex.length()/2]; + for (int i = 0; i < inb.length; i++) inb[i] = (byte) Integer.parseInt(inHex.substring(i*2, i*2+2), 16); + UnidbgPointer pin = writeStdString(new String(inb, java.nio.charset.StandardCharsets.ISO_8859_1)); + UnidbgPointer pkey = writeStdString(key); + UnidbgPointer pout = writeStdString(""); + try { + module.callFunction(emulator, 0x330498L, UnidbgPointer.nativeValue(pin), UnidbgPointer.nativeValue(pkey), UnidbgPointer.nativeValue(pout)); + String out = readStdString(pout); + // out 可能是 ASCII-hex (或原始字节) -> 双解释 + String asHex = toHex(out); + System.out.println("[decode-hex] key=" + key + " ascii32hex=" + out + " rawOut=" + asHex); + } catch (Throwable t) { System.out.println("[decode-hex] err " + t); } + return ""; + } + void dumpKeyMgr() { UnidbgPointer self = emulator.getMemory().malloc(0x80, false).getPointer(); self.write(0, new byte[0x80], 0, 0x80); @@ -375,6 +391,10 @@ public class AesProbe { p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "4VYcPdvKKqjBHZtCmbroRXHk"); p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "xXEDWqiKLGwEZ6HubEiswCqK"); p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "3FMHubdKosFrhmXNLHTNHZwe"); + p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "ybEWdvkjGjPQa2ugireHJCLL"); + p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "HuyaUdb1928374650qwertyuiop"); + p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "xXEDWqiKLGwEZ6HubEiswCqK"); + p.callDecodeAes("ed0db8334cadd236c00cadf7e11ab5a5", "4VYcPdvKKqjBHZtCmbroRXHk"); // 设备材料 OTP 对拍 (appSign = OTP(设备材料)?) p.callOtp("1e8bdf7d4f7a01d3" + "13.4.22" + "1.0.80138" + "127.0.0.1" + "xiaomi", "ZMHAVPRaxJ3MtXDjduUnXAKQ"); p.callOtp("5008" + "13.4.22" + "1.0.80138", "ZMHAVPRaxJ3MtXDjduUnXAKQ");