From 08fcf5c34ce26536f5363502b9bf7c306bc2395c Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 08:53:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20=F0=9F=92=8E=F0=9F=92=8E=20R31=20?= =?UTF-8?q?=E6=B4=BB=E4=BD=93=E9=87=8D=E6=8A=933=E5=AF=86=E6=96=87+Java?= =?UTF-8?q?=E5=85=A8=E9=80=86+native=E9=9B=B6=E8=B0=83=E7=94=A8=E9=93=81?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 配方: frida-server -l 0.0.0.0 + 清状态(保留登录) + str_magic → 40s命中 - 3新POST (4384/4267/4261B, cipher@70) 存 evidence/dfp_live/ - Java Cprivate XXTEA + Perseus 会话密钥 + Lyra TLV 全解 - 报告加密 = 第三路径 (JNI族+XTEA核心+Java三重钩子全0调用!) - cprivate.py 解密器就绪 (key一到即解) --- docs/HUYA_HDID_ALGORITHM_GEN.md | 24 +++ evidence/dfp_live/dfpReport_body_0846.bin | Bin 0 -> 4197 bytes evidence/dfp_live/dfpReport_post_0846.bin | Bin 0 -> 4384 bytes evidence/dfp_live/dfp_body_4267.bin | Bin 0 -> 4080 bytes evidence/dfp_live/dfp_post_4267.bin | Bin 0 -> 4267 bytes tools/frida/hook_cprivate_perseus.js | 70 +++++++++ tools/frida/hook_str_kc.js | 117 ++++++++++++++ tools/frida/hook_str_kcn.js | 145 ++++++++++++++++++ tools/frida/hook_str_kcnx.js | 179 ++++++++++++++++++++++ tools/frida/run_capture.py | 14 ++ 10 files changed, 549 insertions(+) create mode 100644 evidence/dfp_live/dfpReport_body_0846.bin create mode 100644 evidence/dfp_live/dfpReport_post_0846.bin create mode 100644 evidence/dfp_live/dfp_body_4267.bin create mode 100644 evidence/dfp_live/dfp_post_4267.bin create mode 100644 tools/frida/hook_cprivate_perseus.js create mode 100644 tools/frida/hook_str_kc.js create mode 100644 tools/frida/hook_str_kcn.js create mode 100644 tools/frida/hook_str_kcnx.js diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 754943d..27d002d 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -1480,3 +1480,27 @@ full: 7c da | 11 | 69 c9 f5 28 9c 4d 46 | 95 6f 21 | 10 bb 80 1. frida 抓 guava.c (16字符) — Java 层单点 hook (Perseus.a 本地串 / Guava 实例) 2. 用真 key 跑 Cprivate.a(捕获密文) = 明文事件! 3. Lynx 全解码器 (13B 头语义 + 帧结构) + +## §11.62 R31: 💎💎💎 活体重抓 3 密文 + Java 全逆确认 + native 全程零调用 (2026-08-29) + +### 配方复现 (用户协助) +- frida-server 必需 `-l 0.0.0.0:31878` (否则连接closed!) +- 触发 = 只清 turing 状态不 pm-clear (保留登录!) + spawn + hook_str_magic → ~40s 自动重注册上报! (用户"退出重新登录不触发" = 登录态在) +- 3 个全新 POST: 4384B(cipher 4117@70) / 4267B(4000@70) / 4261B 同刻捕获! + +### Java 侧全逆 (jadx classes7.dex — 与 native 同构确认) +- Cprivate(实类名 ga.private!) = XXTEA: b(enc)/a(dec), key>16B→MD5, 尾字=明文长 +- Perseus.a() = 会话: SecureRandom 16字符[A-Za-z0-9] → RSA(MIIB...公钥)封装 → guava{seq,env,KEY,d,expire}! +- Lyra/Lynx TLV: 帧头=(type<<4)|tag, type 0-13 (0=1B 1=2B 2=4B 3=8B 6=str 7=bytes 8/9=集合 10=map 11=END) +- 请求 = Cthrow{Csuper[]} → Octans.a(Lyra帧) → Cextends.a(deflate) → Cprivate.b(data, 16字符UTF8字节)! + +### native 零调用铁证 (同一活体会话!) +- xtea-hooked mfa@24D58 + ga@1F1CC ✓ 但 0 次 xtea-got (报告期内核从未被调!) +- nat b209202@20110 + k209202@219d8 hooked ✓ 0 次 nat-ent +- Java Cprivate.b/Perseus.a hooked ✓ 0 次调用 +- → 报告加密在 turing 的第三路径 (非 JNI 方法族!): 需hook已知 JNI impl (mfa b87_@25c98 / ga 27DBC 解码族!) 或 native 内部更多偏移 + +### 下一步 (R32) +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 个新密文! diff --git a/evidence/dfp_live/dfpReport_body_0846.bin b/evidence/dfp_live/dfpReport_body_0846.bin new file mode 100644 index 0000000000000000000000000000000000000000..1b7cb4574da01151269d40590791676d91d6e956 GIT binary patch literal 4197 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 z%0D%VNrROMcNDBE4cX8VB-?l@`kc2kRov`cXd*~uJIQ`9a8 z=X1*p-F2uBtQ!pk)$C1->b~hlU@EZ-fPjMBjW-K`c2Oa(Ih_Zq$XIwI8Tr!#O_u*Ol zl!rGv0>)T+R6)d1OWbXoN+K(l@5R{n-5qEcE%Su&XIOHUV*0Yur=H{CGWU z_h$aqc#+NZYk|;!9K&X#3YN6Gau@xaxk@Crrex)K*SCALQ~g;TQV0XgEL>xevs&0~ zEqb;l2y=VR%2Uj8{j6j;mZ8HtdED;8B1MqTRQ6AijYUyR72E(@(#tbeUjU}i&YBpc vvHC_8x?Rgi2f>*RRouv=WsXKYZVec@YtRp*{;)xUu+BCBKnx3vm<*^4jbj*J literal 0 HcmV?d00001 diff --git a/evidence/dfp_live/dfpReport_post_0846.bin b/evidence/dfp_live/dfpReport_post_0846.bin new file mode 100644 index 0000000000000000000000000000000000000000..da8677f4186a14e3bde81f53a8e0206c25d7b180 GIT binary patch literal 4384 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 a4H&s=&<~{kut9>b&Ncu*3=52y45$o(2vf!Y literal 0 HcmV?d00001 diff --git a/evidence/dfp_live/dfp_body_4267.bin b/evidence/dfp_live/dfp_body_4267.bin new file mode 100644 index 0000000000000000000000000000000000000000..84ca88f65a25f2931f5a88bd147373c20879b225 GIT binary patch literal 4080 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 60000) return; + var b = args[1].readByteArray(Math.min(len, 2000)); + var u = new Uint8Array(b); + var s = ''; + for (var i=0;i= 0 || u.length>10 && (u[0]==0x7c || u[1]==0xda)) { + var hex = Array.prototype.map.call(u, function(x){return ('0'+x.toString(16)).slice(-2)}).join(''); + send({event:'ssl-dfp', len:len, head:hex.substring(0,120)}); + } + } catch(e){} + } + }); + send({event:'ssl-hooked'}); + } +} catch(e) { send({event:'ssl-fail', e:String(e).substring(0,100)}); } diff --git a/tools/frida/hook_str_kc.js b/tools/frida/hook_str_kc.js new file mode 100644 index 0000000..d1d9091 --- /dev/null +++ b/tools/frida/hook_str_kc.js @@ -0,0 +1,117 @@ +'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)}); } + }, 1500); diff --git a/tools/frida/hook_str_kcn.js b/tools/frida/hook_str_kcn.js new file mode 100644 index 0000000..1b69300 --- /dev/null +++ b/tools/frida/hook_str_kcn.js @@ -0,0 +1,145 @@ +'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)}); } + }, 1500); + +// ===== 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)}); } + }, 1500); + +// ===== 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 自动重注册触发报告 (文档配方 §11.49).""" + try: + subprocess.run(["adb","shell","am","force-stop","com.duowan.kiwi"], capture_output=True, text=True) + time.sleep(1) + for path in ["app_turingdfp","app_turingfd","resinfo","app_turingdmp","cocos","turing_files"]: + r = subprocess.run(["adb","shell","run-as","com.duowan.kiwi","rm","-rf",f"/data/data/com.duowan.kiwi/{path}"], capture_output=True, text=True) + if r.returncode == 0: + print(f"[runner] cleared {path}", flush=True) + print("[runner] turing state cleared -> expect auto re-register report", flush=True) + except Exception as e: + print(f"[runner] clear-EXC {e}", flush=True) + def run_once(fout, out_path): """单次 spawn 捕获一轮; 返回该轮事件数 (0 = 该轮无捕获).""" import frida @@ -65,6 +78,7 @@ def run_once(fout, out_path): adb("shell", "am", "force-stop", PKG) time.sleep(1.0) try: + clear_turing_state() pid = dev.spawn([PKG]) print(f"[runner] spawned pid={pid}", flush=True) except Exception as e: