feat(dfp): 🔑 RC4 key=APK内嵌appkey常量(datadiv@3912240), 全流程零设备依赖闭环 (R38-R39)

This commit is contained in:
yml2213
2026-08-29 11:01:51 +08:00
parent 4868a3b0e8
commit 5fa1f6d082
13 changed files with 43643 additions and 2 deletions
+143
View File
@@ -0,0 +1,143 @@
// R38: 追踪 RC4 key (32hex) 的诞生点 — Java MessageDigest + udb md5 + 0x60e6c 反查副本
'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;
// ---- 1) Java MessageDigest 全量 (md5/sha1) ----
setImmediate(function(){
Java.perform(function(){
try {
var MD = Java.use('java.security.MessageDigest');
MD.digest.overload().implementation = function(){
var algo = this.getAlgorithm();
var out = this.digest();
try {
var hex = Array.prototype.map.call(out, function(b){ return ('0'+(b&0xff).toString(16)).slice(-2); }).join('');
nEvents++;
emit({event:'java-digest', algo: algo, out: hex});
} catch(e){}
return out;
};
MD.digest.overload('[B').implementation = function(inp){
var algo = this.getAlgorithm();
var out = this.digest(inp);
try {
var hex = Array.prototype.map.call(out, function(b){ return ('0'+(b&0xff).toString(16)).slice(-2); }).join('');
var inHex = Array.prototype.map.call(inp, function(b){ return ('0'+(b&0xff).toString(16)).slice(-2); }).join('');
nEvents++;
emit({event:'java-digest', algo: algo, out: hex, in_hex: inHex.substring(0,2048)});
} catch(e){}
return out;
};
emit({event:'java-md5-hooked'});
} catch(e){ emit({event:'java-e', e:String(e).substring(0,150)}); }
});
});
// ---- 2) udbauthunify md5 (0x32e71c) 原始参数 ----
function armUdb(){
var u = Process.findModuleByName('libudbauthunify.so');
if (!u) return false;
try {
Interceptor.attach(u.base.add(0x32e71c), {
onEnter(args){
this.a = [];
for (var i=0;i<4;i++) this.a.push({x:String(args[i]), h:hexb(args[i],96)});
this.lr = this.returnAddress;
},
onLeave(){
try {
var outs = [];
for (var i=0;i<2;i++) outs.push(hexb(this.a[i].x ? ptr(this.a[i].x) : ptr(0), 96));
nEvents++;
emit({event:'udb-md5', args:this.a, out_re:outs, lr: String(this.lr)});
} catch(e){}
}
});
emit({event:'udb-armed'});
return true;
} catch(e){ return false; }
}
// ---- 3) 0x60e6c 到位点 + 全内存反查 key 副本 ----
function armHy(){
var h = Process.findModuleByName('libhydeviceid.so');
if (!h) return false;
try {
Interceptor.attach(h.base.add(0x60e6c), {
onEnter(args){
try {
var s = '';
try { s = args[1].readCString(64); } catch(e){}
nEvents++;
emit({event:'key-site', x1:String(args[1]), key:s});
if (s && s.length === 32) {
setTimeout(function(){
var pat = '';
for (var i=0;i<16;i++) pat += s.substr(i,2).split('').join('')+' ' ;
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++;
emit({event:'key-copy', addr:String(m.address), src: r.file? r.file.path : String(r.base), around: hexb(m.address.sub(160), 352)});
}
if (n>=10) break;
}
emit({event:'key-copies-done', n:n});
}, 50);
}
} catch(e){ emit({event:'key-e', e:String(e).substring(0,150)}); }
}
});
// 4) JNI 边界 0x20e924 参数
Interceptor.attach(h.base.add(0x20e924), {
onEnter(args){
if (nEvents > 3000) return;
var rows=[];
for (var i=0;i<3;i++) rows.push({x:String(args[i]), h:hexb(args[i],48)});
nEvents++;
emit({event:'jni-boundary', args:rows});
}
});
emit({event:'hy-armed'});
return true;
} catch(e){ emit({event:'hy-e', e:String(e).substring(0,150)}); return false; }
}
var udb=false, hy=false;
var poll = setInterval(function(){
if (!udb) udb = armUdb();
if (!hy) hy = armHy();
if (udb && hy) clearInterval(poll);
}, 200);
// ---- 5) 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;
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'});