From 2fe23e4274a49c4926b710c5f65ad42611569eab Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 29 Aug 2026 09:10:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(huya):=20=F0=9F=92=8E=F0=9F=92=8E?= =?UTF-8?q?=F0=9F=92=8E=20R34=20=E4=BC=9A=E8=AF=9D=E5=AF=86=E9=92=A5?= =?UTF-8?q?=E6=B4=BB=E4=BD=93=E6=8D=95=E8=8E=B7=E6=88=90=E5=8A=9F=20(P7TAz?= =?UTF-8?q?QYmX4O6i95q!)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Java.choose 堆枚举 @SSL_write 命中 = 密钥体系! (16字符随机, 每注册轮换) - 多POST结构对比: 密文紧跟magic, 头版本位 01/11 变体 - Java Cprivate.a x 会话密钥 x 0-48切片 = 全null → 13.4.22传输≠Cprivate! - hook_final/hook_brute 可复用捕获体系 --- docs/HUYA_HDID_ALGORITHM_GEN.md | 22 ++++++++++ tools/frida/hook_brute.js | 71 +++++++++++++++++++++++++++++++++ tools/frida/hook_final.js | 67 +++++++++++++++++++++++++++++++ tools/frida/hook_heapkey.js | 57 ++++++++++++++++++++++++++ 4 files changed, 217 insertions(+) create mode 100644 tools/frida/hook_brute.js create mode 100644 tools/frida/hook_final.js create mode 100644 tools/frida/hook_heapkey.js diff --git a/docs/HUYA_HDID_ALGORITHM_GEN.md b/docs/HUYA_HDID_ALGORITHM_GEN.md index 2356c9c..fdb298a 100644 --- a/docs/HUYA_HDID_ALGORITHM_GEN.md +++ b/docs/HUYA_HDID_ALGORITHM_GEN.md @@ -1543,3 +1543,25 @@ full: 7c da | 11 | 69 c9 f5 28 9c 4d 46 | 95 6f 21 | 10 bb 80 1. ART 内联帧深度回溯 (bt 全 libart! Java 侧调用方在 JIT 内联里!) 2. native 上更早: libturing 的 a87 事件收集 → 找构造点 (sub_2C76C 采集器等) 3. 内存快照 @ SSL_write 时点 (密文生成缓冲区刚用完, 可扫关联!) + +## §11.65 R34: 💎💎💎 会话密钥活体捕获成功!!! (2026-08-29) + +### 密钥 = 16 字符 [A-Za-z0-9] 活体抓到! +- **Java.choose(Perseus/Guava) 堆枚举 @ SSL_write 命中瞬间!** +- 密钥样例: P7TAzQYmX4O6i95q / X7RCMU3bmmKeT87L (每注册轮换!) +- sessionId: /6jSVX4VURERKgOwiOq+GDE3MjkzNDQxMDMxODk1OTg1NzI5 (base64!) +- Guava.a = 1 (symmetricAlgorithm), bLen = RSA 信封 + +### 结构新认知 (多 POST 对比!) +- 密文紧跟 magic (无固定 13B 头?!): afterMagic = 64bb0169c9... / 6cdb8f68c8... 每轮全变! +- 头变体 '7cda 11 69c9f5...' (旧) vs '64bb 01 69c9...' (新, version 01!) — 版本位 01/11! +- 旧 '7c da' 2B = 疑似 Lyra 帧头 (type7-tagC!) — 新 '64 bb' = 疑似 type6-tag4 (len-str!) + +### Java Cprivate.a 解密实测 (真机 Java 码!) +- 8 POST × 会话密钥 × 0-48B 切片 = **全 null**! +- → 13.4.22 实际传输 ≠ Cprivate (Java 侧 Cprivate = 其他流程/未用!) +- 传输密文 = native 隐藏路径 (45+ 函数零调用证实!) — 密钥体系独立于 Cprivate! + +### 交付 +- hook_final.js / hook_brute.js: 密钥+POST 同刻捕获体系 (可复用!) +- 验证堆枚举法极大成功 — 后续抓任何 JVM 状态对象都可用此法! diff --git a/tools/frida/hook_brute.js b/tools/frida/hook_brute.js new file mode 100644 index 0000000..4af3d33 --- /dev/null +++ b/tools/frida/hook_brute.js @@ -0,0 +1,71 @@ +// 多切片×多密钥暴力: Java 真 Cprivate.a +function emit(o){ try{ send(o); }catch(e){} } +let klist = []; +for (const mod of Process.enumerateModules()) { + let addr = null; + try { addr = mod.getExportByName('SSL_write'); } catch(e){} + if (!addr) continue; + Interceptor.attach(addr, { + onEnter(args){ + try { + var num = args[2].toInt32(); + if (num < 60 || num > 60000) return; + var u = new Uint8Array(args[1].readByteArray(num)); + var s = ''; + for (var i=0;i=32 && u[i]<127) ? String.fromCharCode(u[i]) : '.'; + if (s.indexOf('dfpReport') < 0 && s.indexOf('hyudbwebuif') < 0) return; + var hex = Array.prototype.map.call(u, function(x){return ('0'+x.toString(16)).slice(-2)}).join(''); + emit({event:'post', num:num, hex:hex}); + setTimeout(function(){ + try { + Java.perform(function(){ + var keys = []; + Java.enumerateClassLoaders({ + onMatch: function(loader){ + try { + Java.classFactory.loader = loader; + Java.choose('com.tencent.turingfd.sdk.ams.ga.Perseus', { + onMatch: function(inst){ + try { + var g = inst.b.value; + if (g && keys.indexOf(g.c.value) < 0) keys.push(g.c.value); + } catch(e){} + }, + onComplete: function(){ + try { + var C = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); + var Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); + var idx = hex.indexOf('571882cf664bb39401ee'); + if (idx < 0) return; + var all = hex.substring(idx+20); + var tot = keys.length; + for (var ki=0; ki 60000) return; + var u = new Uint8Array(args[1].readByteArray(num)); + var s = ''; + for (var i=0;i=32 && u[i]<127) ? String.fromCharCode(u[i]) : '.'; + if (s.indexOf('dfpReport') < 0 && s.indexOf('hyudbwebuif') < 0) return; + var hex = Array.prototype.map.call(u, function(x){return ('0'+x.toString(16)).slice(-2)}).join(''); + emit({event:'post-full', num:num, hex:hex}); + // 堆取密钥 + setTimeout(function(){ + try { + Java.perform(function(){ + Java.enumerateClassLoaders({ + onMatch: function(loader){ + try { + Java.classFactory.loader = loader; + Java.choose('com.tencent.turingfd.sdk.ams.ga.Perseus', { + onMatch: function(inst){ + try { + var g = inst.b.value; + if (g && !gotKey) { gotKey = g.c.value; emit({event:'key', c:gotKey}); } + } catch(e){} + }, + onComplete: function(){ + if (gotKey && tried < 3) { + tried++; + try { + var C = Java.use('com.tencent.turingfd.sdk.ams.ga.private'); + var Melon = Java.use('com.tencent.turingfd.sdk.ams.ga.Melon'); + // 密文 = body内 magic@后; 简化: 用整 POST 找 571882cf... + var needle = [0x57,0x18,0x82,0xcf,0x66,0x4b,0xb3,0x94,0x01,0xee]; + var idx = hex.indexOf('571882cf664bb39401ee'); + var cipherHex = idx >= 0 ? hex.substring(idx+20) : ''; + if (cipherHex.length > 16) { + var bytes = []; + for (var i=0;i 60000) return; + var u = new Uint8Array(args[1].readByteArray(num)); + var s = ''; + for (var i=0;i=32 && u[i]<127) ? String.fromCharCode(u[i]) : '.'; + if (s.indexOf('dfpReport') < 0 && s.indexOf('hyudbwebuif') < 0) return; + emit({event:'str-hit', num:num}); + // 立即堆枚举 Guava (会话密钥类!) + setTimeout(function(){ + try { + Java.perform(function(){ + Java.enumerateClassLoaders({ + onMatch: function(loader){ + try { + Java.classFactory.loader = loader; + Java.choose('com.tencent.turingfd.sdk.ams.ga.Guava', { + onMatch: function(inst){ + try { + var c = inst.c.value; + var d = inst.d.value; + var b = inst.b.value; + emit({event:'heap-guava', c:c, d:d, bLen: b ? b.length : -1, a: inst.a.value}); + } catch(e){ emit({event:'heap-guava-e', e:String(e).substring(0,80)}); } + }, + onComplete: function(){} + }); + Java.choose('com.tencent.turingfd.sdk.ams.ga.Perseus', { + onMatch: function(inst){ + try { + var g = inst.b.value; + emit({event:'heap-perseus', c: g ? g.c.value : null}); + } catch(e){} + }, + onComplete: function(){ emit({event:'heap-done'}); } + }); + } catch(e){} + }, + onComplete: function(){} + }); + }); + } catch(e){ emit({event:'heap-exc', e:String(e).substring(0,100)}); } + }, 300); + } catch(e){} + } + }); +}