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

138 lines
5.2 KiB
JavaScript

// R38b: RC4 key 诞生点终极追踪 — MD5 transform 消息积累 + 到位点反查 + Java digest 输入
'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 ''; } }
var nEvents = 0;
var CAP = 2500;
// ---- 1) MD5 transform 消息积累 (libhydeviceid!0xc37c0, ror#7 核心) ----
var md5msgs = {}; // state -> [blockHex,...]
var md5order = [];
var md5calls = 0;
function armHy(){
var h = Process.findModuleByName('libhydeviceid.so');
if (!h) return false;
try {
Interceptor.attach(h.base.add(0xc37c0), {
onEnter(args){
if (md5calls > 1200) return;
md5calls++;
var st = args[0].toString();
var blk = hexb(args[1], 64);
if (!md5msgs[st]) { md5msgs[st] = []; md5order.push(st); if (md5order.length>60) {} }
md5msgs[st].push(blk);
}
});
// ---- 2) 0x60e6c 到位点 ----
Interceptor.attach(h.base.add(0x60e6c), {
onEnter(args){
try {
var s = '';
try { s = args[1].readCString(64); } catch(e){}
if (s.length !== 32) return;
nEvents++;
emit({event:'key-site', key:s, md5calls: md5calls, nstates: md5order.length});
// 倒出全部 MD5 消息 (每 state 拼接 blocks, 截 512B)
var dumped = 0;
for (var st of md5order){
if (dumped >= 40) break;
var full = md5msgs[st].join('');
nEvents++;
emit({event:'md5-msg', state: st, nblk: md5msgs[st].length, hex: full.substring(0, 1024)});
dumped++;
}
// 内存反查 key 副本
setTimeout(function(){
var pat = s.substring(0,16).split('').map(function(c){ return ('0'+c.charCodeAt(0).toString(16)).slice(-2); }).join(' ');
var n=0;
for (var r of Process.enumerateRanges('rw-')){
if (r.size > 96*1024*1024) continue;
var ms=[];
try { ms = Memory.scanSync(r.base, r.size, pat); } catch(e){ continue; }
for (var m of ms){
if (n>=10) break;
n++; nEvents++;
emit({event:'key-copy', addr:String(m.address), src: r.file? r.file.path : String(r.base), around: hexb(m.address.sub(192), 448)});
}
if (n>=10) break;
}
emit({event:'key-copies-done', n:n});
}, 30);
} catch(e){ emit({event:'key-e', e:String(e).substring(0,150)}); }
}
});
emit({event:'hy-armed'});
return true;
} catch(e){ return false; }
}
// ---- 3) Java MessageDigest: update 输入积累 ----
setImmediate(function(){
Java.perform(function(){
try {
var MD = Java.use('java.security.MessageDigest');
var pend = {}; // hashcode -> [hexchunks]
MD.update.overload('[B').implementation = function(b){
try {
var k = this.hashCode();
if (!pend[k]) pend[k]=[];
if (pend[k].length < 8) {
pend[k].push(Array.prototype.map.call(b, function(x){return ('0'+(x&0xff).toString(16)).slice(-2);}).join('').substring(0,2048));
}
} catch(e){}
return this.update(b);
};
MD.digest.overload().implementation = function(){
var algo = this.getAlgorithm();
var out = this.digest();
try {
var k = this.hashCode();
var hex = Array.prototype.map.call(out, function(b){ return ('0'+(b&0xff).toString(16)).slice(-2); }).join('');
if (nEvents < CAP) { nEvents++; emit({event:'java-digest', algo:algo, out:hex, in_parts:(pend[k]||[]).join('')}); }
delete pend[k];
} catch(e){}
return out;
};
MD.digest.overload('[B').implementation = function(b){
var algo = this.getAlgorithm();
var out = this.digest(b);
try {
var hex = Array.prototype.map.call(out, function(b2){ return ('0'+(b2&0xff).toString(16)).slice(-2); }).join('');
var inHex = Array.prototype.map.call(b, function(x){return ('0'+(x&0xff).toString(16)).slice(-2);}).join('');
if (nEvents < CAP) { nEvents++; emit({event:'java-digest', algo:algo, out:hex, in_parts:inHex.substring(0,4096)}); }
} catch(e){}
return out;
};
emit({event:'java-md5-hooked'});
} catch(e){ emit({event:'java-e', e:String(e).substring(0,150)}); }
});
});
// ---- 4) SSL_write 同轮标记 ----
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;
nEvents++;
emit({event:'post', num:num});
} catch(e){}
}
});
}
var armed=false;
var poll = setInterval(function(){ if (armHy()){ armed=true; clearInterval(poll);} }, 200);
emit({event:'script-loaded'});