Files
live-hub-py/tools/frida/hook_deflate.js
T

109 lines
4.1 KiB
JavaScript

// R36b: 只挂 libz.so 的 deflate/inflate — 抓 XXTEA 输入明文 + 隐藏路径 backtrace
// 教训: GL/EGL 驱动也有同名 deflate 导出但非 zlib ABI, hook 必崩 — 只认 libz.so
'use strict';
function emit(o){ try{ send(o); }catch(e){} }
function hexb(p,n){ try{ return Array.from(new Uint8Array(p.readByteArray(n))).map(b=>('0'+b.toString(16)).slice(-2)).join(''); }catch(e){ return ''; } }
function bt(ctx, depth){
var out = [];
try {
var fr = Thread.backtrace(ctx, Backtracer.ACCURATE).slice(0, depth).map(function(a){
var m = Process.findModuleByAddress(a);
return m ? m.name + '!0x' + a.sub(m.base).toString(16) : a.toString();
});
if (fr.length) return fr;
} catch(e){}
try {
out = Thread.backtrace(ctx, Backtracer.FUZZY).slice(0, depth).map(function(a){
var m = Process.findModuleByAddress(a);
return 'F:' + (m ? m.name + '!0x' + a.sub(m.base).toString(16) : a.toString());
});
} catch(e){}
return out;
}
// z_stream (LP64): next_in@0 avail_in@8 total_in@16 next_out@24 avail_out@32 total_out@40
var streams = {};
var nDumps = 0;
var armed = false;
function armDeflate(){
if (armed) return;
var libz = Process.findModuleByName('libz.so');
if (!libz) return;
var d = null, i = null;
try { d = libz.getExportByName('deflate'); } catch(e){}
try { i = libz.getExportByName('inflate'); } catch(e){}
if (d) {
armed = true;
emit({event:'armed-deflate', mod:'libz.so'});
Interceptor.attach(d, {
onEnter(args){
var strm = args[0]; var flush = args[1].toInt32();
try {
var key = strm.toString();
var st = streams[key];
if (!st){
st = streams[key] = {out_base: strm.add(24).readPointer(), bt0: null, n: 0};
var nin = strm.add(8).readU32();
if (nin > 0 && nin < 200000){
st.in_hex = hexb(strm.readPointer(), Math.min(nin, 65536));
st.in_len = nin;
}
}
if (!st.bt0 && st.n < 3) st.bt0 = bt(this.context, 24);
st.n++;
this.strm = strm; this.flush = flush;
} catch(e){}
},
onLeave(ret){
try {
var st = streams[this.strm.toString()];
if (!st) return;
var zret = ret.toInt32();
var totalOut = this.strm.add(40).readU64().toNumber();
if (this.flush === 4 && (zret === 1 || zret === 0)){
// 只转储 turing 调用 (bt 含 turing) 或大输入 (Lyra 帧 JSON) — 其余是 UI 资源压缩噪音
var btStr = (st.bt0 || []).join(',');
var isTuring = /turing/i.test(btStr);
if (!isTuring && (st.in_len || 0) < 300){ delete streams[this.strm.toString()]; return; }
var hex = hexb(st.out_base, Math.min(totalOut, 131072));
nDumps++;
emit({event:'deflate-out', i:nDumps, total: totalOut, ret: zret, turing: isTuring,
in_len: st.in_len || 0, in_hex: st.in_hex || '', out_hex: hex, bt: st.bt0});
delete streams[this.strm.toString()];
}
} catch(e){}
}
});
}
if (i) {
// inflate 不挂 — 图片解码热路径, 挂了首屏卡死 (R36 教训)
}
}
var poll = setInterval(function(){ armDeflate(); if (armed) clearInterval(poll); }, 150);
// SSL_write: 抓同轮 wire 密文
var done = false;
for (var mod of Process.enumerateModules()){
var addr = null;
try { addr = mod.getExportByName('SSL_write'); } catch(e){}
if (!addr) continue;
Interceptor.attach(addr, {
onEnter(args){
if (done) return;
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<u.length;i++) s += (u[i]>=32 && u[i]<127) ? String.fromCharCode(u[i]) : '.';
if (s.indexOf('dfpReport') < 0) return;
done = true;
var hex = Array.prototype.map.call(u, function(x){return ('0'+x.toString(16)).slice(-2)}).join('');
emit({event:'post', num:num, hex:hex});
} catch(e){}
}
});
}
emit({event:'script-loaded'});