ReadProcessMemory因PAGE_NOACCESS失败 VirtualProtectEx修改无效问题咨询
问题分析
- OpenProcess申请的权限不足。调用
VirtualProtectEx修改外部进程内存保护属性,必须额外添加PROCESS_VM_OPERATION权限,你当前仅申请了PROCESS_VM_READ和PROCESS_VM_WRITE权限,会直接导致VirtualProtectEx调用失败,保护属性不会发生变更。同时你没有添加VirtualProtectEx的返回值判断逻辑,无法感知到调用失败的问题。 - 代码中
VirtualProtectEx的调用处于注释状态,实际运行时没有执行修改保护属性的逻辑,自然无法解除PAGE_NOACCESS的限制。 - 硬编码内存地址可靠性极低。Windows的ASLR地址随机化机制会让程序每次启动时的基地址发生变化,你写死的地址仅对当前一次启动的目标进程有效,进程重启后地址就会失效。如果地址指向未提交的保留内存页,即使修改保护属性也无法读取,依然会返回
ERROR_PARTIAL_COPY错误。 - 缺少必要的返回值校验。原代码没有判断
OpenProcess返回的进程句柄是否有效,如果进程ID填写错误或者权限不足导致句柄获取失败,后续所有操作都会出错。
修复参考代码
void __fastcall TForm1::Button1Click(TObject *Sender) { DWORD procid = 992; HANDLE hproc; uintptr_t addrPosX = 0x7FF62C66DA20; // 改用更规范的地址类型 int iBuffer = 0; SIZE_T rw = 0; DWORD oldProtect; try { // 新增PROCESS_VM_OPERATION权限 hproc = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, procid); // 校验进程句柄是否有效 if (hproc == NULL) { lblPosX->Text = "打开进程失败,错误码:" + String(GetLastError()); return; } // 调用VirtualProtectEx并判断返回值 if (!VirtualProtectEx(hproc, (LPVOID)addrPosX, sizeof(iBuffer), PAGE_READWRITE, &oldProtect)) { lblPosX->Text = "修改内存保护失败,错误码:" + String(GetLastError()); CloseHandle(hproc); return; } // 读取内存 if (ReadProcessMemory(hproc, (LPCVOID)addrPosX, &iBuffer, sizeof(iBuffer), &rw)) { lblPosX->Text = "Value: " + String(iBuffer); } else { lblPosX->Text = "Value: Failed reading memory (" + String(GetLastError()) + ")"; } // 恢复原内存保护属性 VirtualProtectEx(hproc, (LPVOID)addrPosX, sizeof(iBuffer), oldProtect, &oldProtect); CloseHandle(hproc); } catch (Exception &e) { ShowMessage("Error: " + e.Message); } }
如果修改后依然出现VirtualProtectEx调用失败的情况,说明目标进程可能存在反调试、反内存修改的保护机制,需要针对对应的防护逻辑做额外处理。
内容的提问来源于stack exchange,提问作者user1854856
相关产品推荐
相关产品推荐

