From 1dd67a36d71527995527429af182cf165eaa1e17 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 01:23:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20OTP=E5=86=85=E9=83=A8=E4=B8=B2?= =?UTF-8?q?=E6=B1=A0=E5=8F=96=E8=AF=81=20-=20MsgRegSendSms=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E6=A0=87=E7=AD=BE=E7=8E=B0=E5=BD=A2(=E7=99=BB?= =?UTF-8?q?=E5=BD=95/=E6=B3=A8=E5=86=8C=E8=AF=B7=E6=B1=82=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E5=99=A8)+=E5=8F=8C=E9=92=A5=E7=9B=B8=E9=82=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/HUYA_HDID_ALGORITHM_GEN.md | 7 +++++++ tools/unidbg/hydev/src/hydev/AesProbe.java | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 9331783..15cb78c 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -738,3 +738,10 @@ UdbAESUtilC1(…) + encrypt ← 后段 ### appSign (ed0db8) 明文族爆破 (复刻引擎 × 8 钥 × 19 材料 × 8 形态 = 零命中) - md5/sha1/sha256 摘要 16B、首尾 16B、双 md5、hex 编码等全灭 - 结论: 明文 ≠ 简单材料哈希 — 可能是 config 解密产物 / 复合序列化 (下轮: OTP insert-pos 差分 + config 88B 解码路径) + +## §11.24 OTP 内部字符串缓存池取证 (R2 前夜, 0x127ddbe0 1056B dump) +- 相邻 string 对象: key1(24B ZMHAV!) + "abc"(SSO) + "k"(SSO) + "ivx"(SSO) + key2(owNMia!) + ... +- **`MsgRegSendSms`(13) + `MsgResponceRegSendSms`(21) 协议标签现形** → OTP = 注册/登录 + wup 请求加密器 (消息名入串池, 参与 md5/xxtea/AES 组合!) — 纯协议路线的关键拼图 +- 各对象 = std::string (data/cap/len/ptr) 排布, 与§11.23 堆节点同区 +- 下步: 消息名 + 请求字段序列化 进入 OTP 组合的完整还原 (md5_char16 输入=消息级结构) diff --git a/tools/unidbg/hydev/src/hydev/AesProbe.java b/tools/unidbg/hydev/src/hydev/AesProbe.java index 753119e..116f431 100644 --- a/tools/unidbg/hydev/src/hydev/AesProbe.java +++ b/tools/unidbg/hydev/src/hydev/AesProbe.java @@ -179,6 +179,20 @@ public class AesProbe { return ""; } + void dumpRegion(String tag, long addr, long size) { + UnidbgPointer pp = UnidbgPointer.pointer(emulator, addr); + if (pp == null) { System.out.println("[dump] " + tag + " null"); return; } + byte[] buf = new byte[(int) size]; + try { pp.read(0, buf, 0, buf.length); } catch (Throwable t) { System.out.println("[dump] " + tag + " err " + t); return; } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < buf.length; i++) { + byte b = buf[i]; + sb.append(String.format("%02x", b & 0xff)); + if ((i + 1) % 16 == 0) sb.append(' '); + } + System.out.println("[dump] " + tag + " (" + size + "B): " + sb); + } + void scanMemoryForKeys() { byte[] needle = "ZMHAVPRaxJ3MtXDjduUnXAKQ".getBytes(java.nio.charset.StandardCharsets.ISO_8859_1); long[] ranges = {0x0L, 0x1000000L, 0x40000000L, 0x80000000L, 0x100000000L, 0x300000000L, 0x70200000L}; @@ -365,7 +379,8 @@ public class AesProbe { 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"); p.callOtp("ed0db8334cadd236c00cadf7e11ab5a5", "ZMHAVPRaxJ3MtXDjduUnXAKQ"); - p.scanMemoryForKeys(); + p.dumpRegion("0x127ddbe0", 0x127ddf00L, 0x420); + p.dumpRegion("0x127ddf00", 0x127ddf00L, 0x200); p.emulator.close(); } } \ No newline at end of file