#!/usr/bin/env python3 """summarize.py RUNS_DIR: one table row per run, then the verdict per pre-registered prediction. Reads every RUNS_DIR/*/result.json written by inside.py. Prints Markdown. Definitions are the ones in PREREG-probe.md: a lookup is a query the fake DNS logged; a collector attempt is a connection the fake TLS listener accepted with SNI = the collector; an inet syscall is any strace connect/send to an AF_INET/AF_INET6 address (AF_UNIX is local and not counted). """ import glob import json import os import sys COLLECTOR = "mobile.events.data.microsoft.com" N_SECONDS = 60 EXPECT_ATTEMPTS = {"posctl": "P0", "ort130-default": "P1", "ort130-apioff": "P3", "ort129-default": "P4"} EXPECT_SILENCE = {"ort130-envoff": "P2", "ort128-default": "P5"} def facts(r): dns = r.get("dns", []) tls = r.get("tls", []) inet = [c for c in (r.get("strace") or []) if c["family"] != "AF_UNIX"] lookups = [d["t_rel_s"] for d in dns if d["name"] == COLLECTOR] attempts = [t["t_rel_s"] for t in tls if t.get("sni") == COLLECTOR] q = r.get("queue", {}) rows = q.get("rows", []) return { "void": r.get("void") or (not r.get("selftest", {}).get("pass")), "rc": r.get("subject_rc"), "lookups": lookups, "other_dns": sorted({f'{d["name"]}/{d["qtype"]}' for d in dns if d["name"] != COLLECTOR}), "qtypes": sorted({d["qtype"] for d in dns if d["name"] == COLLECTOR}), "attempts": attempts, "other_tls": [t.get("sni") for t in tls if t.get("sni") != COLLECTOR], "http": len(r.get("http", [])), "inet": inet, "inet_not_sink": [c for c in inet if c["dst"] not in ("127.0.0.1:53", "127.0.0.2:443")], "strace_443": [c["t_rel_s"] for c in inet if c["call"] == "connect" and c["dst"] == "127.0.0.2:443"], "deviceid": r.get("deviceid", {}).get("exists"), "db": q.get("db_exists"), "rows": rows, "events": sorted({e for row in rows for e in row["events"]}), "canaries": sorted({c for row in rows for c in row["canaries"]}), "ses": r.get("tmp_ses", {}).get("exists"), "alpn": sorted({",".join(t.get("alpn") or []) for t in tls if t.get("sni") == COLLECTOR}), } def fmt_times(ts, n=6): s = ", ".join(f"{t:.1f}" for t in ts[:n]) return s + (f" … (+{len(ts) - n})" if len(ts) > n else "") def main(runs_dir): results = [] for p in sorted(glob.glob(os.path.join(runs_dir, "*", "result.json"))): with open(p) as f: results.append(json.load(f)) order = ["posctl", "ort130-default", "ort130-envoff", "ort130-apioff", "ort129-default", "ort128-default"] results.sort(key=lambda r: (order.index(r["arm"]) if r["arm"] in order else 99, str(r["rep"]))) print("| arm | rep | exit | self-test | collector lookups (n; s after launch) | TLS attempts, SNI = collector " "(n; s after launch) | inet syscalls (n; to anything but the two sinks) | deviceid / queue db / /tmp/.ses " "| queue rows after exit | event names in queue | canaries in queue |") print("|---|---|---|---|---|---|---|---|---|---|---|") by_arm = {} for r in results: f = facts(r) by_arm.setdefault(r["arm"], []).append(f) yn = lambda b: "yes" if b else "no" print(f'| {r["arm"]} | {r["rep"]} | {f["rc"]} | {"VOID" if f["void"] else "pass"} ' f'| {len(f["lookups"])}; {fmt_times(f["lookups"])} | {len(f["attempts"])}; {fmt_times(f["attempts"])} ' f'| {len(f["inet"])}; {len(f["inet_not_sink"])} ' f'| {yn(f["deviceid"])} / {yn(f["db"])} / {yn(f["ses"])} | {len(f["rows"])} ' f'| {", ".join(f["events"]) or "-"} | {", ".join(f["canaries"]) or "-"} |') print("\n## Verdicts against PREREG-probe.md\n") for arm, pid in {**EXPECT_ATTEMPTS, **EXPECT_SILENCE}.items(): runs = [f for f in by_arm.get(arm, []) if not f["void"]] if not runs: print(f"- **{pid} {arm}**: NO VALID RUNS") continue if arm in EXPECT_ATTEMPTS: ok = [any(t <= N_SECONDS for t in f["lookups"]) and any(t <= N_SECONDS for t in f["attempts"]) for f in runs] claim = f"≥1 collector lookup and ≥1 collector TLS attempt within {N_SECONDS} s" else: ok = [not f["lookups"] and not f["attempts"] and not f["other_dns"] and not f["other_tls"] and not f["http"] and not f["inet"] for f in runs] claim = "0 lookups, 0 TLS/HTTP attempts, 0 inet syscalls" verdict = "CONFIRMED" if all(ok) and len(runs) >= 3 else ("REFUTED" if not all(ok) else "INCOMPLETE") print(f"- **{pid} {arm}**: {verdict}: {claim}: held in {sum(ok)}/{len(runs)} valid runs") secondary(results, runs_dir) def secondary(results, runs_dir): """The pre-registered secondary measures (S1-S5) plus a few descriptive columns, one row per run.""" print("\n## Secondary measures, per run\n") print("| arm | rep | import done (s) | 1st attempt − import (s) | gaps between attempts (s) | ClientHello bytes; ALPN " "| DNS types | files created under /tmp | queue retry_count values | S5: raw deviceid / machine-id / hostname " "in queue | c:SHA256(deviceid) in queue | .ses installId in queue | interpreter path in queue | " "subject exit − its t_exit mark (s) |") print("|---|---|---|---|---|---|---|---|---|---|---|---|---|---|") for r in results: if r["arm"] == "posctl": continue f = facts(r) t0 = r["t_launch"] m = r.get("marks") or {} imp = m.get("t_import_done", t0) - t0 att = f["attempts"] gaps = ", ".join(f"{b - a:.1f}" for a, b in zip(att, att[1:])) or "-" hello = sorted({(t["bytes"], ",".join(t.get("alpn") or []) or "none") for t in r.get("tls", [])}) rows = f["rows"] flag = lambda key: "yes" if any(row[key] for row in rows) else "no" run_dir = os.path.join(runs_dir, f'{r["arm"]}-r{r["rep"]}') ses = (r.get("tmp_ses") or {}).get("content") or "" install_id = ses.split()[-1] if ses else None strings = "" if os.path.exists(os.path.join(run_dir, "queue", "strings.txt")): strings = open(os.path.join(run_dir, "queue", "strings.txt"), errors="replace").read() files = [x["path"].replace("/tmp/home/.cache/Microsoft/DeveloperTools/.onnxruntime/", "…/.onnxruntime/") for x in r.get("files_after", [])] print(f'| {r["arm"]} | {r["rep"]} | {imp:.3f} | {f"{att[0] - imp:.2f}" if att else "-"} | {gaps} ' f'| {"; ".join(f"{b}; {a}" for b, a in hello) or "-"} ' f'| {"+".join(sorted({d["qtype"] for d in r.get("dns", [])})) or "-"} | {", ".join(files) or "none"} ' f'| {",".join(sorted({str(row["retry_count"]) for row in rows})) or "-"} ' f'| {flag("raw_deviceid")} / {flag("raw_machine_id")} / {flag("hostname")} ' f'| {flag("device_hash_c_sha256_deviceid") if rows else "-"} ' f'| {("yes" if install_id and install_id in strings else "no") if rows else "-"} ' f'| {flag("interpreter_path_in_payload") if rows else "-"} ' f'| {r["t_exit_rel_s"] - (m.get("t_exit", t0) - t0):.3f} |') if __name__ == "__main__": main(sys.argv[1] if len(sys.argv) > 1 else os.path.join(os.path.dirname(os.path.abspath(__file__)), "runs"))