我试图读取一个进程的所有已提交页面(Win7-64)。在大多数页面上都能正常工作,但有几页却失败了。我无法解释为什么。这是我的测试程序(编译x32,在Win7-64中测试)。
#include <windows.h>
void main()
{
HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId());
SYSTEM_INFO si;
ZeroMemory(&si,sizeof(SYSTEM_INFO));
GetSystemInfo(&si);
char* buf = new char[si.dwPageSize];
for (unsigned i = 0; i < 0x7fff0; i++)
{
void* baseOffs = (void*) (i * si.dwPageSize);
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi,sizeof(MEMORY_BASIC_INFORMATION));
if (VirtualQueryEx(hProc, baseOffs, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
{
MessageBox(NULL, TEXT("VirtualQueryEx failed"),TEXT(""),MB_OK);
}
if (mbi.State == MEM_COMMIT)
{
SIZE_T numByteWritten = 0;
if(ReadProcessMemory(hProc, baseOffs,buf,si.dwPageSize,&numByteWritten) == FALSE)
OutputDebugString(TEXT("bad\n")); //GetLastError()==ERROR_PARTIALLY_READ; numByteWritten == 0;
else
OutputDebugString(TEXT("good\n"));
}
}
delete[] buf;
}
我花了很长时间去查看失败页面的MEMORY_BASIC_INFORMATION,但我没有发现任何奇怪的地方。此外,失败页面的数量也因运行而异(平均约5个)。是什么原因使我无法阅读这些页面?我是否需要调整进程标记中的一些权限?
稍微调试了一下,发现了一些有趣的东西:所有失败的页面都有保护位。PAGE_GUARD
套 MSDN文档). 根据我对文档的理解,这是设计好的,你不能用 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"));
}
32 位 Windows 上的页面大小与 64 位 Windows 上的页面大小不同。因此,页面大小是每个进程的值。您的进程的页面大小不一定与您读取的进程的页面大小相同。使用 RegionSize
成员 MEMORY_BASIC_INFORMATION
而不是。这就是受影响区域的实际大小。