#!/usr/bin/env python3 """通用 bypass 健康检查器 — 三层面标准 (唯一判定工具). 层面1 进程: pid 不被杀、不换新 (换新 = 被静默杀后重启) 层面2 界面: Activity 轨迹持续推进, 通过 Splash 且最终停在主界面 (轨迹停滞 = 卡死) 层面3 崩溃: logcat 无 FATAL / 无 ANR 用法: bypass_healthcheck.py [attempts] [--recipe merged|original] [--watch 秒] 判定: 每次 attempt 三层全过 → 该次 PASS; 所有 attempt 都 PASS → 总 PASS. """ import subprocess, sys, time, re from pathlib import Path import frida ADB="5dd8c93f"; PKG="com.duowan.kiwi" RE=Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0") sys.path.insert(0,str(Path(__file__).resolve().parent)) from bypass_loader import load_bypass def sh(*a): return subprocess.run(list(a),capture_output=True,text=True).stdout def pid_of(): for l in sh("adb","-s",ADB,"shell","ps","-A").splitlines(): if l.rstrip().endswith(PKG): return l.split()[1] return None def main_thread_frozen(pid): """6s 采样主线程 utime 增量: 0 = 冻结 (前台卡死铁证)""" if not pid: return None def utime(): out=sh("adb","-s",ADB,"shell","su","-c",f"cat /proc/{pid}/task/{pid}/stat") f=out.split() return int(f[13])+int(f[14]) if len(f)>14 else None a=utime() if a is None: return None time.sleep(6) b=utime() return (b is None) or (b==a) def input_anr_warning(): log=sh("adb","-s",ADB,"logcat","-d") return ("Input dispatching timed out" in log) or ("ANR in com.duowan.kiwi" in log) def top_act(): out=sh("adb","-s",ADB,"shell","dumpsys","activity","activities") for line in out.splitlines(): if "Hist #0" in line and PKG in line: m=re.search(r"u0 ([\w.$]+) t\d+", line) return m.group(1) if m else "?" return None def load_merged(s, delay=11000): load_bypass(s, patch_guard_delay_ms=delay) def load_original(s): s.create_script((RE/"evidence/scripts/bypass_msaoaid_maps_art_callsite.js").read_text()).load() s.create_script((RE/"evidence/scripts/mask_frida_maps_only.js").read_text()).load() time.sleep(11) s.create_script((RE/"evidence/scripts/patch_guard_block_termination.js").read_text()).load() def check_once(recipe="merged", watch=45, guard_delay=11000): sh("adb","-s",ADB,"shell","am","force-stop",PKG); time.sleep(4) sh("adb","-s",ADB,"logcat","-c") d=frida.get_device_manager().add_remote_device("127.0.0.1:31878") pid0=d.spawn([PKG]); s=d.attach(pid0) (load_merged if recipe=="merged" else load_original)(s, guard_delay) if recipe=="merged" else load_original(s) d.resume(pid0) L1_ok=True; trail=[]; die=None t0=time.time() while time.time()-t0 '.join(r['trail']) or '(none)'}") total=all(r["PASS"] for r in results) print(f"TOTAL: {'PASS ✅' if total else 'FAIL ❌'} ({recipe} x{attempts})") sys.exit(0 if total else 1) if __name__=="__main__": main()