"""用 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()