spawn_mm_and_hook.py 1.77 KB
#!/usr/bin/env python3
# 贴图号发布 hook 的真正入口点是 Ljs1/m;->c(TransferRequestInfo, callback)(见
# BRANDSERVICE_PUBLISH_RESEARCH.md §3.5),大概率跑在微信主进程(长驻,不是
# spawn-gating 能抓的子进程)。长驻进程 Java.perform 枚举存量类会超时,唯一办法是
# force-stop 整个微信、用 frida 重新 spawn 它,在类加载膨胀之前就把钩子挂上
# (跟之前抓 appbrand 子进程用的是同一个技巧,只是这次 spawn 的是整个 App)。
#
# 用法: source .venv/bin/activate && python3 spawn_mm_and_hook.py
import subprocess
import time

import frida

PACKAGE = "com.tencent.mm"
SCRIPT_PATH = "../wechat_send_internal/hook_transfer_sink_bundled.js"


def on_message(message, data):
    if message["type"] == "send":
        print(f"[msg] {message['payload']}")
    elif message["type"] == "error":
        print(f"[error] {message.get('stack', message)}")


def main():
    print(f"[*] force-stopping {PACKAGE} ...")
    subprocess.run(
        ["adb", "shell", "su", "-c", f"am force-stop {PACKAGE}"], check=True
    )
    time.sleep(1)

    device = frida.get_usb_device(timeout=10)
    with open(SCRIPT_PATH) as f:
        source = f.read()

    print(f"[*] spawning {PACKAGE} (paused) ...")
    pid = device.spawn([PACKAGE])
    print(f"[+] spawned pid={pid}, attaching...")
    session = device.attach(pid)
    script = session.create_script(source)
    script.on("message", on_message)
    script.load()
    print("[+] script loaded, resuming...")
    device.resume(pid)
    print(f"[*] {PACKAGE} resumed (pid={pid}). Reopen WeChat on the phone and redo the flow.")

    try:
        while True:
            time.sleep(3600)
    except KeyboardInterrupt:
        print("stopping")


if __name__ == "__main__":
    main()