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