import ctypes
import ctypes.wintypes as w
import struct

k32 = ctypes.WinDLL('kernel32', use_last_error=True)
h = k32.OpenProcess(0x1F0FFF, False, 37676)

class MEMORY_BASIC_INFORMATION(ctypes.Structure):
    _fields_ = [
        ('BaseAddress', ctypes.c_uint64),
        ('AllocationBase', ctypes.c_uint64),
        ('AllocationProtect', ctypes.c_ulong),
        ('__alignment1', ctypes.c_ulong),
        ('RegionSize', ctypes.c_size_t),
        ('State', ctypes.c_ulong),
        ('Protect', ctypes.c_ulong),
        ('Type', ctypes.c_ulong),
        ('__alignment2', ctypes.c_ulong),
    ]

vtable = 0x7ff6b31c24c0
v_bytes = struct.pack('<Q', vtable)

mbi = MEMORY_BASIC_INFORMATION()
addr = 0
found = []
max_addr = 0x7fffffffffff

while addr < max_addr:
    res = k32.VirtualQueryEx(h, ctypes.c_void_p(addr), ctypes.byref(mbi), ctypes.sizeof(mbi))
    if not res:
        break
    base_addr = mbi.BaseAddress
    reg_size = mbi.RegionSize
    if mbi.State == 0x1000 and (mbi.Protect & 0xEE) and not (mbi.Protect & 0x100):
        chunk_sz = 4 * 1024 * 1024
        cur = base_addr
        end = base_addr + reg_size
        while cur < end:
            read_len = min(chunk_sz, end - cur)
            buf = (ctypes.c_ubyte * read_len)()
            got = ctypes.c_size_t(0)
            if k32.ReadProcessMemory(h, ctypes.c_void_p(cur), buf, read_len, ctypes.byref(got)):
                data = bytes(buf[:got.value])
                idx = 0
                while True:
                    idx = data.find(v_bytes, idx)
                    if idx == -1:
                        break
                    match_addr = cur + idx
                    found.append(match_addr)
                    idx += 8
            cur += read_len
    addr = base_addr + reg_size

print(f"Found {len(found)} instances of vtable {vtable:#x}:")
for fa in found:
    print(f"  Camera Instance Addr: {fa:#x}")
