"""dump_leaked_objects.py For each object with primary vtable 0x007caa08, dump full state. Also dump the first 256 bytes of the buffer it points to (if any). """ import struct, sys from collections import Counter from minidump.minidumpfile import MinidumpFile VTABLE_PRIMARY = 0x007caa08 VTABLE_SECONDARY = 0x007ca9f4 SECONDARY_OFFSET = 0x30 def _ei(v): if v is None: return 0 if hasattr(v, 'value'): return int(v.value) return int(v) def main(): md = MinidumpFile.parse(sys.argv[1]) reader = md.get_reader().get_buffered_reader() # Leaked regions leaked = [] leaked_set = set() for r in md.memory_info.infos: st, ty, pr = _ei(r.State), _ei(r.Type), _ei(r.Protect) & 0xff if st == 0x1000 and ty == 0x20000 and pr in (0x04, 0x40) \ and 256*1024 <= r.RegionSize < 512*1024: leaked.append((r.BaseAddress, r.RegionSize)) leaked_set.add(r.BaseAddress) def in_leaked(p): if p in leaked_set: return True for b, s in leaked: if b <= p < b + s: return (b, s) return False # Find all instances of vtable 0x007caa08 at offset 0 scan = [] for r in md.memory_info.infos: st, ty, pr = _ei(r.State), _ei(r.Type), _ei(r.Protect) & 0xff if st != 0x1000 or ty == 0x1000000 or pr not in (0x04, 0x40): continue scan.append((r.BaseAddress, r.RegionSize)) objs = [] for base, size in scan: try: reader.move(base); buf = reader.read(size) except Exception: continue if not buf: continue end = (len(buf) // 4) * 4 for off in range(0, end - 0x48, 4): if struct.unpack_from("= 8: break buf_ptr = f[0x10] if buf_ptr == 0: continue try: reader.move(buf_ptr); raw = reader.read(64) except Exception: continue if not raw: continue h = " ".join(f"{b:02x}" for b in raw) print(f" obj 0x{addr:08x} +0x40 -> 0x{buf_ptr:08x}: {h}") n_dumped += 1 if __name__ == "__main__": main()