"""count_one_pid.py Quick scan of a single PID for all leak-class vtable counts. """ import ctypes, ctypes.wintypes as wt, struct, sys VTABLES = { "uiitem": 0x007c0498, "palette": 0x007caa08, "cphysicsobj": 0x007c78ec, "renderSurf": 0x0079a67c, "renderSurfD3D": 0x00801a94, "renderTexD3D": 0x00801a18, "csurface": 0x007ca4dc, "imgtex": 0x007cab04, "cgfxobj": 0x007ca418, "d3dxmesh": 0x007ed3b0, } PROCESS_VM_READ = 0x10 PROCESS_QUERY_INFORMATION = 0x400 MEM_COMMIT = 0x1000 MEM_PRIVATE = 0x20000 class MBI(ctypes.Structure): _fields_ = [('BaseAddress', ctypes.c_void_p), ('AllocationBase', ctypes.c_void_p), ('AllocationProtect', wt.DWORD), ('PartitionId', wt.WORD), ('RegionSize', ctypes.c_size_t), ('State', wt.DWORD), ('Protect', wt.DWORD), ('Type', wt.DWORD)] k = ctypes.windll.kernel32 k.OpenProcess.argtypes = [wt.DWORD, wt.BOOL, wt.DWORD]; k.OpenProcess.restype = wt.HANDLE k.CloseHandle.argtypes = [wt.HANDLE]; k.CloseHandle.restype = wt.BOOL k.ReadProcessMemory.argtypes = [wt.HANDLE, wt.LPCVOID, wt.LPVOID, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)] k.ReadProcessMemory.restype = wt.BOOL k.VirtualQueryEx.argtypes = [wt.HANDLE, ctypes.c_void_p, ctypes.POINTER(MBI), ctypes.c_size_t] k.VirtualQueryEx.restype = ctypes.c_size_t pid = int(sys.argv[1]) h = k.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, pid) if not h: print(f"OpenProcess({pid}) failed err={ctypes.get_last_error()}"); sys.exit(2) counts = {n: 0 for n in VTABLES} vt_to_name = {vt: name for name, vt in VTABLES.items()} mbi = MBI() addr = 0 while k.VirtualQueryEx(h, addr, ctypes.byref(mbi), ctypes.sizeof(mbi)): pr = mbi.Protect & 0xff if (mbi.State == MEM_COMMIT and mbi.Type == MEM_PRIVATE and pr in (0x04, 0x40)): buf = (ctypes.c_ubyte * mbi.RegionSize)() sz = ctypes.c_size_t(0) if k.ReadProcessMemory(h, mbi.BaseAddress, buf, mbi.RegionSize, ctypes.byref(sz)): data = bytes(buf[:sz.value]) end = (len(data) // 4) * 4 for off in range(0, end, 4): v = struct.unpack_from("= 0x80000000: break print(f"PID {pid}") for n in VTABLES: print(f" {n:14s} = {counts[n]:6d}") k.CloseHandle(h)