"""count_uiitem_live.py Count UIElement_UIItem instances in a live process by scanning RW heap for the primary vtable pointer 0x007c0498. """ import argparse, ctypes, ctypes.wintypes as wt, struct, sys, time UIITEM_VTABLE = 0x007c0498 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.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 ap = argparse.ArgumentParser() ap.add_argument("pid", type=int) args = ap.parse_args() h = k.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, args.pid) if not h: print(f"OpenProcess({args.pid}) failed err={ctypes.get_last_error()}"); sys.exit(2) # Count UIITEM_VTABLE pointers AND count cleared cells (item-GUID == 0 at +0x5fc) all_instances = [] 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 # For each instance, read +0x5fc (item GUID) zero_guid = 0 nonzero_guid = 0 for inst_addr in all_instances: guid_addr = inst_addr + 0x5fc buf4 = (ctypes.c_ubyte * 4)() sz4 = ctypes.c_size_t(0) if k.ReadProcessMemory(h, guid_addr, buf4, 4, ctypes.byref(sz4)): guid = struct.unpack("