docs(huya): 模拟器存活闪退诊断报告与 Frida 探测脚本证据

- 诊断报告: attach 主进程静默退出/EGL 崩溃, 仅约 4s 窗口可抓帧
- scripts: attach/spawn/hook/emu 系列 Frida 脚本与抓帧/验证工具
- evidence: identity/reqchain/frame/inputbuf/magic_buf/propedge 抓取样本,
  emu_* 存活对比, diag_* 策略实验, baseline 裸测基准
This commit is contained in:
yml2213
2026-08-27 17:58:32 +08:00
parent 36b5d78050
commit 49c5c36c05
100 changed files with 8666 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""T0: 基础对照实验 (2026-08-27 重做, 不用旧结论).
T1: spawn + attach(空session) + resume → 观察 15s, 死因=完整logcat
T2: spawn + resume (不attach) → 对照
每轮输出: pid 时间线 + 死亡时 logcat(main/crash/events + kernel) 关键行。
判定死亡: 主进程不存在 或 pid 变化 (KeepAlive 重启也算死)。
"""
from pathlib import Path
import frida, time, json, subprocess, sys, re
REMOTE = "127.0.0.1:31878"
ADB = ["adb", "-s", "127.0.0.1:5555"]
PACKAGE = "com.duowan.kiwi"
OUT = Path("/tmp/t0_basic.json")
def sh(*a): return subprocess.run(a, capture_output=True, text=True)
def adb(*a): return sh(*ADB, *a)
def main_pid():
r = adb("shell", "pidof", PACKAGE)
for p in r.stdout.strip().split():
rr = adb("shell", "cat", f"/proc/{p}/cmdline")
if rr.stdout.strip("\x00").strip() == PACKAGE:
return int(p)
return None
def run_case(d, kind, rnd):
adb("shell", "am", "force-stop", PACKAGE)
time.sleep(1.5)
adb("shell", "logcat", "-c")
adb("shell", "logcat", "-c", "-b", "crash")
pid = d.spawn([PACKAGE])
t0 = time.time()
session = None
if kind == "attach":
session = d.attach(pid)
d.resume(pid)
print(f"[T1.r{rnd}] spawn pid={pid} {'attach+resume' if kind=='attach' else '纯resume'} +{(time.time()-t0)*1000:.0f}ms", flush=True)
# 观察 15s
timeline = []
died_at = None
while time.time() - t0 < 15:
time.sleep(1.5)
mp = main_pid()
now = round(time.time() - t0, 1)
if mp is None:
died_at = now
timeline.append({"t": now, "main": None})
print(f" +{now}s 主进程消失 (死)", flush=True)
break
if mp != pid:
died_at = now
timeline.append({"t": now, "main": mp, "note": "pid变化"})
print(f" +{now}s pid变化 {pid}->{mp} (主进程死/重启)", flush=True)
break
timeline.append({"t": now, "main": mp})
# 抓日志
main_log = adb("shell", "logcat", "-d", "-t", "300").stdout
crash_log = adb("shell", "logcat", "-d", "-b", "crash", "-t", "100").stdout
# 关键筛选
keys = []
for line in (main_log.splitlines() + crash_log.splitlines()):
if re.search(r"msaoaid|nsdt|kist|guard|exit|kill|died|died|FATAL|Fatal|signal|Abort|SIGSEGV|SIGABRT|frida|avc:|SELinux|scudo|Suspicious|property|magisk|denied", line, re.I):
keys.append(line[:220])
print(f" 死亡={'是@'+str(died_at) if died_at else '否(存活)'} 关键日志行数={len(keys)}", flush=True)
for l in keys[-18:]:
print(f" L: {l}", flush=True)
try:
if session: session.detach()
except Exception: pass
try: d.kill(pid)
except Exception: pass
time.sleep(1)
return {"kind": kind, "round": rnd, "died_at": died_at, "timeline": timeline, "log_lines": keys[-40:]}
def main():
d = frida.get_device_manager().add_remote_device(REMOTE)
results = []
for rnd in (1, 2):
results.append(run_case(d, "attach", rnd))
results.append(run_case(d, "pure", 1))
OUT.write_text(json.dumps(results, ensure_ascii=False, indent=1))
print(f"[*] -> {OUT}", flush=True)
if __name__ == "__main__":
main()