feat(dfp): 🏆 dfpReport 加密完全攻破 — RC4+gzip, 12/12 密文解密+逐字节回验 (R35-R37)
This commit is contained in:
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user