import ctypes
import struct
import sys

PROCESS_ALL_ACCESS = 0x1F0FFF
PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008

kPoe2InGameStateStaticRva = 0x4430108

kernel32 = ctypes.windll.kernel32

pid = 43084
hProc = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
if not hProc:
    hProc = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, False, pid)
if not hProc:
    print("Cannot open process:", kernel32.GetLastError())
    sys.exit(1)

def rpm(addr, size):
    buf = (ctypes.c_char * size)()
    read = ctypes.c_size_t()
    if kernel32.ReadProcessMemory(hProc, ctypes.c_uint64(addr), buf, size, ctypes.byref(read)):
        return bytes(buf[:read.value])
    return b""

def rpm_u64(addr):
    b = rpm(addr, 8)
    return struct.unpack("<Q", b)[0] if len(b) == 8 else 0

def rpm_f32(addr):
    b = rpm(addr, 4)
    return struct.unpack("<f", b)[0] if len(b) == 4 else 0.0

# Lấy Base Address của PathOfExile.exe
import win32process
# Base thường là 0x7ff6afc20000
mod_base = 0x7ff6afc20000
# Kiểm tra PE header
dos = rpm(mod_base, 2)
if dos != b"MZ":
    print("Base address mismatch! Searching modules...")
    # Find module base via EnumProcessModules
    import win32api
    hMods = win32process.EnumProcessModules(hProc)
    for h in hMods:
        name = win32process.GetModuleFileNameEx(hProc, h)
        if "pathofexile" in name.lower():
            mod_base = h
            break

print(f"PathOfExile.exe Module Base: 0x{mod_base:X}")

in_game_state_ptr = rpm_u64(mod_base + kPoe2InGameStateStaticRva)
print(f"InGameState Pointer: 0x{in_game_state_ptr:X}")

if in_game_state_ptr:
    # Quét các con trỏ trong InGameState
    print("Scanning InGameState fields (+0x000 to +0x600):")
    for off in range(0x0, 0x600, 8):
        ptr = rpm_u64(in_game_state_ptr + off)
        if 0x100000000 <= ptr <= 0x7FFFFFFFFFFF:
            # Check vtable
            vt = rpm_u64(ptr)
            if 0x7FF600000000 <= vt <= 0x7FFF00000000:
                print(f"  +0x{off:03X} -> 0x{ptr:X} (vtable: 0x{vt:X})")

kernel32.CloseHandle(hProc)
