feat(dfp): 🏆 dfpReport 加密完全攻破 — RC4+gzip, 12/12 密文解密+逐字节回验 (R35-R37)

This commit is contained in:
yml2213
2026-08-29 10:13:08 +08:00
parent 12fad07385
commit 4868a3b0e8
28 changed files with 4110 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""R36: hook libz deflate/inflate — 抓 XXTEA 输入明文 + 隐藏加密路径 backtrace."""
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"/("deflate_"+time.strftime("%H%M%S")+".json")
def clear_turing():
for d in ("app_turingdfp","app_turingfd"):
subprocess.run(["adb","-s",ADB,"shell","su","-c",f"rm -rf /data/data/{PACKAGE}/{d}/*"],capture_output=True)
subprocess.run(["adb","-s",ADB,"shell","su","-c",f"find /data/data/{PACKAGE} -name 'resinfo*' -delete"],capture_output=True)
def main():
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={}; got={"post":False,"out":False}
def on(m,_):
if m.get("type")=="error":
txt=str(m)
if "ClassNotFoundException" in txt: return
print(f"[JS] {txt[:160]}",flush=True); return
p=m.get("payload") or {}
ev=p.get("event")
if ev=="post": got["post"]=True; print(f"[+] POST {p['num']}B",flush=True)
elif ev=="deflate-out": got["out"]=True; print(f"[+] deflate-out #{p['i']} in={p['in_len']} out={p['total']}",flush=True)
elif ev=="deflate-found": print(f"[*] deflate export in {p['mod']}",flush=True)
elif ev=="inflate-in": print(f"[+] inflate-in {p['len']}B via {p['mod']}",flush=True)
result.setdefault(ev or "misc",[]).append(p)
sc=s.create_script((HERE/"tools/frida/hook_deflate.js").read_text())
sc.on("message",on); sc.load()
t0=time.time()
while time.time()-t0<150:
time.sleep(2)
if got["out"] and got["post"]: time.sleep(4); 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()
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""R36: hook libz deflate/inflate — 抓 XXTEA 输入明文 + 隐藏加密路径 backtrace."""
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"/("hy_"+time.strftime("%H%M%S")+".json")
def clear_turing():
for d in ("app_turingdfp","app_turingfd"):
subprocess.run(["adb","-s",ADB,"shell","su","-c",f"rm -rf /data/data/{PACKAGE}/{d}/*"],capture_output=True)
subprocess.run(["adb","-s",ADB,"shell","su","-c",f"find /data/data/{PACKAGE} -name 'resinfo*' -delete"],capture_output=True)
def main():
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={}; got={"post":False,"out":False}
seen_fns=set()
def events_ok(p):
seen_fns.add(p.get('fn')); return True
def on(m,_):
if m.get("type")=="error":
txt=str(m)
if "ClassNotFoundException" in txt: return
print(f"[JS] {txt[:160]}",flush=True); return
p=m.get("payload") or {}
ev=p.get("event")
if ev=="post": got["post"]=True; print(f"[+] POST {p['num']}B",flush=True)
elif ev=="armed-hy": print("[*] hy chain armed",flush=True)
elif ev=="call":
if len(seen_fns)<99: pass
elif ev=="call" and events_ok(p): got["out"]=True
elif ev=="deflate-found": print(f"[*] deflate export in {p['mod']}",flush=True)
elif ev=="inflate-in": print(f"[+] inflate-in {p['len']}B via {p['mod']}",flush=True)
result.setdefault(ev or "misc",[]).append(p)
sc=s.create_script((HERE/"tools/frida/hook_hy.js").read_text())
sc.on("message",on); sc.load()
t0=time.time()
while time.time()-t0<150:
time.sleep(2)
if got["out"] and got["post"]: time.sleep(4); 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()
+99
View File
@@ -0,0 +1,99 @@
#!/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()