- 诊断报告: attach 主进程静默退出/EGL 崩溃, 仅约 4s 窗口可抓帧 - scripts: attach/spawn/hook/emu 系列 Frida 脚本与抓帧/验证工具 - evidence: identity/reqchain/frame/inputbuf/magic_buf/propedge 抓取样本, emu_* 存活对比, diag_* 策略实验, baseline 裸测基准
79 lines
3.0 KiB
Python
79 lines
3.0 KiB
Python
"""用 frida attach 到运行中 App, hook __system_property_get,
|
|
记录虎牙派生读取的系统属性, 并测试替换某些属性后 hdid 是否变化.
|
|
"""
|
|
import frida, time, subprocess, sys, json, re, ssl, socket
|
|
|
|
PACKAGE="com.duowan.kiwi"
|
|
REMOTE="127.0.0.1:31878"
|
|
JS = r"""
|
|
'use strict';
|
|
send({type:'armed'});
|
|
function rcsv(p){try{return p.readCString(256)||'';}catch(e){return '';}}
|
|
var interest = ['ro.serialno','ro.product.model','ro.product.device',
|
|
'ro.boot.serialno','ro.hardware','ro.build.fingerprint','ro.build.id',
|
|
'ro.product.board','ro.product.manufacturer','ro.ril.miui.imei0',
|
|
'persist.sys.imei','gsm.imei','ro.boot.image','ro.boot.product',
|
|
'ro.kernel.qemu','init.svc.adbd','ro.product.cpu.abi','ro.build.version.sdk',
|
|
'ro.build.version.release','ro.product.brand','ro.product.name'];
|
|
function hook(){
|
|
var m = Process.findModuleByName('libc.so');
|
|
// dl_ prefixed variants first
|
|
var syms = ['__system_property_get','free'];
|
|
var target = Module.findExportByName('libc.so','__system_property_get');
|
|
if(!target){send({type:'info',k:'no-propget'});return;}
|
|
send({type:'info',k:'found',a:target.toString()});
|
|
Interceptor.attach(target,{
|
|
onEnter:function(a){
|
|
this.name = rcsv(a[0]);
|
|
},
|
|
onLeave:function(ret){
|
|
var ov = rcsv(this.ctx.x1); // __system_property_get 第二参数 value buffer (x1)
|
|
var sig = this.name+'='+ov;
|
|
// 只记录感兴趣的; 若想起记则全记
|
|
if(interest.indexOf(this.name)>=0 || 1){
|
|
send({type:'prop',name:this.name,val:ov.slice(0,80)});
|
|
}
|
|
// 可选替换
|
|
// if(this.name=='ro.serialno'){ this.ctx.x1.writeUtf8String('99999999999'); }
|
|
}
|
|
});
|
|
}
|
|
hook();
|
|
"""
|
|
|
|
def get_pid(d):
|
|
for _ in range(10):
|
|
r=subprocess.run(["adb","-s","127.0.0.1:5555","shell","pidof",PACKAGE],capture_output=True,text=True)
|
|
if r.stdout.strip(): return int(r.stdout.strip().split()[0])
|
|
time.sleep(1)
|
|
return None
|
|
|
|
def main():
|
|
subprocess.run(["adb","-s","127.0.0.1:5555","shell","am","force-stop",PACKAGE],capture_output=True)
|
|
time.sleep(1)
|
|
subprocess.run(["adb","-s","127.0.0.1:5555","shell","monkey","-p",PACKAGE,"-c","android.intent.category.LAUNCHER","1"],capture_output=True)
|
|
# attach 前等 app 起来但不触发派生(login 触发)
|
|
time.sleep(6)
|
|
d=frida.get_device_manager().add_remote_device(REMOTE)
|
|
pid=get_pid(d)
|
|
print("attaching pid",pid,flush=True)
|
|
if not pid:
|
|
print("no pid"); return
|
|
s=d.attach(pid)
|
|
props=[]
|
|
def on(m,dd):
|
|
if m.get('type')!='send':return
|
|
p=m.get('payload') or {}
|
|
if p.get('type')=='prop':
|
|
props.append((p['name'],p['val']))
|
|
print(f" {p['name']} = {p['val']}",flush=True)
|
|
sc=s.create_script(JS); sc.on('message',on); sc.load()
|
|
print("[*] hooked, 触发登录/活动 观察派生属性 20s...",flush=True)
|
|
# 触发动作让 app 读取属性
|
|
time.sleep(20)
|
|
print(f"[*] 共捕获 {len(props)} 次属性读取",flush=True)
|
|
try: s.detach()
|
|
except: pass
|
|
|
|
if __name__=="__main__": main()
|