import ctypes, win32process, psutil

kernel32 = ctypes.windll.kernel32
PROCESS_VM_READ = 0x0010
PROCESS_QUERY_INFORMATION = 0x0400

candidates = [b"BoCuaCacCon", b"MeCuaCacCon", b"ConCuaBoMe", b"ConGailCung"]

with open(r"c:\Projects\JX\logs\scan_pids_out.txt", "w", encoding="utf-8") as out_f:
    for pid in [30076, 32572]:
        h_proc = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, pid)
        out_f.write(f"PID {pid} OpenProcess: {h_proc}\n")
        if h_proc:
            found = []
            addr = 0
            mbi = ctypes.create_string_buffer(48)
            while addr < 0x7FFFFFFF:
                res = kernel32.VirtualQueryEx(h_proc, ctypes.c_void_p(addr), mbi, 48)
                if not res:
                    break
                base = int.from_bytes(mbi[0:8], 'little')
                region_size = int.from_bytes(mbi[24:32], 'little')
                state = int.from_bytes(mbi[32:36], 'little')
                protect = int.from_bytes(mbi[36:40], 'little')
                
                if state == 0x1000 and (protect & 0xEE) != 0 and (protect & 0x01) == 0 and region_size < 10000000:
                    buf = ctypes.create_string_buffer(region_size)
                    read_bytes = ctypes.c_size_t()
                    if kernel32.ReadProcessMemory(h_proc, ctypes.c_void_p(base), buf, region_size, ctypes.byref(read_bytes)):
                        data = buf.raw[:read_bytes.value]
                        for cand in candidates:
                            if cand in data and cand not in found:
                                found.append(cand)
                addr = base + max(region_size, 4096)
            kernel32.CloseHandle(h_proc)
            out_f.write(f"PID {pid} found characters: {[c.decode() for c in found]}\n")
