Files
live-hub-py/scripts/hook_memshot.py
T

100 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""R35: 清 turing 状态(保留登录) -> spawn -> bypass -> hook_memshot 内存快照.
产出 evidence/memshot_<HHMMSS>.json:
- dfp wire 全量 + backtrace
- 线上密文在进程内存中的全部拷贝 + ±2KB 邻域
- Perseus 会话密钥 + 静态密钥出现位置 + 16 字符候选密钥串
- zlib 流候选 (78 xx) 供主机 inflate 验证
"""
from __future__ import annotations
import json, subprocess, time
from pathlib import Path
import frida
REMOTE = "127.0.0.1:31878"
ADB = "5dd8c93f"
PACKAGE = "com.duowan.kiwi"
RE = Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0")
HERE = Path(__file__).resolve().parent.parent
OUT = HERE / "evidence" / ("memshot_" + time.strftime("%H%M%S") + ".json")
def clear_turing():
"""只清 turing 状态, 保留登录态 -> ~40s 内自动重注册上报."""
dirs = ["app_turingdfp", "app_turingfd"]
for d in dirs:
subprocess.run(["adb", "-s", ADB, "shell", "su", "-c",
f"rm -rf /data/data/{PACKAGE}/{d}/*"], capture_output=True)
# resinfo 清理 (配方 §11.55)
subprocess.run(["adb", "-s", ADB, "shell", "su", "-c",
f"find /data/data/{PACKAGE} -name 'resinfo*' -delete"], capture_output=True)
def main():
print("[*] clearing turing state (login kept)", flush=True)
clear_turing()
d = frida.get_device_manager().add_remote_device(REMOTE)
subprocess.run(["adb", "-s", ADB, "shell", "am", "force-stop", PACKAGE], capture_output=True)
time.sleep(1.5)
pid = d.spawn([PACKAGE])
print(f"[*] spawn pid={pid}", flush=True)
s = d.attach(pid)
try:
b = s.create_script((RE / "evidence/scripts/bypass_msaoaid_maps_skip_cleanup.js").read_text())
b.load()
except Exception as e:
print(f"[*] bypass err {e}", flush=True)
d.resume(pid)
result: dict = {}
got = {"post": False, "done": False}
def on(m, _):
if m.get("type") == "error":
print(f"[JS] {str(m)[:200]}", flush=True)
return
p = m.get("payload") or {}
ev = p.get("event")
if ev in ("post", "scan-done"):
got["post" if ev == "post" else "done"] = True
if ev == "post":
print(f"[+] dfpReport POST {p['num']}B", flush=True)
elif ev == "ranges":
print(f"[*] scanning {p['n']} rw- ranges ({p['bytes']//1024//1024}MB)", flush=True)
elif ev == "cipher-copies":
print(f"[+] cipher copies in memory: {p['n']}", flush=True)
elif ev == "perseus":
print(f"[+] Perseus key: {p.get('key')}", flush=True)
elif ev == "key-cands":
print(f"[+] key candidates: {p['n']}", flush=True)
elif ev == "zcand":
pass
elif ev == "scan-done":
print(f"[*] scan complete (zlib cands={p['zcands']})", flush=True)
result.setdefault(ev or "misc", []).append(p)
sc = s.create_script((HERE / "tools/frida/hook_memshot.js").read_text())
sc.on("message", on)
sc.load()
t0 = time.time()
while time.time() - t0 < 120:
time.sleep(2)
if got["done"]:
break
if got["post"] and time.time() - t0 > 60:
break
json.dump(result, open(OUT, "w"), indent=2)
print(f"[*] saved {OUT}", flush=True)
try:
s.detach()
except Exception:
pass
if __name__ == "__main__":
main()