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:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -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