I try to read all commited pages of a process (Win7-64). On most pages it works but it fails for a few pages. I cannot explain why. Here is my test programme (compiled x32, tested in 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;
}
I tired to look into the MEMORY_BASIC_INFORMATION for the failing pages but I didn't find anything strange there. Also the number of failing pages varies from run to run (in average about 5). WHat prevents me from reading these pages? Do I need to adjust some privilges in the process token?
A little bit of debugging and something interesting is identified: all pages that fail have protection bit PAGE_GUARD
set (see MSDN doc). As I interpret the docs, it is by design that you cannot read these pages with 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"));
}