import ctypes
import struct

PROCESS_ALL_ACCESS = 0x1F0FFF
kernel32 = ctypes.windll.kernel32
h_proc = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, 43084)

def rpm(addr, size):
    buf = ctypes.create_string_buffer(size)
    bytes_read = ctypes.c_size_t(0)
    if kernel32.ReadProcessMemory(h_proc, ctypes.c_void_p(addr), buf, size, ctypes.byref(bytes_read)):
        return buf.raw
    return None

mod_base = 0x7FF6AFC20000

# Scan .text section: from mod_base + 0x1000, size ~ 0x2E85000 (46.5 MB)
# We search for displacement 0x9d0 (d0 09 00 00) and 0x9b8 (b8 09 00 00) and 0x9a0 (a0 09 00 00)
# in instructions like:
# [reg + 0x9d0] -> 48 8b ?? d0 09 00 00 or 8b ?? d0 09 00 00 or 0f b6 ?? d0 09 00 00

chunk_size = 2 * 1024 * 1024
text_start = mod_base + 0x1000
text_size = 0x2E85000

print(f"Scanning .text from {hex(text_start)} to {hex(text_start + text_size)}...")

matches_9d0 = []
matches_9b8 = []
matches_9a0 = []

target_9d0 = bytes([0xd0, 0x09, 0x00, 0x00])
target_9b8 = bytes([0xb8, 0x09, 0x00, 0x00])
target_9a0 = bytes([0xa0, 0x09, 0x00, 0x00])

curr = text_start
end = text_start + text_size
while curr < end:
    read_len = min(chunk_size, end - curr)
    data = rpm(curr, read_len)
    if not data:
        curr += chunk_size
        continue
    
    idx = 0
    while True:
        pos = data.find(target_9d0, idx)
        if pos == -1:
            break
        matches_9d0.append(curr + pos)
        idx = pos + 1
        
    idx = 0
    while True:
        pos = data.find(target_9b8, idx)
        if pos == -1:
            break
        matches_9b8.append(curr + pos)
        idx = pos + 1

    idx = 0
    while True:
        pos = data.find(target_9a0, idx)
        if pos == -1:
            break
        matches_9a0.append(curr + pos)
        idx = pos + 1

    curr += read_len - 16 # overlap

print(f"Found {len(matches_9d0)} references to 0x9d0")
print(f"Found {len(matches_9b8)} references to 0x9b8")
print(f"Found {len(matches_9a0)} references to 0x9a0")

# Disassemble around the first 5 references to 0x9d0
for addr in matches_9d0[:10]:
    disasm_addr = addr - 4
    bytes_window = rpm(disasm_addr, 16)
    hex_str = bytes_window.hex() if bytes_window else ""
    rva = addr - mod_base
    print(f"Ref 0x9d0 at {hex(addr)} (RVA: +{hex(rva)}): bytes: {hex_str}")

kernel32.CloseHandle(h_proc)
