"""Decode the StartEventQuery filter-block encoding (HCAL R1.7). Extracts the `pRequestBuff` from the StartEventQuery WriteMessage body in the baseline (no filter) and filtered captures produced by scripts/Capture-EventFilter.ps1, dumps both, and marks where they diverge so the filter predicate (property name / comparison op / value) can be read off the empty-filter baseline. Output is diagnostic. Sanitize before copying into docs/. """ import base64 import json import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent CAPDIR = REPO_ROOT / "artifacts" / "reverse-engineering" / "instrumented-wcf-event-filter" PARAM = b"pRequestBuff" OP = b"StartEventQuery" def extract_request(path): if not path.exists(): return None for line in path.open(encoding="utf-8-sig"): if not line.strip(): continue rec = json.loads(line) if rec.get("Phase") != "WCF.WriteMessage.Body": continue body = base64.b64decode(rec["Base64"]) if OP not in body: continue i = body.find(PARAM) if i < 0: continue i += len(PARAM) for s in range(i, min(i + 16, len(body))): m = body[s] if m == 0x9E: return body[s + 2:s + 2 + body[s + 1]] if m == 0x9F: n = int.from_bytes(body[s + 1:s + 3], "little") return body[s + 3:s + 3 + n] if m == 0xA0: n = int.from_bytes(body[s + 1:s + 3], "little") return body[s + 3:s + 3 + n] return None def hexdump(label, buf): print(f"=== {label}: {len(buf)} bytes ===") for off in range(0, len(buf), 16): c = buf[off:off + 16] hp = " ".join(f"{x:02X}" for x in c) ap = "".join(chr(x) if 32 <= x < 127 else "." for x in c) print(f" {off:04X} {hp:<48} |{ap}|") print() def main() -> int: base = extract_request(CAPDIR / "event-filter-capture-baseline-latest.ndjson") filt = extract_request(CAPDIR / "event-filter-capture-filtered-latest.ndjson") if base is None or filt is None: print("Missing capture(s). Run scripts/Capture-EventFilter.ps1 first.") print(f" baseline: {'ok' if base is not None else 'MISSING'}") print(f" filtered: {'ok' if filt is not None else 'MISSING'}") return 1 hexdump("baseline (no filter) pRequestBuff", base) hexdump("filtered pRequestBuff", filt) # First divergence offset. n = min(len(base), len(filt)) div = next((i for i in range(n) if base[i] != filt[i]), n) print(f"== First divergence at offset 0x{div:04X} (lenBase={len(base)} lenFilt={len(filt)}) ==") print(" Filtered bytes from divergence (the inserted filter block):") tail = filt[div:] for off in range(0, len(tail), 16): c = tail[off:off + 16] hp = " ".join(f"{x:02X}" for x in c) ap = "".join(chr(x) if 32 <= x < 127 else "." for x in c) print(f" {div + off:04X} {hp:<48} |{ap}|") print("\n== Strings in filtered buffer ==") for enc, label in ((b"ascii", "ASCII"), (None, "UTF-16LE")): if enc == b"ascii": cur, start = [], 0 for i, x in enumerate(filt): if 32 <= x < 127: if not cur: start = i cur.append(chr(x)) else: if len(cur) >= 3: print(f" {label} 0x{start:04X} {''.join(cur)!r}") cur = [] else: i = 0 while i < len(filt) - 1: j, chars = i, [] while j < len(filt) - 1 and 32 <= filt[j] < 127 and filt[j + 1] == 0: chars.append(chr(filt[j])) j += 2 if len(chars) >= 3: print(f" {label} 0x{i:04X} {''.join(chars)!r}") i = j else: i += 1 return 0 if __name__ == "__main__": sys.exit(main())