#!/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()