docs(huya): 模拟器存活闪退诊断报告与 Frida 探测脚本证据
- 诊断报告: attach 主进程静默退出/EGL 崩溃, 仅约 4s 窗口可抓帧 - scripts: attach/spawn/hook/emu 系列 Frida 脚本与抓帧/验证工具 - evidence: identity/reqchain/frame/inputbuf/magic_buf/propedge 抓取样本, emu_* 存活对比, diag_* 策略实验, baseline 裸测基准
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""hook BusinessCfg::setSafeDeviceId + getHdid, 抓真实 hdid/safeDeviceId 生成值 + 调用栈.
|
||||
setSafeDeviceId(a1+1008=safeDeviceId, a1+1088=hdid), a2=argv1(safeDeviceId str), a3=argv2(hdid str)
|
||||
同时 hook createWupDeviceInfo 观察 DeviceInfo 组装.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import frida, time, subprocess, json
|
||||
REMOTE="127.0.0.1:31878"; PACKAGE="com.duowan.kiwi"
|
||||
RE=Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0")
|
||||
JS=r"""
|
||||
'use strict';
|
||||
function rcs(p,n){try{return p.readCString(n)||'';}catch(e){return '';}}
|
||||
function st7(p){ // std::string (libc++ short/long form)
|
||||
try{ var s=rcs(p,64); return s; }catch(e){return '<?>';}
|
||||
}
|
||||
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 '';}}
|
||||
|
||||
// setSafeDeviceId: a2=std::string*a=safeDeviceId, a3=std::string*a2=hdid
|
||||
function tryInstall(){
|
||||
var md=Process.findModuleByName('libudbauthunify.so');
|
||||
if(!md){ send({type:'waiting'}); return false; }
|
||||
send({type:'mod',base:md.base.toString()});
|
||||
Interceptor.attach(md.base.add(0x26A2E0),{
|
||||
onEnter:function(a){
|
||||
var sd=st7(a[1]); var hd=st7(a[2]);
|
||||
send({type:'setSd',sd:sd.slice(0,64),hd:hd.slice(0,64),tid:Process.getCurrentThreadId()});
|
||||
var bt=Thread.backtrace(this.context,Backtracer.ACCURATE).slice(0,14).map(function(x){return x.toString();});
|
||||
send({type:'bt',bt:bt});
|
||||
}
|
||||
});
|
||||
send({type:'setSd_hooked'});
|
||||
Interceptor.attach(md.base.add(0x26A484),{
|
||||
onEnter:function(){ this.out=this.context.x8; },
|
||||
onLeave:function(retval){
|
||||
try{
|
||||
var out=this.out;
|
||||
if(out.isNull()){ send({type:'getHdid',str:'NULL'}); return; }
|
||||
// std::string: 字节0的低位=SSO标志
|
||||
var first=out.readU8();
|
||||
if((first & 1)===0){
|
||||
// short string: len = first>>1; data in [out+1..]
|
||||
var len=first>>1; var s=out.add(1).readCString(Math.max(0,Math.min(len,80)));
|
||||
send({type:'getHdid',str:''+s,ln:len});
|
||||
} else {
|
||||
var p=out.readPointer(); var len=out.add(8).readU64(); var cap=out.add(16).readU64();
|
||||
var s=p.readCString(Math.max(0,Math.min(len,80)));
|
||||
send({type:'getHdid',str:''+s,ln:len,heap:true});
|
||||
}
|
||||
}catch(e){ send({type:'getHdid',err:String(e)}); }
|
||||
}
|
||||
});
|
||||
send({type:'getHdid_hooked'});
|
||||
return true;
|
||||
}
|
||||
var installed=false;
|
||||
function poll(){
|
||||
if(!installed){ installed=tryInstall(); }
|
||||
if(!installed){ setTimeout(poll,300); }
|
||||
}
|
||||
poll();
|
||||
"""
|
||||
def main():
|
||||
d=frida.get_device_manager().add_remote_device(REMOTE)
|
||||
for a in range(1,4):
|
||||
subprocess.run(["adb","-s","127.0.0.1:5555","shell","am","force-stop",PACKAGE],capture_output=True); time.sleep(1)
|
||||
pid=d.spawn([PACKAGE]); s=d.attach(pid)
|
||||
try:
|
||||
b=s.create_script((RE/"evidence/scripts/bypass_msaoaid_maps_skip_cleanup.js").read_text()); b.load()
|
||||
except: pass
|
||||
d.resume(pid)
|
||||
def on(m,dd):
|
||||
if m.get('type')=='error': print(f" JSErr {str(m)[:150]}",flush=True); return
|
||||
p=m.get('payload') or {}; t=p.get('type')
|
||||
if t in ('setSd','getHdid'):
|
||||
print(f"[att{a}] {t}: {p}",flush=True)
|
||||
elif t=='bt': print(" backtrace:",flush=True);
|
||||
elif t=='err' or t=='err2': print(f" {t}: {p}",flush=True)
|
||||
sc=s.create_script(JS); sc.on('message',on); sc.load()
|
||||
time.sleep(16)
|
||||
try: d.kill(pid)
|
||||
except: pass
|
||||
time.sleep(1)
|
||||
print("done",flush=True)
|
||||
if __name__=="__main__": main()
|
||||
Reference in New Issue
Block a user