feat(huya): getOtp全流程执行成功!OTP调用实弹+参数读取 - 根因=BusinessCfg实例配置字段空
This commit is contained in:
@@ -248,6 +248,8 @@ public class AesProbe {
|
||||
// hook: getOtp 入口 + 内部 OTP 调用点
|
||||
final long ENTRY = module.base + 0x26916cL;
|
||||
final long OTPC = module.base + 0x269324L;
|
||||
final boolean[] f1 = {false};
|
||||
final long[] outSlot = {0};
|
||||
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));
|
||||
@@ -264,10 +266,47 @@ public class AesProbe {
|
||||
long x23 = backend.reg_read(Arm64Const.UC_ARM64_REG_X23).longValue();
|
||||
long x20 = backend.reg_read(Arm64Const.UC_ARM64_REG_X20).longValue();
|
||||
long sp = backend.reg_read(Arm64Const.UC_ARM64_REG_SP).longValue();
|
||||
long x29r = backend.reg_read(Arm64Const.UC_ARM64_REG_X29).longValue();
|
||||
if (address == module.base + 0x269278L && !f1[0]) {
|
||||
f1[0] = true;
|
||||
UnidbgPointer inslot = UnidbgPointer.pointer(emulator, x29r - 0x58L);
|
||||
if (inslot != null) {
|
||||
byte[] sso = new byte[24];
|
||||
sso[0] = 0x02; // len1<<1
|
||||
sso[1] = (byte) '0';
|
||||
inslot.write(0, sso, 0, 24);
|
||||
System.out.println("[hook] in-slot pre-written @0x" + Long.toHexString(x29r - 0x58));
|
||||
}
|
||||
}
|
||||
long outPtr = 0, x19r = 0;
|
||||
if (address == module.base + 0x269324L) {
|
||||
UnidbgPointer spP = UnidbgPointer.pointer(emulator, sp);
|
||||
if (spP != null) { outPtr = spP.getLong(0); x19r = backend.reg_read(Arm64Const.UC_ARM64_REG_X19).longValue(); }
|
||||
if (spP != null) { outPtr = spP.getLong(0); outSlot[0] = outPtr; x19r = backend.reg_read(Arm64Const.UC_ARM64_REG_X19).longValue(); }
|
||||
// 读 x0/x3/x4/x5 槽内容 (各 24B)
|
||||
for (long rr : new long[]{a0, a3, a4, a5}) {
|
||||
UnidbgPointer strp = UnidbgPointer.pointer(emulator, rr);
|
||||
if (strp != null && rr != 0) {
|
||||
byte[] hh = new byte[24];
|
||||
try { strp.read(0, hh, 0, 24); } catch (Throwable tx) { continue; }
|
||||
StringBuilder sbx = new StringBuilder();
|
||||
for (byte bb2 : hh) sbx.append(String.format("%02x", bb2 & 0xff));
|
||||
System.out.println("[otp-arg] @" + Long.toHexString(rr) + " = " + sbx);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((address == module.base + 0x269328L || address == module.base + 0x2693a8L || address == module.base + 0x2693b0L) && outSlot[0] != 0) {
|
||||
// 后调: 读 OUT 串内容
|
||||
UnidbgPointer oP = UnidbgPointer.pointer(emulator, outSlot[0]);
|
||||
if (oP != null) {
|
||||
byte[] head = new byte[24];
|
||||
oP.read(0, head, 0, 24);
|
||||
StringBuilder hx = new StringBuilder();
|
||||
for (byte bb2 : head) hx.append(String.format("%02x", bb2 & 0xff));
|
||||
StringBuilder asc = new StringBuilder();
|
||||
for (byte bb2 : head) asc.append((bb2 >= 0x20 && bb2 < 0x7f) ? (char) bb2 : '.');
|
||||
System.out.println("[otp-OUT] @" + Long.toHexString(outSlot[0]) + " head=" + hx + " asc=" + asc);
|
||||
outSlot[0] = 0;
|
||||
}
|
||||
}
|
||||
System.out.println("[hook-args] @0x" + Long.toHexString(address) + " x0=" + Long.toHexString(a0) + " x1=" + Long.toHexString(a1)
|
||||
+ " x2=" + Long.toHexString(a2) + " x3=" + Long.toHexString(a3) + " x4=" + Long.toHexString(a4) + " x5=" + Long.toHexString(a5)
|
||||
@@ -280,10 +319,14 @@ public class AesProbe {
|
||||
public void detach() {}
|
||||
};
|
||||
emulator.getBackend().hook_add_new(th, ENTRY, ENTRY, null);
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x2691a4L, module.base + 0x2691d8L, null);
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x26921cL, module.base + 0x269330L, null);
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x4543a0L, module.base + 0x4543a4L, null);
|
||||
System.out.println("[hook] installed full-flow 0x2691a4->0x269330");
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x26916cL, module.base + 0x2695dcL, null);
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x4542c0L, module.base + 0x4542c4L, null);
|
||||
emulator.getBackend().hook_add_new(th, module.base + 0x4543a0L, module.base + 0x4543c4L, null);
|
||||
// to_string@0x4543c0 符号缺失(UC_ERR_READ_UNMAPPED) -> 269278 bl 换 NOP
|
||||
byte[] nop = new byte[]{(byte)0x1f, (byte)0x20, (byte)0x03, (byte)0xd5};
|
||||
try { emulator.getBackend().mem_write(module.base + 0x269278L, nop); System.out.println("[hook] NOP-patched 0x269278"); }
|
||||
catch (Throwable tn) { System.out.println("[hook] NOP-patch failed: " + tn); }
|
||||
System.out.println("[hook] MEGA + to_string bypass");
|
||||
scanHeapWindow("[getOtp-pre]");
|
||||
// BusinessCfg::getInstance @0x281270
|
||||
Number inst = module.callFunction(emulator, 0x281270L);
|
||||
@@ -310,6 +353,20 @@ public class AesProbe {
|
||||
for (byte bb : rb) sb2.append(String.format("%02x", bb));
|
||||
System.out.println("[getOtp] call ok, struct: " + sb2);
|
||||
scanHeapWindow("[getOtp-post]");
|
||||
System.out.println("[getOtp] instance dump 0x0-0xc0:");
|
||||
{
|
||||
byte[] ib = new byte[0xc0];
|
||||
UnidbgPointer iptr = UnidbgPointer.pointer(emulator, thisPtr);
|
||||
if (iptr != null) {
|
||||
try { iptr.read(0, ib, 0, ib.length); } catch (Throwable te) {}
|
||||
StringBuilder hx = new StringBuilder();
|
||||
for (int i = 0; i < ib.length; i++) { hx.append(String.format("%02x", ib[i] & 0xff)); if (i % 2 == 1) hx.append(' '); }
|
||||
System.out.println("[inst] " + hx);
|
||||
StringBuilder asc = new StringBuilder();
|
||||
for (int i = 0; i < ib.length; i++) asc.append((ib[i] >= 0x20 && ib[i] < 0x7f) ? (char) ib[i] : '.');
|
||||
System.out.println("[inst] " + asc);
|
||||
} else System.out.println("[inst] null iptr");
|
||||
}
|
||||
System.out.println("[getOtp] heap-scan done");
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[getOtp] err: " + t);
|
||||
|
||||
Reference in New Issue
Block a user