Snapshot of every non-log artifact under audit-runs/ from audits 003 through 058: findings.md per audit, comparison CSVs, probe diffs, schema docs, register-dump txts, lr-trace JSONL streams, the saved canary patch diffs, etc. ~284 files / ~52 MB total. Excluded (per .gitignore): probe stdout/stderr/log streams (the raw firehose), guest-memory dumps under audit-026/027/029 (4.5 GB of .bin files; *.bin pattern added to .gitignore this commit). Also adds the orphan audit-058-sub825070F0-activation directory that a subagent accidentally created at project-root instead of under xenia-rs/audit-runs/; relocated to its proper home. Purpose: cross-machine continuity. With these summaries committed, a fresh clone gives the next session the full per-audit context (findings + tables + cascade predictions) without dependence on local-only working tree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
99 lines
3.7 KiB
Python
99 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Compare canary's memory dump (Memory::Save format) against our --dump-addr
|
|
output for a list of target addresses. Output unified diff highlighting
|
|
divergent 4-byte words.
|
|
"""
|
|
import re
|
|
import struct
|
|
import sys
|
|
sys.path.insert(0, '/home/fabi/RE Project Sylpheed/xenia-rs/audit-runs/audit-023-canary-diff')
|
|
from parse_dump import parse, read_addr
|
|
|
|
DUMP_LOG_RE = re.compile(r'^\s*addr=0x([0-9a-fA-F]+)\s*$')
|
|
DUMP_LINE_RE = re.compile(r'^\s*\+0x([0-9a-fA-F]+):\s*((?:[0-9a-f]{2} ){15}[0-9a-f]{2})')
|
|
|
|
def parse_ours_log(path):
|
|
"""Parse ours' dump-addr log into {addr -> bytes}."""
|
|
with open(path) as f:
|
|
cur_addr = None
|
|
cur_bytes = bytearray()
|
|
out = {}
|
|
for line in f:
|
|
m = DUMP_LOG_RE.match(line)
|
|
if m:
|
|
if cur_addr is not None and cur_bytes:
|
|
out[cur_addr] = bytes(cur_bytes)
|
|
cur_addr = int(m.group(1), 16)
|
|
cur_bytes = bytearray()
|
|
continue
|
|
m = DUMP_LINE_RE.match(line)
|
|
if m and cur_addr is not None:
|
|
hexbytes = m.group(2).split()
|
|
cur_bytes.extend(int(b, 16) for b in hexbytes)
|
|
if cur_addr is not None and cur_bytes:
|
|
out[cur_addr] = bytes(cur_bytes)
|
|
return out
|
|
|
|
def fmt(addr, bytes_):
|
|
"""Return list of (offset, [4*be32 strings]) tuples."""
|
|
rows = []
|
|
for i in range(0, len(bytes_), 16):
|
|
row = bytes_[i:i+16]
|
|
words = []
|
|
for w in range(0, len(row), 4):
|
|
if w + 4 <= len(row):
|
|
words.append(f"{struct.unpack('>I', row[w:w+4])[0]:08x}")
|
|
rows.append((addr + i, words))
|
|
return rows
|
|
|
|
def main():
|
|
canary_dump = sys.argv[1] if len(sys.argv) > 1 else '/tmp/audit-023-canary-memory.dump'
|
|
ours_log = sys.argv[2] if len(sys.argv) > 2 else '/home/fabi/RE Project Sylpheed/xenia-rs/audit-runs/audit-023-canary-diff/ours-dump.log'
|
|
extra_log = sys.argv[3] if len(sys.argv) > 3 else '/home/fabi/RE Project Sylpheed/xenia-rs/audit-runs/audit-023-canary-diff/ours-extra.log'
|
|
|
|
heap_index, data = parse(canary_dump)
|
|
print()
|
|
ours = parse_ours_log(ours_log)
|
|
if extra_log:
|
|
try:
|
|
ours.update(parse_ours_log(extra_log))
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
diffs_total = 0
|
|
for addr in sorted(ours.keys()):
|
|
our_bytes = ours[addr]
|
|
n = len(our_bytes)
|
|
canary_bytes, name, _, _, status = read_addr(heap_index, data, addr, n)
|
|
print(f"\n=== addr {addr:#010x} (canary heap={name} status={status}) ===")
|
|
if canary_bytes is None:
|
|
print(f" canary: {status}")
|
|
continue
|
|
canary_rows = fmt(addr, canary_bytes)
|
|
our_rows = fmt(addr, our_bytes)
|
|
for (a1, w1), (a2, w2) in zip(canary_rows, our_rows):
|
|
assert a1 == a2
|
|
diff_marks = []
|
|
for c, o in zip(w1, w2):
|
|
if c == o:
|
|
diff_marks.append(" ")
|
|
else:
|
|
diff_marks.append(" !! ")
|
|
row_has_diff = any(c != o for c, o in zip(w1, w2))
|
|
if row_has_diff:
|
|
diffs_total += 1
|
|
canary_line = " ".join(w1)
|
|
our_line = " ".join(w2)
|
|
mark = "DIFF " if row_has_diff else " "
|
|
print(f" {mark}+{a1-addr:04x} canary: {canary_line}")
|
|
print(f" {mark} ours : {our_line}")
|
|
if row_has_diff:
|
|
marks = "".join(f" {m} " for m in diff_marks).rstrip()
|
|
# Print marker line if useful
|
|
# print(f" {marks}")
|
|
print(f"\n=== TOTAL DIFFERING ROWS: {diffs_total} ===")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|