feat(huya): dfpReport密文体实时捕获 (R17) — wsapi.huya.com端点+完整请求
- hook_ssl_magic.js: SSL_write明文扫魔数, 命中即全量dump+杀进程 - 捕获: 3798B POST (hyudbwebuif/dfpReport, tReq tag1=[10B魔数]+3531B密文) - 触发: 清turing状态重注册 (备份tar零副作用) - 动态插件定位: libturingmfa.so(v87)/libturingga.so(v2.92.2) - evidence/dfp_live/ 存档; docs §11.47
This commit is contained in:
@@ -1101,3 +1101,23 @@ dfpReport: tReq = [10B 魔数 57 18 82 cf 66 4b b3 94 01 ee][3988B 加密采
|
||||
- tools/frida/hook_dfp_java.js (Java 全量 hook — 太重, 会闪退, 弃用)
|
||||
- /tmp/turing/: mpdc1/ga2/tur 数据存档
|
||||
- 建议: turing-dfp 立为独立子项目 (证据链齐全); 或轻量运行时 trace 追 tReq 装配点
|
||||
|
||||
---
|
||||
|
||||
## §11.47 R17: dfpReport 密文体实时捕获成功 (2026-08-29) — turing 加密体现场!
|
||||
|
||||
### 捕获 (SSL_write 明文扫描, hook_ssl_magic.js)
|
||||
- 端点: **POST wsapi.huya.com** (okhttp) — 非 udbdf 域名!
|
||||
- 3798B 请求: hyudbwebuif/dfpReport WUP -> tReq{tag6="android-", tag1=[0dcb]3531B = [10B魔数 571882cf664bb39401ee] + 密文}
|
||||
- 证据: evidence/dfp_live/dfpReport_post_full.bin (完整 3798B HTTP POST)
|
||||
- 组件: libturingmfa.so(v87, tss;rfr;ite) + libturingga.so(v2.92.2) 动态插件 (app_dynamic_so_64/)
|
||||
- 密钥材料: mpdc_108298_1=32hex(0399ED0B...), getDfpConfig tRsp=81B密文配置, ga2(1860B), .turing.dat(64B)
|
||||
|
||||
### 触发方法 (重注册)
|
||||
- 备份 tar (604MB) -> 清 app_turingdfp/app_turingfd/resinfo -> 启动 -> 自动重注册 -> SSL_write 命中 -> 状态已再生 (ga2/resinfo 恢复)
|
||||
- 无副作用 (备份在 /data/local/tmp/dfp_backup.tar)
|
||||
|
||||
### 下一步 (turing-dfp 独立子项目)
|
||||
- 解析 WUP 完整结构 + 抓 SSL_read 响应
|
||||
- 破 getDfpConfig 81B 配置 (含加密钥?) -> 破 dfpReport 密文
|
||||
- 或运行时 trace 密文装配点 (SSL_magic 命中时刻的调用者)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
{"event": "treq-hooks", "installed": 2}
|
||||
@@ -0,0 +1 @@
|
||||
{"event": "treq-hooks", "installed": 2}
|
||||
@@ -0,0 +1 @@
|
||||
{"event": "treq-hooks", "installed": 2}
|
||||
@@ -0,0 +1 @@
|
||||
{"event": "treq-hooks", "installed": 2}
|
||||
@@ -0,0 +1 @@
|
||||
{"event": "treq-hooks", "installed": 2}
|
||||
@@ -0,0 +1,12 @@
|
||||
{"event": "ssl-hook", "module": "libjavacrypto.so"}
|
||||
{"event": "ssl-hook", "module": "libssl.so"}
|
||||
{"event": "ssl-hook", "module": "libhyssl.so"}
|
||||
{"event": "ssl-hook", "module": "libmarsstn.so"}
|
||||
{"event": "ssl-hook", "module": "libhyquic.so"}
|
||||
{"event": "ssl-hook", "module": "libngtcp2_crypto_boringssl.so"}
|
||||
{"event": "ssl-hook", "module": "libposix_quic_ngtcp.so"}
|
||||
{"event": "ssl-hook", "module": "libhysignalcore.so"}
|
||||
{"event": "ssl-hook", "module": "libhymediatrans.so"}
|
||||
{"event": "ssl-hook", "module": "libYCloudLive.so"}
|
||||
{"event": "ssl-hook", "module": "libhydt.so"}
|
||||
{"event": "ssl-magic", "module": "libjavacrypto.so", "num": 4201, "off": 257, "head": "571882cf664bb39401ee7cda1189c1750c9c4d56ddf3a91b0881cc464cb378e0397bdaa32175b402f2fa7ca4ad383247925ee3e31158ad8b6631b964f9c12ee6475e037bc5508deb6de633ac5100c8fde3b712b36cd6b570ec55131e60a866817e5e29da3128d1ef2eb49b88a9c1da529e208e3be6ae1383583aba1490d4643a06386723d5e2134f81830671d9ad1bfce909530228c2f84e9133a501a5486fd7", "bt": ""}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
function emit(row) { try { send(row); } catch (e) {} }
|
||||
function btOk() {
|
||||
try {
|
||||
return Thread.backtrace(this.context, Backtracer.ACCURATE).slice(0, 10).map(a => {
|
||||
const m = Process.findModuleByAddress(a);
|
||||
return m ? m.name + '!' + a.sub(m.base) : a.toString();
|
||||
}).join(' <- ');
|
||||
} catch (e) { return ''; }
|
||||
}
|
||||
const PREF = [0x57, 0x18, 0x82, 0xcf];
|
||||
let fired = false;
|
||||
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) {
|
||||
if (fired) return;
|
||||
const buf = args[1];
|
||||
const num = args[2].toInt32();
|
||||
if (num < 40) return;
|
||||
try {
|
||||
const b = buf.readByteArray(1 << 20 > num ? num : num); // 尽量读
|
||||
const u = new Uint8Array(b);
|
||||
for (let i = 0; i + 4 < u.length; i++) {
|
||||
if (u[i] === PREF[0] && u[i+1] === PREF[1] && u[i+2] === PREF[2] && u[i+3] === PREF[3]) {
|
||||
fired = true;
|
||||
const n = Math.min(num, 12000);
|
||||
const hex = Array.from((new Uint8Array(buf.readByteArray(n)))).map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
emit({ event: 'ssl-magic', module: mod.name, num, off: i, full: hex, bt: btOk() });
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
});
|
||||
emit({ event: 'ssl-hook', module: mod.name });
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
function emit(row) { try { send(row); } catch (e) {} }
|
||||
function btOk() {
|
||||
try {
|
||||
return Thread.backtrace(this.context, Backtracer.ACCURATE).slice(0, 8).map(a => {
|
||||
const m = Process.findModuleByAddress(a);
|
||||
return m ? m.name + '!' + a.sub(m.base) : a.toString();
|
||||
}).join(' <- ');
|
||||
} catch (e) { return ''; }
|
||||
}
|
||||
// tReq = [571882cf664bb39401ee][cipher] — 过滤向量/字符串写入
|
||||
const PREF = [0x57, 0x18, 0x82, 0xcf];
|
||||
const seen = {};
|
||||
function probeBuf(p, len) {
|
||||
try {
|
||||
if (len < 4) return false;
|
||||
const b = p.readByteArray(4);
|
||||
const u = new Uint8Array(b);
|
||||
return u[0] === PREF[0] && u[1] === PREF[1] && u[2] === PREF[2] && u[3] === PREF[3];
|
||||
} catch (e) { return false; }
|
||||
}
|
||||
const VECWRITE = '_ZN6udbjce15JceOutputStreamINS_12BufferWriterEE5writeINSt6__ndk19allocatorIcEEEEvRKNS4_6vectorIcT_EEh';
|
||||
const STRWRITE = '_ZN6udbjce15JceOutputStreamINS_12BufferWriterEE5writeERKNSt6__ndk112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEh';
|
||||
let installed = 0;
|
||||
for (const mod of Process.enumerateModules()) {
|
||||
for (const [name, kind] of [[VECWRITE, 'vec'], [STRWRITE, 'str']]) {
|
||||
let addr = null;
|
||||
try { addr = mod.getExportByName(name); } catch (e) {}
|
||||
if (addr === null) continue;
|
||||
Interceptor.attach(addr, {
|
||||
onEnter(args) {
|
||||
let data, len;
|
||||
try {
|
||||
if (kind === 'vec') {
|
||||
const begin = args[1].readPointer();
|
||||
const end = args[1].add(8).readPointer();
|
||||
len = end.sub(begin).toInt32();
|
||||
data = begin;
|
||||
} else {
|
||||
const flag = args[1].readU8();
|
||||
if ((flag & 1) === 0) { len = flag >> 1; data = args[1].add(1); }
|
||||
else { len = args[1].add(8).readU64().toNumber(); data = args[1].add(16).readPointer(); }
|
||||
}
|
||||
} catch (e) { return; }
|
||||
if (!probeBuf(data, len)) return;
|
||||
const key = mod.name + '|' + kind;
|
||||
if (seen[key]) return;
|
||||
seen[key] = true;
|
||||
let hex = '';
|
||||
try {
|
||||
const n = Math.min(len, 96);
|
||||
hex = Array.from(new Uint8Array(data.readByteArray(n))).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
} catch (e) {}
|
||||
emit({ event: 'treq-magic', module: mod.name, kind, len, head: hex, bt: btOk() });
|
||||
},
|
||||
});
|
||||
installed++;
|
||||
}
|
||||
}
|
||||
emit({ event: 'treq-hooks', installed });
|
||||
// 动态重扫: 每 2s 对新加载模块补挂 (插件/lib 延迟加载场景)
|
||||
const seenMods = {};
|
||||
setInterval(() => {
|
||||
for (const m of Process.enumerateModules()) {
|
||||
if (seenMods[m.name]) continue;
|
||||
seenMods[m.name] = true;
|
||||
for (const [name, kind] of [[VECWRITE, 'vec'], [STRWRITE, 'str']]) {
|
||||
let addr = null;
|
||||
try { addr = m.getExportByName(name); } catch (e) {}
|
||||
if (addr === null) continue;
|
||||
try {
|
||||
Interceptor.attach(addr, {
|
||||
onEnter(args) {
|
||||
let data, len;
|
||||
try {
|
||||
if (kind === 'vec') { const b = args[1].readPointer(); const e = args[1].add(8).readPointer(); len = e.sub(b).toInt32(); data = b; }
|
||||
else { const f = args[1].readU8(); if ((f & 1) === 0) { len = f >> 1; data = args[1].add(1); } else { len = args[1].add(8).readU64().toNumber(); data = args[1].add(16).readPointer(); } }
|
||||
} catch (e2) { return; }
|
||||
if (!probeBuf(data, len)) return;
|
||||
const key = m.name + '|' + kind;
|
||||
if (seen[key] === undefined) { seen[key] = true; } else return;
|
||||
let hex = '';
|
||||
try { hex = Array.from(new Uint8Array(data.readByteArray(Math.min(len, 96)))).map(b => b.toString(16).padStart(2, '0')).join(''); } catch (e3) {}
|
||||
emit({ event: 'treq-magic', module: m.name, kind, len, head: hex, bt: btOk() });
|
||||
},
|
||||
});
|
||||
} catch (e4) {}
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
Reference in New Issue
Block a user