"""identify_d3d_vtable.py Read consecutive DWORDs from a candidate vtable address and report how many of them are valid d3d9.dll function pointers. IDirect3DDevice9 has 119 slots, IDirect3DTexture9 ~17, IDirect3D9 ~16. """ import ctypes, ctypes.wintypes as wt, sys, struct PROCESS_VM_READ = 0x10 PROCESS_QUERY_INFORMATION = 0x400 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)] D3D9_BASE = 0x6F4E0000 D3D9_END = 0x6F4E0000 + 0x17A000 def rd(h, va, n): buf = (ctypes.c_ubyte * n)(); sz = ctypes.c_size_t(0) if not k.ReadProcessMemory(h, va, buf, n, ctypes.byref(sz)): return None return bytes(buf[:sz.value]) pid = int(sys.argv[1]) va = int(sys.argv[2], 0) h = k.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, pid) if not h: print("OpenProcess fail"); sys.exit(2) data = rd(h, va, 4 * 130) if not data: print(f"unreadable at 0x{va:08x}"); sys.exit(3) # Count consecutive valid d3d9 function pointers slot_count = 0 slots = [] for i in range(130): if i*4 + 4 > len(data): break p = struct.unpack_from(' 3: break print(f"Vtable @ 0x{va:08x}: valid d3d9 slots = {slot_count}") print(f" Slot 0: 0x{slots[0]:08x}") if slot_count > 2: print(f" Slot 2: 0x{slots[2]:08x} (would be IUnknown::Release)") if slot_count > 16: print(f" Slot 16: 0x{slots[16]:08x} (could be IDirect3D9::CreateDevice if D3D9 vtable, or IDirect3DDevice9::Reset)") if slot_count > 23: print(f" Slot 23: 0x{slots[23]:08x} (would be IDirect3DDevice9::CreateTexture)") if slot_count > 28: print(f" Slot 28: 0x{slots[28]:08x} (would be IDirect3DDevice9::CreateRenderTarget)") # Identify if slot_count >= 119: print(f"\n*** LIKELY IDirect3DDevice9 (119 slots expected) ***") elif 14 <= slot_count <= 20: print(f"\nLIKELY IDirect3D9 or IDirect3DTexture9 (small)") elif 4 <= slot_count <= 10: print(f"\nLIKELY IUnknown derivative (very small)") else: print(f"\nUnknown — {slot_count} slots") k.CloseHandle(h)