"""RE bước 0 - Test khả năng OpenProcess/ReadProcessMemory trên vggame.exe (INV: chi DOC, khong bao gio ghi).
Chay thu khong admin truoc; neu that bai se chay lai bang elevated."""
from __future__ import annotations

import ctypes
import subprocess
from ctypes import wintypes

k32 = ctypes.WinDLL("kernel32", use_last_error=True)

PROCESS_VM_READ = 0x0010
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000

k32.OpenProcess.restype = wintypes.HANDLE
k32.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
k32.ReadProcessMemory.restype = wintypes.BOOL
k32.ReadProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPCVOID, wintypes.LPVOID, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)]
k32.CloseHandle.argtypes = [wintypes.HANDLE]

STATIC_NAME = 0x006DEC44
STATIC_LEVEL = 0x006DEC66
STATIC_MAP = 0x006966CC


def vggame_pids():
    out = subprocess.check_output(["tasklist", "/FI", "IMAGENAME eq vggame.exe", "/FO", "CSV", "/NH"], text=True, errors="replace")
    pids = []
    for line in out.splitlines():
        parts = [p.strip('"') for p in line.split('","')]
        if len(parts) >= 2 and parts[0].lower() == "vggame.exe":
            try:
                pids.append(int(parts[1]))
            except ValueError:
                pass
    return pids


def read_mem(h, addr, size):
    buf = ctypes.create_string_buffer(size)
    read = ctypes.c_size_t(0)
    ok = k32.ReadProcessMemory(h, ctypes.c_void_p(addr), buf, size, ctypes.byref(read))
    if not ok:
        return None
    return buf.raw[: read.value]


def main():
    import os
    print("is_admin_hint: use 'net session' check separately")
    for pid in vggame_pids():
        h = k32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
        if not h:
            err = ctypes.get_last_error()
            h2 = k32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, False, pid)
            print(f"PID {pid}: OpenProcess(VM_READ|QUERY) FAILED err={err} ; limited retry => {'OK' if h2 else 'FAIL'}")
            if h2:
                k32.CloseHandle(h2)
            continue
        name = read_mem(h, STATIC_NAME, 32)
        lvl = read_mem(h, STATIC_LEVEL, 4)
        mp = read_mem(h, STATIC_MAP, 8)
        nm = name.split(b"\x00", 1)[0].decode("latin1", "replace") if name else "?"
        lv = int.from_bytes(lvl, "little") if lvl else -1
        mapid = int.from_bytes(mp[0:4], "little") if mp else -1
        print(f"PID {pid}: OK name='{nm}' level~{lv} mapId~{mapid}")
        k32.CloseHandle(h)


if __name__ == "__main__":
    main()
