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

# String: "visibility_fully_revealed"
# Let's find its exact address in .rdata
rdata_start = mod_base + 0x2E87000
rdata_size = 0xB7C000
rdata = rpm(rdata_start, rdata_size)

str_name = b"visibility_fully_revealed\x00"
pos = rdata.find(str_name)
if pos == -1:
    print("String not found!")
    exit(1)

str_addr = rdata_start + pos
print(f"'visibility_fully_revealed' is at {hex(str_addr)} (RVA: +{hex(str_addr - mod_base)})")

# Find pointers to str_addr in .rdata and .data
targets = [
    (b"visibility_fully_revealed\x00", str_addr),
    (b"visibility_walkable_revealed\x00", rdata_start + rdata.find(b"visibility_walkable_revealed\x00")),
    (b"use_revealed_bound\x00", rdata_start + rdata.find(b"use_revealed_bound\x00")),
    (b"revealed_bound\x00", rdata_start + rdata.find(b"revealed_bound\x00")),
    (b"RenderVisibility\x00", rdata_start + rdata.find(b"RenderVisibility\x00")),
]

# Scan .data and .rdata for pointers to these strings
for name, addr in targets:
    pat = struct.pack("<Q", addr)
    p_data = rpm(mod_base + 0x3A04000, 0xD16000)
    p_rdata = rdata
    
    idx = 0
    while True:
        p = p_rdata.find(pat, idx)
        if p == -1:
            break
        found = rdata_start + p
        print(f"[{name.decode().rstrip(chr(0))}] pointer found in .rdata at {hex(found)} (RVA: +{hex(found - mod_base)})")
        win = rpm(found - 16, 64)
        print("   Hex:", win.hex() if win else "none")
        idx = p + 1

kernel32.CloseHandle(h_proc)
