// 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=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'});