调用Win32 API无法在其他进程内存中找到指定字符串,求排查
我正在探索Win32技术,尝试在其他进程的内存中查找变量对应的字符串。启动记事本写入“hello”,或在Python解释器中保存变量后,均无法在其内存转储中找到目标内容。我已编写代码,为当前进程设置seDebugPrivilege权限,调用GetSystemInfo获取进程内存边界与页大小,遍历映射内存页查找“hello”的十六进制值,但始终失败。以下是我的代码:
from pymem.ressources.structure import MEMORY_BASIC_INFORMATION, SYSTEM_INFO from ctypes import windll, wintypes as w, POINTER, c_size_t from pymem import Pymem from ctypes import byref, sizeof, c_ulonglong, create_string_buffer import win32security, win32api VIRTUALQUERYEX = windll.kernel32.VirtualQueryEx VIRTUALQUERYEX.argtypes = w.HANDLE, w.LPCVOID, POINTER(MEMORY_BASIC_INFORMATION), c_size_t GETSYSTEMINFO = windll.kernel32.GetSystemInfo READPROCESSMEMORY = windll.kernel32.ReadProcessMemory READPROCESSMEMORY.argtypes = w.HANDLE, w.LPCVOID, w.LPVOID, c_size_t, POINTER(c_size_t) READPROCESSMEMORY.restype = w.BOOL MEM_COMMIT = 0x1000 MEM_IMAGE_TYPE = 0x1000000 MEM_MAPPED_TYPE = 0x40000 MEM_PRIVATE_TYPE = 0x20000 def get_system_info(): system_info = SYSTEM_INFO() GETSYSTEMINFO(byref(system_info)) return system_info def AdjustPrivilege(priv): flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY htoken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), flags) id = win32security.LookupPrivilegeValue(None, priv) newPrivileges = [(id, win32security.SE_PRIVILEGE_ENABLED)] val = win32security.AdjustTokenPrivileges(htoken, 0, newPrivileges) print(val) print(win32api.GetLastError()) process_handle = Pymem() process_handle.open_process_from_id(41616) AdjustPrivilege("seDebugPrivilege") system_info = get_system_info() min_addr = system_info.lpMinimumApplicationAddress max_addr = system_info.lpMaximumApplicationAddress page_size = system_info.dwPageSize memory_offset = min_addr hello = b"\x68\x65\x6C\x6C\x6F" while memory_offset < max_addr: memory_basic_information = MEMORY_BASIC_INFORMATION() count = c_ulonglong(0) if VIRTUALQUERYEX( process_handle.process_handle, memory_offset, byref(memory_basic_information), sizeof(memory_basic_information) ) == sizeof(memory_basic_information): memory_offset = memory_basic_information.BaseAddress memory_commit_region = memory_basic_information.State & MEM_COMMIT memory_type_mapped = memory_basic_information.Type & (MEM_MAPPED_TYPE | MEM_IMAGE_TYPE | MEM_PRIVATE_TYPE) if memory_commit_region and memory_type_mapped: buffer = create_string_buffer(memory_basic_information.RegionSize) if READPROCESSMEMORY( process_handle.process_handle, memory_offset, buffer, memory_basic_information.RegionSize, byref(count) ): print(hello in buffer.raw) if hello in buffer: break print(buffer.raw) memory_offset += memory_basic_information.RegionSize else: memory_offset += page_size
请问我哪里操作有误?
1. 权限调整时机错误
你是先打开目标进程,再提权,这会导致打开进程时的权限仍是未提升状态,后续内存读取可能因权限不足失败。正确顺序是先调用AdjustPrivilege提升权限,再打开目标进程。
2. 字符串编码不匹配
记事本默认使用Unicode(UTF-16LE)存储文本,"hello"在内存中的字节序列是b'\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00',而非你搜索的ASCII字节b"\x68\x65\x6C\x6C\x6F"。Python解释器中的字符串同样以Unicode形式存储,需对应搜索宽字符版本的字节序列。
3. 内存偏移更新逻辑错误
当VirtualQueryEx返回一个内存区域后,无论该区域是否符合读取条件,都应直接用memory_basic_information.RegionSize来更新memory_offset,而非在不符合条件时加page_size。因为一个内存区域的大小通常远大于页大小,用页大小偏移会导致重复处理同一区域的起始部分,甚至陷入循环。
4. 缓冲区搜索逻辑不一致
代码中同时使用hello in buffer.raw和hello in buffer:
buffer会在遇到第一个\0时截断字符串,无法搜索包含空字节的Unicode字符串;- 应统一使用
buffer.raw来搜索整个缓冲区的字节内容。
5. ReadProcessMemory读取完整性检查
除了判断ReadProcessMemory的返回值为True,还需验证count.value是否等于请求读取的RegionSize,避免因部分内存不可读导致的搜索遗漏。
修正后的关键代码片段
# 调整顺序:先提权再打开进程 AdjustPrivilege("seDebugPrivilege") process_handle = Pymem() process_handle.open_process_from_id(41616) # 替换为Unicode版本的hello字节序列 hello = b"\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00" while memory_offset < max_addr: memory_basic_information = MEMORY_BASIC_INFORMATION() count = c_ulonglong(0) if VIRTUALQUERYEX( process_handle.process_handle, memory_offset, byref(memory_basic_information), sizeof(memory_basic_information) ) == sizeof(memory_basic_information): current_region_size = memory_basic_information.RegionSize memory_offset = memory_basic_information.BaseAddress memory_commit_region = memory_basic_information.State & MEM_COMMIT memory_type_valid = (memory_basic_information.Type & (MEM_MAPPED_TYPE | MEM_IMAGE_TYPE | MEM_PRIVATE_TYPE)) != 0 if memory_commit_region and memory_type_valid: buffer = create_string_buffer(current_region_size) if READPROCESSMEMORY( process_handle.process_handle, memory_offset, buffer, current_region_size, byref(count) ) and count.value == current_region_size: if hello in buffer.raw: print(f"Found target at address: {hex(memory_offset + buffer.raw.find(hello))}") break # 无论是否处理,都用区域大小更新偏移 memory_offset += current_region_size
内容的提问来源于stack exchange,提问作者moti shaku

