Winapi ReadProcessMemory在某些页面上失败(GetLastError()=299)

Winapi ReadProcessMemory在某些页面上失败(GetLastError()=299),winapi,windows-7,kernel32,readprocessmemory,Winapi,Windows 7,Kernel32,Readprocessmemory,我尝试读取进程的所有提交页面(Win7-64)。在大多数页面上,它都可以工作,但在少数页面上失败。我无法解释原因。这是我的测试程序(编译为x32,在Win7-64中测试): #包括 void main() { HANDLE hProc=OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId()); 系统信息系统; 零内存(&si,sizeof(系统信息)); GetSystemInfo&s

我尝试读取进程的所有提交页面(Win7-64)。在大多数页面上,它都可以工作,但在少数页面上失败。我无法解释原因。这是我的测试程序(编译为x32,在Win7-64中测试):

#包括
void main()
{
HANDLE hProc=OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId());
系统信息系统;
零内存(&si,sizeof(系统信息));
GetSystemInfo&si;
char*buf=新字符[si.dwPageSize];
for(无符号i=0;i<0x7fff0;i++)
{
void*baseOffs=(void*)(i*si.dwPageSize);
存储器基本信息mbi;
零内存(&mbi,sizeof(内存基本信息));
if(VirtualQueryEx(hProc、baseOffs和mbi、sizeof(内存基本信息))==0)
{
MessageBox(NULL,文本(“VirtualQueryEx失败”),文本(“”),MB_OK);
}
if(mbi.State==MEM_COMMIT)
{
大小=0;
if(ReadProcessMemory(hProc、baseOffs、buf、si.dwPageSize和numbytewrited)==FALSE)
OutputDebugString(TEXT(“bad\n”);//GetLastError()==ERROR\u PARTIALLY\u READ;numbyteWrite==0;
其他的
OutputDebugString(文本(“良好”);
}
}
删除[]buf;
}

我努力寻找失败页面的记忆基本信息,但没有发现任何奇怪的地方。此外,失败页面的数量因运行而异(平均约5个)。是什么阻止我阅读这些页面?是否需要调整进程令牌中的某些权限?

32位窗口上的页面大小与64位窗口上的页面大小不同。因此,页面大小是每个进程的值。进程的页面大小不一定与正在读取的进程的页面大小相同。使用
内存基本信息
区域大小
成员。这是受影响区域的实际大小。

经过一点调试,发现了一些有趣的东西:所有失败的页面都设置了保护位
PAGE\u GUARD
(请参阅)。在我解释这些文档时,根据设计,您无法使用
ReadProcessMemory
阅读这些页面

if(ReadProcessMemory(hProc, baseOffs,buf,si.dwPageSize,&numByteWritten) == FALSE) {
    assert(mbi.Protect & 0x100);
    OutputDebugString(TEXT("bad\n")); //GetLastError()==ERROR_PARTIALLY_READ; numByteWritten == 0; 
}
else {
    assert(!(mbi.Protect & 0x100));
    OutputDebugString(TEXT("good\n")); 
}

我不知道,但是如果目标进程在ReadProcessMemory试图复制页面时取消了该页面的映射,会发生什么情况?收到此错误后,页面是否仍然提交?是的,如果在ReadProcessMemory失败后直接运行VirtualQuery,它仍然会返回该页面的状态==MEM_COMMIT。我还对整个程序进行了另一次测试,在一个循环中测试了两次,在两次运行中,相同的页面都失败了。但是,当我多次运行该进程时,会得到不同的页面(也是不同的编号)。这是64位操作系统上常见的错误代码。不知道为什么,我怀疑wow64模拟器与此有关。如果通过
VirtualProtect
将页面显式设置为可读,会发生什么情况?查看程序的运行方式,您可能正在访问不在内存中的页面,并且
ReadProcessMemory
不会触发它们被分页,请尝试检查失败页面的内存信息类型。仅供参考:“错误\u部分\u COPY 299(0x12B)ReadProcessMemory或WriteProcessMemory请求仅完成了一部分”然而我想,我已经仔细检查了,你是完全正确的。我添加了VirtualProtectEx来暂时移除旗帜,一切都很好。谢谢你的提示。我了解了GetSystemInfo()和GetNativeSystemInfo()的区别。然而,在我的操作系统中,这两种尺寸是相同的。RegionSize通常包含多个页面。但您是对的,一次处理较大的块是有意义的。
if(ReadProcessMemory(hProc, baseOffs,buf,si.dwPageSize,&numByteWritten) == FALSE) {
    assert(mbi.Protect & 0x100);
    OutputDebugString(TEXT("bad\n")); //GetLastError()==ERROR_PARTIALLY_READ; numByteWritten == 0; 
}
else {
    assert(!(mbi.Protect & 0x100));
    OutputDebugString(TEXT("good\n")); 
}