diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index acbd84a..62d6443 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -1227,3 +1227,22 @@ dfpReport: tReq = [10B 魔数 57 18 82 cf 66 4b b3 94 01 ee][3988B 加密采 - 三种输入 (全POST/cipher-only/magic+cipher) × int{0,1} = 全部确定性 **ret=-1** - 判定: jobject 封送通; -1 = turing 全局初始化态缺失 (config/dat 未载入) 或 SparseArray 内容格式不符 - 下一步: (a) onLoad 初始化链修复后直调 (x0 原子问题先解), (b) 或喂 SparseArray 事件内容探格式 + +--- + +## §11.52 R22: harness onLoad 迭代修复进展 (2026-08-29) + +### 崩因链逐级突破 (每补一个槽位推进一段) +1. **0x48a90 全局槽 NULL → 引用计数崩溃** (0x12b6c ldxr x0): + - onLoad 的 init 函数 0x11690 先读该槽 (adrp 0x48000 + ldr #0xa90) 再 refcount + - 真机上该槽在 init 链前序已赋值; harness 中静默为空 + - **补丁: 塞 8B dummy 对象指针 → 过此关!** +2. 新崩溃: BR-x8 空跳 (X8=0x0, PC=0x0), X0=X1=0x1203ced5 (rodata 字符串) + - 变体函数指针表空槽 / C++ 虚表未建 / PLT 未解析 +3. 根因深化: turing 类定义 (字段/方法) 缺失 — 预注册的空类无法支撑 JNI 静态字段链 + - unidbg VM 无 dex 加载 (仅 setDvmClassFactory/ProxyClassFactory 宿主代理) + +### 状态判定 +- onLoad 全仿真 = 类定义工程 (ProxyClassFactory) 或连续空槽 wack-a-mole — 小时级 +- 替代: 跳过 onLoad, 直接按 JNI 表构造 b87_@0x25c98 的 C 结构对象模型直调 +- 进展固化: gap补映射 + 预注册类 + 全局槽补丁 = 已进 TuringProbe.java 可复现 diff --git a/tools/unidbg/hydev/src/hydev/TuringProbe.java b/tools/unidbg/hydev/src/hydev/TuringProbe.java index 5edb4fc..ed3b6ee 100644 --- a/tools/unidbg/hydev/src/hydev/TuringProbe.java +++ b/tools/unidbg/hydev/src/hydev/TuringProbe.java @@ -82,11 +82,22 @@ public class TuringProbe { } catch (Throwable t2) { System.out.println("[TP] gap map EXC " + t2); } + // 全局槽基础补丁: base+0x48a90 读取为 NULL -> 塞一个 8B dummy 对象 (引用计数目标) + try { + long slot = m.base + 0x48a90; + com.github.unidbg.pointer.UnidbgPointer dummyPtr = emulator.getMemory().mmap(8, 7); + dummyPtr.setMemory(0, 8, (byte) 0); + com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, slot).setPointer(0, dummyPtr); + System.out.println("[TP] global slot 0x48a90 <- " + Long.toHexString(dummyPtr.peer)); + } catch (Throwable t4) { + System.out.println("[TP] slot patch EXC " + t4); + } try { dm.callJNI_OnLoad(emulator); System.out.println("[TP] libturingmfa JNI_OnLoad OK"); } catch (Throwable t3) { System.out.println("[TP] onLoad EXC: " + t3); + regDump(); } break; } @@ -98,12 +109,20 @@ public class TuringProbe { } catch (Throwable t) { System.out.println("[TP] load " + which + " EXC: " + t); try { - com.github.unidbg.arm.ARM emu = (com.github.unidbg.arm.ARM) emulator; - java.lang.reflect.Field f = emulator.getClass().getSuperclass().getDeclaredField("backend"); - f.setAccessible(true); - Object be = f.get(emulator); - java.lang.reflect.Method pc = be.getClass().getMethod("reg_read", int.class); - System.out.println("[TP] PC=" + Long.toHexString(((Number) pc.invoke(be, com.github.unidbg.arm.backend.Unicorn2Factory.class.getField("UC_ARM64_REG_PC").getLong(null))).longValue())); + com.github.unidbg.arm.backend.Backend be = emulator.getBackend(); + int[] regs = {unicorn.Arm64Const.UC_ARM64_REG_PC, + unicorn.Arm64Const.UC_ARM64_REG_X0, + unicorn.Arm64Const.UC_ARM64_REG_X1, + unicorn.Arm64Const.UC_ARM64_REG_X8, + unicorn.Arm64Const.UC_ARM64_REG_X19, + unicorn.Arm64Const.UC_ARM64_REG_LR, + unicorn.Arm64Const.UC_ARM64_REG_SP}; + String[] names = {"PC","X0","X1","X8","X19","LR","SP"}; + for (int k=0;k=0x12012000L && v<0x12018000L) ? " (rel 0x" + Long.toHexString(v - 0x12012000L) + ")" : ""; + System.out.println("[TP] " + names[k] + "=0x" + Long.toHexString(v) + rel); + } + // 尝试读 x0 处内存 + try { + long x0 = be.reg_read(unicorn.Arm64Const.UC_ARM64_REG_X0).longValue(); + com.github.unidbg.pointer.UnidbgPointer pp = com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, x0); + byte[] b = pp.getByteArray(0, 32); + System.out.println("[TP] *X0 = " + java.util.HexFormat.of().formatHex(b)); + } catch (Throwable t4) { System.out.println("[TP] *X0 unreadable " + t4); } + } catch (Throwable t2) { System.out.println("[TP] regDump fail " + t2); } + } + /** 直调 mfa 的 b87_ (impl@0x25c98) — JNI: (env, thiz, SparseArray, byte[], Map, int) -> SparseArray */ void callEnc(String blobPath) { try {