如何确定Windows开放进程中可读取的内存地址?
解决ReadProcessMemory遇到不可读地址的问题
嘿,这在Windows进程内存扫描里绝对是高频踩坑点!我来给你几个实用的解决方案,帮你顺畅绕过这些不可读的内存区域:
1. 先用VirtualQueryEx预判地址可读性
在调用ReadProcessMemory之前,先用VirtualQueryEx查询目标地址的内存属性,提前筛掉不可读的区域。这个函数会返回MEMORY_BASIC_INFORMATION结构,里面的Protect字段能明确告诉你这块内存的访问权限。
示例代码(C++):
MEMORY_BASIC_INFORMATION mbi; if (VirtualQueryEx(hProcess, (LPCVOID)targetAddr, &mbi, sizeof(mbi))) { // 覆盖所有可能的可读保护标志 const DWORD readableFlags = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; if ((mbi.Protect & readableFlags) == 0) { // 这块内存不可读,直接跳过 continue; } } else { // 地址无效,同样跳过 continue; }
2. 分块读取,容错部分不可读区域
有时候目标地址所在的内存块不是完全不可读,可能只是其中某几页无法访问。你可以按系统页面大小(通常是4KB)拆分读取任务,逐个页面尝试读取,遇到不可读的页面就跳过,这样不会因为局部不可读导致整个读取任务失败。
3. 启用SeDebugPrivilege提升权限
有些进程(比如系统核心进程、受保护的安全进程)即使你用VM_READ打开了句柄,也会因为权限不足无法读取。这时候可以尝试启用当前进程的SeDebugPrivilege权限,这能让你获得更高的进程访问权限。
示例代码(C++):
BOOL EnableDebugPrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return FALSE; } LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); const BOOL result = (GetLastError() == ERROR_SUCCESS); CloseHandle(hToken); return result; }
记得在程序启动初期调用这个函数,提升权限后再尝试读取进程内存。
4. 用结构化异常处理(SEH)捕获访问异常
如果上面的预判方法没覆盖到所有边缘情况,你可以用Windows的结构化异常处理包裹ReadProcessMemory调用,当触发EXCEPTION_ACCESS_VIOLATION异常时,直接捕获并跳过当前地址。
示例代码(C++):
BYTE buffer[4096]; SIZE_T bytesRead; __try { BOOL success = ReadProcessMemory(hProcess, (LPCVOID)targetAddr, buffer, sizeof(buffer), &bytesRead); if (success) { // 处理读取到的数据 } } __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { // 捕获到不可读异常,跳过这个地址 continue; }
额外提醒
- 注意区分错误码:调用
ReadProcessMemory失败后,用GetLastError()获取错误码,ERROR_ACCESS_DENIED是权限问题,ERROR_INVALID_ADDRESS是地址无效,针对性处理会更高效。 - 受系统保护的进程(比如Windows Defender核心进程)即使有SeDebug权限也可能无法读取,这是系统安全机制,不要强行突破。
内容的提问来源于stack exchange,提问作者TheAnonyMoose1234512
相关产品推荐
相关产品推荐

