feat(huya): 真实getOtp语义全解(serviceTime+计数器+AppLoginData字段) - 直调路线就绪

This commit is contained in:
yml2213
2026-08-29 02:17:12 +08:00
parent 6bde9beec2
commit 0185296089
2 changed files with 72 additions and 0 deletions
+10
View File
@@ -796,3 +796,13 @@ UdbAESUtilC1(…) + encrypt ← 后段
### OTP 消息名差分
hypasswordLogin/MsgLoginReq/LogLoginReq → mid 各异, tail 恒定 8b38f1 → appSign ≠ OTP 任何段
### 下轮: setSafeDeviceId 直调后 getHDID 状态变化 + 0x64670 "hdid: " 装配函数直调
## §11.30 真实 getOtp 调用语义全解 (R7) - 直调路线就绪
### OTP 双真实调用方 (BusinessCfg::getOtp!)
- 268ca0 (getOtp(y, string&, int&)) + **0x269324 (getOtp(AppLoginData&) = 登录路径!)**
- 269324 参数: x0=to_string(serviceTime)!, x1=2, x2=AESkeyMgr计数器(w25), x3=AppLoginData+0x40,
x4=AppLoginData+0x10, x5=全局串(0x484000+0xa0), x6=4, x7=out, [sp]=m(串)
- **可直调**: BusinessCfg::getInstance@0x281270 + getOtp(AppLoginData&)@0x26916c (T/W 符号)
- AppLoginData 字段布局: +0x40/+0x10/+0x8 (多 string), 全局材料=0x484000+0xa0
### OTP tail = f(c,d) 差分 (推翻"固定"结论) + 真实布局空输出 (参数微差待调)
### 下轮 (R8): getInstance→getOtp(AppLoginData) 直调, 金样本值注满结构 → 输出 vs ed0db8
@@ -137,6 +137,45 @@ public class AesProbe {
return out;
}
String callOtpReal(String in, long counter, String s3, String s4, String s5, long mStack) {
UnidbgPointer pa = writeStdString(in);
UnidbgPointer ps3 = writeStdString(s3);
UnidbgPointer ps4 = writeStdString(s4);
UnidbgPointer ps5 = writeStdString(s5);
UnidbgPointer pout = writeStdString("");
UnidbgPointer pm = writeStdString("mstack");
try {
// 真实布局: (x0=in, x1=2, x2=counter, x3, x4, x5, x6=4, x7=out, [sp]=m)
module.callFunction(emulator, 0x32fa24L,
UnidbgPointer.nativeValue(pa), 2L, counter,
UnidbgPointer.nativeValue(ps3), UnidbgPointer.nativeValue(ps4), UnidbgPointer.nativeValue(ps5),
4L, UnidbgPointer.nativeValue(pout), UnidbgPointer.nativeValue(pm));
String out = readStdString(pout);
String shortIn = in.length() > 20 ? in.substring(0, 20) : in;
String mid = out.length() > 36 ? out.substring(4, 36) : out;
System.out.println("[otp-real] in=" + shortIn + " cnt=" + counter + " s3=" + s3.substring(0, Math.min(10,s3.length()))
+ " s5=" + s5.substring(0, Math.min(10,s5.length())) + " -> out=" + toHex(out) + " mid16=" + mid);
} catch (Throwable t) { System.out.println("[otp-real] err " + t.getMessage()); }
return "";
}
String callOtpFull(String a, String b, String c, String d, long h2, long m2) {
UnidbgPointer pa = writeStdString(a);
UnidbgPointer pb = writeStdString(b);
UnidbgPointer pc = writeStdString(c);
UnidbgPointer pd = writeStdString(d);
UnidbgPointer pout = writeStdString("");
try {
module.callFunction(emulator, 0x32fa24L,
UnidbgPointer.nativeValue(pa), 2L, 0L,
UnidbgPointer.nativeValue(pb), UnidbgPointer.nativeValue(pc), UnidbgPointer.nativeValue(pd),
h2, m2, UnidbgPointer.nativeValue(pout));
String out = readStdString(pout);
System.out.println("[otp-full] c=" + c + " d=" + d + " h=" + h2 + " m=" + m2 + " -> " + toHex(out));
} catch (Throwable t) { System.out.println("[otp-full] err " + t); }
return "";
}
String callOtp(String a, String b) {
UnidbgPointer pa = writeStdString(a);
UnidbgPointer pb = writeStdString(b);
@@ -407,6 +446,29 @@ public class AesProbe {
p.callOtp("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ");
p.callOtp("hypasswordLogin", "owNMiaCgcHmqoTr3iRamFuHj");
p.callOtp("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ");
// 尾随参数差分: 变 c/d/h/m
p.callOtpFull("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "X", "Y", 3L, 4L);
p.callOtpFull("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "ABCDEFGH", "IJKLMNOP", 7L, 9L);
p.callOtpFull("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "5008", "13.4.22", 1L, 2L);
p.callOtpFull("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "ed0db8334cadd236c00cadf7e11ab5a5", "1e8bdf7d4f7a01d3", 5L, 6L);
// 金样本帧材料爆破: (c,d) = 帧字段, h=1..6
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "13.4.22", "1.0.80138", 1L, 2L);
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "13.4.22", "1.0.80138", 3L, 4L);
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "127.0.0.1", "xiaomi", 1L, 2L);
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "1e8bdf7d4f7a01d3", "7c5387e0539c023c31c4ff0e807e7256117385ee", 1L, 2L);
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "7c5387e0539c023c31c4ff0e807e7256117385ee", "02df398797432eadefcc12767119ad5e80999389", 1L, 2L);
p.callOtpFull("hypasswordLogin", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "13.4.22", "xiaomi", 1L, 2L);
p.callOtpFull("", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "13.4.22", "1.0.80138", 1L, 2L);
p.callOtpFull("MsgLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ", "13.4.22", "1.0.80138", 1L, 2L);
// 真实 getOtp 布局: (in=serviceTime串, cnt, s3, s4, s5, m) - 金样本值
p.callOtpReal("3251699", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("3251699", 1L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("3251699", 2L, "300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("300023887", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("12916753251699", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("0", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "1e8bdf7d4f7a01d3", 1L);
p.callOtpReal("3251699", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "7c5387e0539c023c31c4ff0e807e7256117385ee", 1L);
p.callOtpReal("3251699", 0L, "hy_300023887", "772ed992b0e161276f44ec63671e60155c506294", "13.4.22", 1L);
p.callOtp("LogLoginReq", "ZMHAVPRaxJ3MtXDjduUnXAKQ");
// SDID 块直解 (36B 证书的两个16B块 × 全部钥)
p.callDecodeAes("859acf6fad86b24ac479361c2de5132f", "ZMHAVPRaxJ3MtXDjduUnXAKQ");