#!/usr/bin/env python3 """attach 模式抓模拟器自生成 32hex hdid (对比真机 ed0db8...). 核心: hook libudbauthunify.so: - BusinessCfg::setSafeDeviceId(0x26A2E0): a1+1008=sd, a1+1088=hdid (两者都写) - BusinessCfg::getHdid(0x26A484): this+1088 是 std::string 对象 - createWupDeviceInfo(0x2746A0): 返回结构 +152 = hdid std::string App 正常启动后 attach, 不做 spawn (spawn 挂起会 EGL 闪退)。 """ import sys, time, json import frida REMOTE = "127.0.0.1:31878" PACKAGE = "com.duowan.kiwi" JS = r""" 'use strict'; function readStdString(p){ if (p.isNull()) return null; try{ var first = p.readU8(); if ((first & 1) === 0) { // short string: len = first>>1 var len = first >> 1; return p.add(1).readUtf8String(len > 0 && len < 128 ? len : 0) || ''; } else { var data = p.readPointer(); var len = p.add(8).readU64(); if (len > 0 && len < 512) return data.readUtf8String(len) || ''; return null; } }catch(e){ return null; } } function log(t, m){ send({t:t, m:m}); } function tryInstall(){ var md = Process.findModuleByName('libudbauthunify.so'); if (!md){ return false; } log('mod', md.base.toString() + ' size=' + md.size); // setSafeDeviceId: a2=sd, a3=hdid (std::string*) Interceptor.attach(md.base.add(0x26A2E0), { onEnter: function(a){ this.sd = readStdString(a[1]); this.hd = readStdString(a[2]); }, onLeave: function(){ log('setSafeDeviceId', JSON.stringify({sd: (this.sd||'').slice(0,48), hd: (this.hd||'').slice(0,48)})); } }); // getHdid: this+1088 = std::string Interceptor.attach(md.base.add(0x26A484), { onEnter: function(a){ this.thiz = a[0]; }, onLeave: function(){ try{ var s = readStdString(this.thiz.add(1088)); log('getHdid', s ? ''+s : 'EMPTY'); }catch(e){ log('getHdid', 'ERR ' + e); } } }); // createWupDeviceInfo 输出 +152 hdid Interceptor.attach(md.base.add(0x2746A0), { onLeave: function(ret){ try{ var s = readStdString(ret.add(152)); log('wupDeviceInfo.hdid', s ? ''+s : 'EMPTY'); }catch(e){} } }); log('hooked', 'all'); return true; } var installed = false; function poll(){ if (!installed){ installed = tryInstall(); } if (!installed){ setTimeout(poll, 300); } } poll(); """ def main(): dev = frida.get_device_manager().add_remote_device(REMOTE) # 找 App 进程 attach pid = None for p in dev.enumerate_processes(): if p.name and PACKAGE in p.name: pid = p.pid break if not pid: print("App 未运行, 先启动:", PACKAGE) import subprocess subprocess.run(["adb", "-s", "127.0.0.1:5555", "shell", "monkey -p %s -c android.intent.category.LAUNCHER 1" % PACKAGE], capture_output=True) time.sleep(12) # 等 lib 加载 for p in dev.enumerate_processes(): if p.name and PACKAGE in p.name: pid = p.pid break if not pid: print("仍找不到进程"); return print("attach pid =", pid, flush=True) session = dev.attach(pid) def on_message(msg, data): if msg.get("type") == "send": pl = msg["payload"] print("[%s] %s" % (pl["t"], pl["m"]), flush=True) elif msg.get("type") == "error": print("JSErr:", str(msg)[:200], flush=True) script = session.create_script(JS) script.on("message", on_message) script.load() print("等待 hook 事件 (60s)...", flush=True) time.sleep(60) print("done", flush=True) if __name__ == "__main__": main()