From 51962b8bf271c5bb7983f7d6a60a640c9c5d53ca Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 07:45:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20ga=20k209202=3D16B=E5=9D=97?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=E5=99=A8+=E7=8A=B6=E6=80=81=E9=97=A8?= =?UTF-8?q?=E6=89=93=E9=80=9A=20(R26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - k209202 反汇编: len==16严格校验 + 0x24334状态化块加密核心 - mfa 0x48C18=单例字段 补非零后 b87_全链LIVE (XXTEA+inflate执行!) - 定论: 捕获密文密钥=设备材料派生(非静态), 传输链静态解=需ga IDA导出 - 下一步: 用户导 turingga.so / 或抓服务器 resp 旁路 --- docs/HUYA_HDID_ALGORITHM_GEN.md | 27 +++++++++++++++++++ tools/unidbg/hydev/src/hydev/TuringProbe.java | 18 ++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 4611218..588ffff 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -1342,3 +1342,30 @@ m209202(SparseArray,Context,Map)@0x21bdc n209202(SparseArray,[B,I,String,J)@0x43 ### 下一步 (两条关键路径) 1. **用户导出的 turingga.so IDA export** → k209202@0x219d8 反编译 → 传输加密链静态全解 (同 mfa 方法论) 2. harness 继续喂 ga 运行时状态 (0x48XXX 构建器等价物) → k209202 真调用 (同 b87_ -1 问题) + +## §11.57 R26: ga k209202 = 16B 块加密器 + 状态门全打通 (2026-08-29) + +### k209202@0x219d8 反汇编解构 ([B)[B) +- **GetArrayLength; `cmp w0,#0x10; b.ne FAIL` = 严格 16B 输入** (非大块传输加密!) +- GetByteArrayElements + strncpy(16B) → bl 0x19378 (对象创建!) → bl 0xc8a4 (builder-init) + → bl 0x13eb8×2 (序列化!) → bl 0x1c640×2 → **bl 0x24334 (块加密核心: calloc+memcpy+全局0x48000+c18状态+0x5754串!)** + → bl 0x19258 (收尾) → NewByteArray(0x580)+ 结果 vs 全局计数器 cmp +- **0x24334 = 带状态的块加密机器** (读 [0x48000+0xc18] 指针再解引用 → 计数器对比 w21!) +- 失败路径: 0x21b4c (len≠16 → x20=null) / 0x21bb0; 成功 = NewByteArray-route + +### harness 状态门全打通 +- **mfa: 0x48C18 = 单例 48BD8 对象字段 a1+64 (id!) — 补非零 → b87_ 全链 LIVE!!** + (sub_347C8(map-check) → GetByteArrayElements → sub_2E4A4 → XXTEA+inflate 全部执行!) +- b87_ 对捕获密文三种输入 (strip/only/magic-full) 全 -1 = **确定性拒绝 — 捕获 ≠ b87_'resp' 格式** +- ga: 0x48c18 状态指针已补 → k209202 仍 -1 (0x19378 对象创建需更深的 SDK 全局态) + +### 结论 (本阶段定论) +- **捕获密文的密钥 = 设备材料派生 (mpdc 16B→ga 16B块加密→主密!) — 非静态 3DF88** +- mfa 的 XXTEA (24D58) = 内部序列化 (resp-解码侧!) — 已 100% 回环验证 +- **传输加密链 0x19378/0x13eb8/0x24334 的静态明文 = 需要 turingga.so 的 IDA 导出** + (同 mfa 方法论: 反编译这些函数的 key 派生/块加密逻辑 = 密钥再推导!) + +### 立即下一步 +1. **用户导出 turingga.so 的 IDA decompile** (k209202 全家: 0x219d8/0x24334/0x19378/0x13eb8/0x1c640) +2. harness 继续: mfa 单例 34D68 全量 ctor (48BD8) + 各字段填充 → b87_ 对正确 resp 输入成功 +3. 或 frida 捕获一次 **服务器 dfpConfig 响应** (b87_ 的 resp 输入 = 密钥推导的旁路!) diff --git a/tools/unidbg/hydev/src/hydev/TuringProbe.java b/tools/unidbg/hydev/src/hydev/TuringProbe.java index cc4f48d..190f6bd 100644 --- a/tools/unidbg/hydev/src/hydev/TuringProbe.java +++ b/tools/unidbg/hydev/src/hydev/TuringProbe.java @@ -280,6 +280,13 @@ public class TuringProbe { DvmObject sa = vm.resolveClass("android/util/SparseArray").newObject(null); DvmObject dba = vm.resolveClass("[B").newObject(blob); DvmObject map = vm.resolveClass("java/util/HashMap").newObject(null); + // 补 0x48C18 门 (单例字段 a1+64) — 非零即可过 b87_ 的 qword_48C18 检查 + try { + com.github.unidbg.pointer.UnidbgPointer st = emulator.getMemory().mmap(0x100, 7); + st.setMemory(0, 0x100, (byte) 0); + com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, m.base + 0x48C18).setPointer(0, st); + System.out.println("[TP] state 0x48C18 <- " + Long.toHexString(st.peer)); + } catch (Throwable t3) { System.out.println("[TP] state EXC " + t3); } // 直调 impl: module.base + 0x25c98; 参数: env, null, 局部引用句柄(int), ..., 1 long fn = m.base + 0x25c98; int hsa = vm.addLocalObject(sa); @@ -288,7 +295,7 @@ public class TuringProbe { System.out.println("[TP] calling b87_ @ " + Long.toHexString(fn) + " blob=" + blob.length + " refs hsa=" + hsa + " hba=" + hba + " hmap=" + hmap); int iv = Integer.parseInt(System.getenv().getOrDefault("TP_INT", "1")); - Number ret = m.callFunction(emulator, fn, vm.getJavaVM(), null, hsa, hba, hmap, iv); + Number ret = m.callFunction(emulator, fn, ((com.github.unidbg.pointer.UnidbgPointer) vm.getJNIEnv()).peer, 0, hsa, hba, hmap, iv); System.out.println("[TP] b87_ ret=" + ret + " int=" + iv + " blob=" + blobPath); } catch (Throwable t) { System.out.println("[TP] callEnc EXC " + t); @@ -426,6 +433,15 @@ public class TuringProbe { com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, ggap).setMemory(0, 0x720, (byte) 0); } catch (Throwable t) {} try { dm.callJNI_OnLoad(emulator); } catch (Throwable t) {} + // 补 ga 0x48c18 状态指针 (ldr w8,[x8] 解引用) + 邻近槽 + try { + com.github.unidbg.pointer.UnidbgPointer gst = emulator.getMemory().mmap(0x40, 7); + gst.setMemory(0, 0x40, (byte) 0); + gst.setInt(0, 1); + com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, gm.base + 0x48c18).setPointer(0, gst); + com.github.unidbg.pointer.UnidbgPointer.pointer(emulator, gm.base + 0x48c20).setPointer(0, gst); + System.out.println("[TP] ga state 0x48c18 <- " + Long.toHexString(gst.peer)); + } catch (Throwable t) {} byte[] blob = new java.io.FileInputStream(blobPath).readAllBytes(); DvmObject byteObj = vm.resolveClass("[B").newObject(blob); long env = ((com.github.unidbg.pointer.UnidbgPointer) vm.getJNIEnv()).peer;