From b76ec96573d3eebfefe41552ec469c0877f12a49 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 09:01:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20R32=208=E5=AF=86=E6=96=87?= =?UTF-8?q?=E9=9B=86+=E4=B8=89=E9=87=8D=E9=92=A9=E5=85=A8=E9=9B=B6?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=AE=9A=E8=AE=BA+known-pair=E6=A0=A1?= =?UTF-8?q?=E5=87=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 8活体POST存 evidence (magic 10B@70 一致, 头同族7cda11) - 25 JNI + 2 XTEA核 + 2 Java = 全0调用 (报告=隐藏native路径!) - rtk_known/ 44B known pair (native ct 45542bb3...) 后续差分用 --- docs/HUYA_HDID_ALGORITHM_GEN.md | 23 +++ evidence/dfp_live/dfpReport_body_0856.bin | Bin 0 -> 4076 bytes evidence/dfp_live/dfpReport_post_0856.bin | Bin 0 -> 4263 bytes tools/frida/hook_jnitab.js | 218 ++++++++++++++++++++++ tools/frida/hook_str_kcnx2.js | 179 ++++++++++++++++++ tools/unidbg/hydev/rtk_known/ct.bin | 1 + tools/unidbg/hydev/rtk_known/key.bin | 1 + tools/unidbg/hydev/rtk_known/pt.bin | Bin 0 -> 48 bytes 8 files changed, 422 insertions(+) create mode 100644 evidence/dfp_live/dfpReport_body_0856.bin create mode 100644 evidence/dfp_live/dfpReport_post_0856.bin create mode 100644 tools/frida/hook_jnitab.js create mode 100644 tools/frida/hook_str_kcnx2.js create mode 100644 tools/unidbg/hydev/rtk_known/ct.bin create mode 100644 tools/unidbg/hydev/rtk_known/key.bin create mode 100644 tools/unidbg/hydev/rtk_known/pt.bin diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 27d002d..918037d 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -1504,3 +1504,26 @@ full: 7c da | 11 | 69 c9 f5 28 9c 4d 46 | 95 6f 21 | 10 bb 80 1. hook mfa b87_@25c98/27DA4 + ga 27DBC/23DF8 (JNI impl 直挂!) — 关键参数 (byte[], map, mode!) 2. 或: mfa 动态符号/内部调用大范围探 (OLLVM 静态已尽) 3. 解密器待 key: cprivate.py (Cprivate.a 全等直译) 已就绪 — key 一到即解 3 个新密文! + +## §11.63 R32: 8 密文集 + 全钩零调用定论 + Java/native 差分 (2026-08-29) + +### 8 密文集 (存 evidence/dfp_live/) +4384/4267/4261/4263/4267/4261/4261/4263...B POSTs + bodies (magic 10B 一致 @70!) +- 0647-0856: 8 个活体 POST (同配方重注册触发!) +- 头部同族: 7cda 11 {session} {cnt} {stable} — 计数位 28/34 递增等 + +### 三重钩全零调用铁证 (原生 25 JNI + XTEA 2 核 + Java 2 钩!) +- mfa 11 JNI (a87_@25680..k87_@27b74) + ga 14 JNI (a209202@1fcb8..n209202@43900) = 全部安装且 0 次触发! +- mfa sub_24D58 + ga sub_1F1CC XTEA 核心 = 0 次! +- Java ga.private(Cprivate).b + Perseus.a = 0 次! +- → 报告密文 = 隐藏 native 路径 (JNI 方法族之外!) + +### Java Cprivate 与 native sub_24D58 差分 +- Java (decompile 直读) = 标准 XXTEA (sum-=DELTA!) +- native (OLLVM 模糊!) — known pair 校准失败 (44B: native ct 45542bb3... vs python 全部变体) +- → native 核心 = 变体 (OLLVM 掩码深处) 或 harness 参数语义差异 (raw-core vs envelope-len-word) +- rtk_known/ 存校准对 — 后续对照用 + +### 下一步 (R33) +1. native 信封/收集器全钩: mfa 2E164/2E250/25234/252EC/34B98/34A00/2E4A4 + ga 1F918/1F9C8/27DBC/27CE0/23DF8! +2. 或用已知对差分出 native 变体的确切公式 (再校验 Java 解密器) diff --git a/evidence/dfp_live/dfpReport_body_0856.bin b/evidence/dfp_live/dfpReport_body_0856.bin new file mode 100644 index 0000000000000000000000000000000000000000..c0db004ae2c81c24f448e21b4cedf75dbffb1ba8 GIT binary patch literal 4076 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 J3yhcys0_}L6E*+< literal 0 HcmV?d00001 diff --git a/tools/frida/hook_jnitab.js b/tools/frida/hook_jnitab.js new file mode 100644 index 0000000..9a3a5f2 --- /dev/null +++ b/tools/frida/hook_jnitab.js @@ -0,0 +1,218 @@ +'use strict'; +function emit(row) { try { send(row); } catch (e) {} } +function btOk(ctx) { try { return Thread.backtrace(ctx, Backtracer.ACCURATE).slice(0, 40).map(a => { const m = Process.findModuleByAddress(a); return m ? m.name + '!' + a.sub(m.base) : a.toString(); }).join(' <- '); } catch (e) { return ''; } } +let fired = false, writes = 0; +for (const mod of Process.enumerateModules()) { + let addr = null; + try { addr = mod.getExportByName('SSL_write'); } catch (e) {} + if (addr === null) continue; + Interceptor.attach(addr, { + onEnter(args) { + writes++; + if (fired) return; + if (writes % 40 === 0) emit({ event: 'ssl-heartbeat', module: mod.name, writes }); + const buf = args[1], num = args[2].toInt32(); + if (num < 60) return; + try { + const u = new Uint8Array(buf.readByteArray(Math.min(num, 30000))); + // 编码成可检索串 (简化: 只查 ascii 子串) + let s = ''; + for (let i = 0; i < u.length; i++) s += (u[i] >= 32 && u[i] < 127) ? String.fromCharCode(u[i]) : '.'; + if (s.indexOf('dfpReport') < 0 && s.indexOf('hyudbwebuif') < 0) return; + fired = true; + const hex = Array.from(u).map(x => x.toString(16).padStart(2, '0')).join(''); + emit({ event: 'str-magic', module: mod.name, num, full: hex, bt: btOk(this.context) }); + // ---- co-located: 命中后立即在 turing 区域 + 全堆扫第二处魔数/明文特征 ---- + const MAG = [0x57, 0x18, 0x82, 0xcf, 0x66, 0x4b, 0xb3, 0x94, 0x01, 0xee]; + setTimeout(() => { + try { + const regions = []; + for (const m of Process.enumerateModules()) { + if (/turing|Turin/.test(m.name)) regions.push({ name: m.name, p: m.base, n: Math.min(m.size, 2 * 1024 * 1024) }); + } + // 附加: 加载库里的映射区域 (含 .turing.dat mmap) — 用 Process.enumerateRanges 'r--' 太广, 只挑 map 文件路径含 turing 的 + for (const r of Process.enumerateRanges('r--')) { + try { + const f = r.file ? r.file.path : ''; + if (/turing|\.dat/.test(f) && !/\.so/.test(f)) regions.push({ name: f.slice(-40), p: r.base, n: Math.min(r.size, 512 * 1024) }); + } catch (e) {} + } + let nFound = 0; + for (const rg of regions) { + try { + const buf = new Uint8Array(rg.p.readByteArray(rg.n)); + for (let i = 0; i + 10 < rg.n; i++) { + let ok = true; + for (let j = 0; j < 10; j++) if (buf[i+j] !== MAG[j]) { ok = false; break; } + if (!ok) continue; + nFound++; + if (nFound > 12) break; + // 邻域 ASCII 提取 + const as = []; + for (let k = -128; k < 1024; k += 64) { + try { + const c = Array.from(new Uint8Array(rg.p.add(i + k).readByteArray(64))); + const str = c.map(x => (x >= 32 && x < 127) ? String.fromCharCode(x) : '.').join(''); + if (/[A-Za-z0-9_\-\.\/:]{10,}/.test(str)) as.push({ k, s: str }); + } catch (e) {} + } + emit({ event: 'co-magic', mod: rg.name, off: '0x' + i.toString(16), ascii: as.slice(0, 10) }); + } + } catch (e) {} + } + emit({ event: 'co-done', n: nFound, regions: regions.length }); + } catch (e) { emit({ event: 'co-err', msg: String(e).slice(0, 120) }); } + }, 0); + } catch (e) {} + }, + }); + emit({ event: 'ssl-hooked', module: mod.name }); +} + +// ===== 附加: Java 密钥钩子 (Cprivate.b 明文+密钥 / Perseus.a 会话密钥) ===== +setTimeout(function(){ + function S(o){ try { send(o); } catch(e){} } + try { + Java.perform(function(){ + var hooked = 0; + try { + var Cpr = null, Melon = null; + Java.enumerateClassLoaders({ + onMatch: function(loader){ + try { + Java.classFactory.loader = loader; + var c = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); + if (c) { Cpr = c; Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); } + } catch(e){} + }, + onComplete: function(){} + }); + if (!Cpr) { Cpr = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); } + var Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); + Cpr.b.overload('[B','[B').implementation = function(a, b){ + var out = this.b(a, b); + try { + S({event:'cpr-b', dlen:a.length, klen:b.length, + key:Melon.a(b), dhead:(Melon.a(a)||'').substring(0,300)}); + } catch(e){ S({event:'cpr-err', e:String(e)}); } + return out; + }; + hooked++; + } catch(e){ S({event:'cpr-nohook', e:String(e).substring(0,120)}); } + try { + var Perseus = Java.use('com.tencent.turingfd.sdk.ams.ga.Perseus'); + var Guava = Java.use('com.tencent.turingfd.sdk.ams.ga.Guava'); + Perseus.a.implementation = function(){ + this.a(); + try { + var g = this.b.value; + if (g) S({event:'perseus-key', c:g.c.value, b1:g.a.value, blen: g.b.value ? g.b.value.length : -1}); + } catch(e){} + }; + hooked++; + } catch(e2){ S({event:'cpr-noperseus', e:String(e2).substring(0,120)}); } + S({event:'cpr-installed', hooked:hooked}); + }); + } catch(e) { S({event:'cpr-perm', e:String(e).substring(0,120)}); } + }, 200); + +// ===== native 实参钩子: ga b209202(0x20110) / k209202(0x219d8) — 抓 16B 块输入! ===== +setTimeout(function(){ + try { + var mod = Process.findModuleByName('libturingga.so'); + if (!mod) { send({event:'nat-nomod'}); return; } + function hookFn(off, name, nargs){ + var addr = mod.base.add(off); + try { + Interceptor.attach(addr, { + onEnter: function(args){ + var regs = ''; + for (var i=2;i { const m = Process.findModuleByAddress(a); return m ? m.name + '!' + a.sub(m.base) : a.toString(); }).join(' <- '); } catch (e) { return ''; } } +let fired = false, writes = 0; +for (const mod of Process.enumerateModules()) { + let addr = null; + try { addr = mod.getExportByName('SSL_write'); } catch (e) {} + if (addr === null) continue; + Interceptor.attach(addr, { + onEnter(args) { + writes++; + if (fired) return; + if (writes % 40 === 0) emit({ event: 'ssl-heartbeat', module: mod.name, writes }); + const buf = args[1], num = args[2].toInt32(); + if (num < 60) return; + try { + const u = new Uint8Array(buf.readByteArray(Math.min(num, 30000))); + // 编码成可检索串 (简化: 只查 ascii 子串) + let s = ''; + for (let i = 0; i < u.length; i++) s += (u[i] >= 32 && u[i] < 127) ? String.fromCharCode(u[i]) : '.'; + if (s.indexOf('dfpReport') < 0 && s.indexOf('hyudbwebuif') < 0) return; + fired = true; + const hex = Array.from(u).map(x => x.toString(16).padStart(2, '0')).join(''); + emit({ event: 'str-magic', module: mod.name, num, full: hex, bt: btOk(this.context) }); + // ---- co-located: 命中后立即在 turing 区域 + 全堆扫第二处魔数/明文特征 ---- + const MAG = [0x57, 0x18, 0x82, 0xcf, 0x66, 0x4b, 0xb3, 0x94, 0x01, 0xee]; + setTimeout(() => { + try { + const regions = []; + for (const m of Process.enumerateModules()) { + if (/turing|Turin/.test(m.name)) regions.push({ name: m.name, p: m.base, n: Math.min(m.size, 2 * 1024 * 1024) }); + } + // 附加: 加载库里的映射区域 (含 .turing.dat mmap) — 用 Process.enumerateRanges 'r--' 太广, 只挑 map 文件路径含 turing 的 + for (const r of Process.enumerateRanges('r--')) { + try { + const f = r.file ? r.file.path : ''; + if (/turing|\.dat/.test(f) && !/\.so/.test(f)) regions.push({ name: f.slice(-40), p: r.base, n: Math.min(r.size, 512 * 1024) }); + } catch (e) {} + } + let nFound = 0; + for (const rg of regions) { + try { + const buf = new Uint8Array(rg.p.readByteArray(rg.n)); + for (let i = 0; i + 10 < rg.n; i++) { + let ok = true; + for (let j = 0; j < 10; j++) if (buf[i+j] !== MAG[j]) { ok = false; break; } + if (!ok) continue; + nFound++; + if (nFound > 12) break; + // 邻域 ASCII 提取 + const as = []; + for (let k = -128; k < 1024; k += 64) { + try { + const c = Array.from(new Uint8Array(rg.p.add(i + k).readByteArray(64))); + const str = c.map(x => (x >= 32 && x < 127) ? String.fromCharCode(x) : '.').join(''); + if (/[A-Za-z0-9_\-\.\/:]{10,}/.test(str)) as.push({ k, s: str }); + } catch (e) {} + } + emit({ event: 'co-magic', mod: rg.name, off: '0x' + i.toString(16), ascii: as.slice(0, 10) }); + } + } catch (e) {} + } + emit({ event: 'co-done', n: nFound, regions: regions.length }); + } catch (e) { emit({ event: 'co-err', msg: String(e).slice(0, 120) }); } + }, 0); + } catch (e) {} + }, + }); + emit({ event: 'ssl-hooked', module: mod.name }); +} + +// ===== 附加: Java 密钥钩子 (Cprivate.b 明文+密钥 / Perseus.a 会话密钥) ===== +setTimeout(function(){ + function S(o){ try { send(o); } catch(e){} } + try { + Java.perform(function(){ + var hooked = 0; + try { + var Cpr = null, Melon = null; + Java.enumerateClassLoaders({ + onMatch: function(loader){ + try { + Java.classFactory.loader = loader; + var c = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); + if (c) { Cpr = c; Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); } + } catch(e){} + }, + onComplete: function(){} + }); + if (!Cpr) { Cpr = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); } + var Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); + Cpr.b.overload('[B','[B').implementation = function(a, b){ + var out = this.b(a, b); + try { + S({event:'cpr-b', dlen:a.length, klen:b.length, + key:Melon.a(b), dhead:(Melon.a(a)||'').substring(0,300)}); + } catch(e){ S({event:'cpr-err', e:String(e)}); } + return out; + }; + hooked++; + } catch(e){ S({event:'cpr-nohook', e:String(e).substring(0,120)}); } + try { + var Perseus = Java.use('com.tencent.turingfd.sdk.ams.ga.Perseus'); + var Guava = Java.use('com.tencent.turingfd.sdk.ams.ga.Guava'); + Perseus.a.implementation = function(){ + this.a(); + try { + var g = this.b.value; + if (g) S({event:'perseus-key', c:g.c.value, b1:g.a.value, blen: g.b.value ? g.b.value.length : -1}); + } catch(e){} + }; + hooked++; + } catch(e2){ S({event:'cpr-noperseus', e:String(e2).substring(0,120)}); } + S({event:'cpr-installed', hooked:hooked}); + }); + } catch(e) { S({event:'cpr-perm', e:String(e).substring(0,120)}); } + }, 200); + +// ===== native 实参钩子: ga b209202(0x20110) / k209202(0x219d8) — 抓 16B 块输入! ===== +setTimeout(function(){ + try { + var mod = Process.findModuleByName('libturingga.so'); + if (!mod) { send({event:'nat-nomod'}); return; } + function hookFn(off, name, nargs){ + var addr = mod.base.add(off); + try { + Interceptor.attach(addr, { + onEnter: function(args){ + var regs = ''; + for (var i=2;i3R^ \ No newline at end of file diff --git a/tools/unidbg/hydev/rtk_known/key.bin b/tools/unidbg/hydev/rtk_known/key.bin new file mode 100644 index 0000000..27c18ed --- /dev/null +++ b/tools/unidbg/hydev/rtk_known/key.bin @@ -0,0 +1 @@ +^x03ĺȩ%g~: \ No newline at end of file diff --git a/tools/unidbg/hydev/rtk_known/pt.bin b/tools/unidbg/hydev/rtk_known/pt.bin new file mode 100644 index 0000000000000000000000000000000000000000..932f433dd489ffaeceb94bd72988bcca54084fb6 GIT binary patch literal 48 zcmZQzWMXDvWn<^yMC+6cQE@6%&_`l#-T_m6KOcR8m$^Ra4i{)Y4`E0suy4 B1G4}C literal 0 HcmV?d00001