feat(huya): turing密文流式模式判定 + 全双工捕获 (R18)
- 三样本差分: 仅5稳定字节(7cda+69c9f5头), 流式CTR+nonce非ECB - SSL_write+SSL_read 全双工: req4198B+resp108B 捕获, java侧拼body回溯实锤 - 采样集: golden+f1+f2 三份密文; dfp_live 存档 - turing专项起点: 密钥材料mpdc/81B配置/ga2 齐备
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
function emit(row) { try { send(row); } catch (e) {} }
|
||||
function btOk() {
|
||||
function btOk(ctx) {
|
||||
try {
|
||||
return Thread.backtrace(this.context, Backtracer.ACCURATE).slice(0, 10).map(a => {
|
||||
return Thread.backtrace(ctx, Backtracer.ACCURATE).slice(0, 14).map(a => {
|
||||
const m = Process.findModuleByAddress(a);
|
||||
return m ? m.name + '!' + a.sub(m.base) : a.toString();
|
||||
}).join(' <- ');
|
||||
@@ -11,29 +11,53 @@ function btOk() {
|
||||
const PREF = [0x57, 0x18, 0x82, 0xcf];
|
||||
let fired = false;
|
||||
for (const mod of Process.enumerateModules()) {
|
||||
// ---- SSL_write: 扫描明文请求缓冲中的魔数 -> 全量 dump + 回溯 ----
|
||||
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;
|
||||
if (addr !== null) {
|
||||
Interceptor.attach(addr, {
|
||||
onEnter(args) {
|
||||
const ctx = this.context;
|
||||
if (fired) return;
|
||||
const buf = args[1];
|
||||
const num = args[2].toInt32();
|
||||
if (num < 40) return;
|
||||
try {
|
||||
const u = new Uint8Array(buf.readByteArray(Math.min(num, 20000)));
|
||||
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 hex = Array.from(u).map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
emit({ event: 'ssl-magic', module: mod.name, num, off: i, full: hex, bt: btOk(ctx) });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
});
|
||||
emit({ event: 'ssl-hook', module: mod.name });
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
});
|
||||
emit({ event: 'ssl-hook', module: mod.name, fn: 'write' });
|
||||
}
|
||||
// ---- SSL_read: 捕获响应 (含 tRsp/t1/sdid 特征的才发) ----
|
||||
let rd = null;
|
||||
try { rd = mod.getExportByName('SSL_read'); } catch (e) {}
|
||||
if (rd !== null) {
|
||||
Interceptor.attach(rd, {
|
||||
onEnter(args) {
|
||||
this._rdBuf = args[1];
|
||||
this._rdNum = args[2].toInt32();
|
||||
this._rdMod = mod.name;
|
||||
},
|
||||
onLeave(retval) {
|
||||
const n = retval.toInt32();
|
||||
if (n <= 40 || n > 20000) return;
|
||||
try {
|
||||
const hex = Array.from(new Uint8Array(this._rdBuf.readByteArray(n))).map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
if (fired || hex.indexOf('74727370') >= 0 || hex.indexOf('dfp') >= 0) {
|
||||
emit({ event: 'ssl-readcap', module: this._rdMod, num: n, full: hex, bt: btOk(this.context) });
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
});
|
||||
emit({ event: 'ssl-hook', module: mod.name, fn: 'read' });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user