某些页面的ReadProcessMemory失败(GetLastError()=299)

问题描述 投票:4回答:2

我试图读取一个进程的所有已提交页面(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个)。是什么原因使我无法阅读这些页面?我是否需要调整进程标记中的一些权限?

winapi windows-7 kernel32 readprocessmemory
2个回答
6
投票

稍微调试了一下,发现了一些有趣的东西:所有失败的页面都有保护位。PAGE_GUARDMSDN文档). 根据我对文档的理解,这是设计好的,你不能用 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")); 
}

2
投票

32 位 Windows 上的页面大小与 64 位 Windows 上的页面大小不同。因此,页面大小是每个进程的值。您的进程的页面大小不一定与您读取的进程的页面大小相同。使用 RegionSize 成员 MEMORY_BASIC_INFORMATION 而不是。这就是受影响区域的实际大小。

© www.soinside.com 2019 - 2024. All rights reserved.