feat(huya): hook突破(getOtp入口命中) + 275d0ff6排除(pre存在) + 结构校验判定点定位
This commit is contained in:
@@ -817,3 +817,14 @@ hypasswordLogin/MsgLoginReq/LogLoginReq → mid 各异, tail 恒定 8b38f1 → a
|
||||
- mid = f(in, cnt, s3, s4, s5); OTP 输出=[h6][00][16B mid][s5 加密块...]
|
||||
### 新候选: 堆 0x127d4b90 = 275d0ff676c0d65114acdefbd2ad87a3 (32hex! 来源待查)
|
||||
### 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
|
||||
|
||||
@@ -218,8 +218,59 @@ public class AesProbe {
|
||||
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() {
|
||||
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
|
||||
Number inst = module.callFunction(emulator, 0x281270L);
|
||||
long thisPtr = inst.longValue();
|
||||
@@ -240,28 +291,8 @@ public class AesProbe {
|
||||
StringBuilder sb2 = new StringBuilder();
|
||||
for (byte bb : rb) sb2.append(String.format("%02x", bb));
|
||||
System.out.println("[getOtp] call ok, struct: " + sb2);
|
||||
System.out.println("[getOtp] done, scanning heap for outputs...");
|
||||
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("[getOtp-heap] @" + String.format("0x%x", baseA + st) + " = " + cur);
|
||||
hits2++;
|
||||
}
|
||||
cur.setLength(0); st = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("[getOtp] heap-scan done hits=" + hits2);
|
||||
scanHeapWindow("[getOtp-post]");
|
||||
System.out.println("[getOtp] heap-scan done");
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[getOtp] err: " + t);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user