feat(huya): hook突破(getOtp入口命中) + 275d0ff6排除(pre存在) + 结构校验判定点定位

This commit is contained in:
yml2213
2026-08-29 02:27:47 +08:00
parent f121f41f61
commit 702c6276fc
2 changed files with 64 additions and 22 deletions
+11
View File
@@ -817,3 +817,14 @@ hypasswordLogin/MsgLoginReq/LogLoginReq → mid 各异, tail 恒定 8b38f1 → a
- mid = f(in, cnt, s3, s4, s5); OTP 输出=[h6][00][16B mid][s5 加密块...] - mid = f(in, cnt, s3, s4, s5); OTP 输出=[h6][00][16B mid][s5 加密块...]
### 新候选: 堆 0x127d4b90 = 275d0ff676c0d65114acdefbd2ad87a3 (32hex! 来源待查) ### 新候选: 堆 0x127d4b90 = 275d0ff676c0d65114acdefbd2ad87a3 (32hex! 来源待查)
### R9: ① hook 269328 (post-OTP, X29 读 [x29-0x40] = OUT!) ② 0x123M-0x130M 扫窗 before/after 差分 ### R9: ① hook 269328 (post-OTP, X29 读 [x29-0x40] = OUT!) ② 0x123M-0x130M 扫窗 before/after 差分
## §11.32 Hook 突破 (R9) + getOtp 结构校验 + 275d0ff6 排除
### Hook 首次触发! (此前"不触发"=地址错)
- unicorn2 hook_add_new ✓ → getOtp 入口 0x26916c 命中:
x0=0x12491540(this) x1=0x127c2700(AppLoginData&)
- OTP 调用点 0x269324 未到 → getOtp 在 2691a4 "cmn x20,#0x8; b.hs 2695dc(函数尾)" 提前返回
= 对伪造结构判定失败 (x20-layout 未知, 需读 0x26916c-0x2691a4 前导)
### 275d0ff676c0d65114acdefbd2ad87a3 = 调用前已有 (pre/post 扫描同现) → 非 getOtp 输出, 排除
### 堆窗 pre/post 差分法就绪 (getOtp-pre/post 双扫描框架)
### R10: ① hook 2691a4 读 x20 (分支条件) + 读 0x26916c-0x2691a4 前导定 AppLoginData 布局
### ② 布局修正 → getOtp 走到 269324 → hook 抓 OTP 实参+OUT
+53 -22
View File
@@ -218,8 +218,59 @@ public class AesProbe {
return ""; return "";
} }
void scanHeapWindow(String tag) {
byte[] win = new byte[0x10000];
int hits2 = 0;
for (long baseA = 0x12300000L; baseA < 0x13000000L && hits2 < 40; baseA += 0x10000L) {
UnidbgPointer hp2 = UnidbgPointer.pointer(emulator, baseA);
if (hp2 == null) continue;
try { hp2.read(0, win, 0, win.length); } catch (Throwable t) { continue; }
StringBuilder cur = new StringBuilder();
int st = -1;
for (int i = 0; i < win.length; i++) {
int b = win[i] & 0xff;
if ((b >= 0x20 && b < 0x7f)) { if (st < 0) st = i; cur.append((char) b); }
else {
if (cur.length() >= 30 && cur.chars().allMatch(c -> "0123456789abcdef".indexOf(Character.toLowerCase(c)) >= 0
|| "hZrPb62GskrEeTYcLeUTL1fJ1OR8ky3x9qXQq0s6ICJV5v9T".indexOf(c) >= 0)) {
System.out.println(tag + " @" + String.format("0x%x", baseA + st) + " = " + cur);
hits2++;
}
cur.setLength(0); st = -1;
}
}
}
System.out.println(tag + " done hits=" + hits2);
}
void callGetOtp() { void callGetOtp() {
try { try {
// hook: getOtp 入口 + 内部 OTP 调用点
final long ENTRY = module.base + 0x26916cL;
final long OTPC = module.base + 0x269324L;
com.github.unidbg.arm.backend.CodeHook th = new com.github.unidbg.arm.backend.CodeHook() {
public void hook(com.github.unidbg.arm.backend.Backend backend, long address, int size, Object user) {
System.out.println("[hook] hit @0x" + Long.toHexString(address));
if (address == OTPC || address == ENTRY) {
try {
long a0 = backend.reg_read(Arm64Const.UC_ARM64_REG_X0).longValue();
long a1 = backend.reg_read(Arm64Const.UC_ARM64_REG_X1).longValue();
long a2 = backend.reg_read(Arm64Const.UC_ARM64_REG_X2).longValue();
long a3 = backend.reg_read(Arm64Const.UC_ARM64_REG_X3).longValue();
long a6 = backend.reg_read(Arm64Const.UC_ARM64_REG_X6).longValue();
long a7 = backend.reg_read(Arm64Const.UC_ARM64_REG_X7).longValue();
System.out.println("[hook-args] x0=" + Long.toHexString(a0) + " x1=" + a1 + " x2=" + Long.toHexString(a2)
+ " x3=" + Long.toHexString(a3) + " x6=" + a6 + " x7=" + Long.toHexString(a7));
} catch (Throwable t) { System.out.println("[hook-args] err " + t); }
}
}
public void onAttach(com.github.unidbg.arm.backend.UnHook unHook) {}
public void detach() {}
};
emulator.getBackend().hook_add_new(th, OTPC, OTPC, null);
emulator.getBackend().hook_add_new(th, ENTRY, ENTRY, null);
System.out.println("[hook] installed @0x26916c + @0x269324");
scanHeapWindow("[getOtp-pre]");
// BusinessCfg::getInstance @0x281270 // BusinessCfg::getInstance @0x281270
Number inst = module.callFunction(emulator, 0x281270L); Number inst = module.callFunction(emulator, 0x281270L);
long thisPtr = inst.longValue(); long thisPtr = inst.longValue();
@@ -240,28 +291,8 @@ public class AesProbe {
StringBuilder sb2 = new StringBuilder(); StringBuilder sb2 = new StringBuilder();
for (byte bb : rb) sb2.append(String.format("%02x", bb)); for (byte bb : rb) sb2.append(String.format("%02x", bb));
System.out.println("[getOtp] call ok, struct: " + sb2); System.out.println("[getOtp] call ok, struct: " + sb2);
System.out.println("[getOtp] done, scanning heap for outputs..."); scanHeapWindow("[getOtp-post]");
byte[] win = new byte[0x10000]; System.out.println("[getOtp] heap-scan done");
int hits2 = 0;
for (long baseA = 0x12300000L; baseA < 0x13000000L && hits2 < 40; baseA += 0x10000L) {
UnidbgPointer hp2 = UnidbgPointer.pointer(emulator, baseA);
if (hp2 == null) continue;
try { hp2.read(0, win, 0, win.length); } catch (Throwable t) { continue; }
StringBuilder cur = new StringBuilder();
int st = -1;
for (int i = 0; i < win.length; i++) {
int b = win[i] & 0xff;
if ((b >= 0x20 && b < 0x7f)) { if (st < 0) st = i; cur.append((char) b); }
else {
if (cur.length() >= 30 && cur.chars().allMatch(c -> "0123456789abcdef".indexOf(Character.toLowerCase(c)) >= 0 || "hZrPb62GskrEeTYcLeUTL1fJ1OR8ky3x9qXQq0s6ICJV5v9T".indexOf(c) >= 0)) {
System.out.println("[getOtp-heap] @" + String.format("0x%x", baseA + st) + " = " + cur);
hits2++;
}
cur.setLength(0); st = -1;
}
}
}
System.out.println("[getOtp] heap-scan done hits=" + hits2);
} catch (Throwable t) { } catch (Throwable t) {
System.out.println("[getOtp] err: " + t); System.out.println("[getOtp] err: " + t);
} }