【发布时间】:2012-08-20 18:44:15
【问题描述】:
我尝试读取进程的所有已提交页面 (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)。是什么阻止我阅读这些页面?我需要调整进程令牌中的一些权限吗?
【问题讨论】:
-
我不知道,但是如果目标进程在 ReadProcessMemory 试图复制页面时取消映射页面会发生什么?收到此错误后,页面是否仍然提交?
-
是的,如果我在 ReadProcessMemory 失败后直接运行 VirtualQuery,它仍然会为该页面返回 State==MEM_COMMIT。我还在一个循环中对整个程序进行了两次测试,并且在两次运行中相同的页面都失败了。但是,当我多次运行该进程时,我会得到不同的页面(也有不同的编号)。
-
这是 64 位操作系统上的常见错误代码。不知道为什么,我怀疑 wow64 模拟器与它有关。
-
如果您通过
VirtualProtect将页面显式设置为可读会发生什么?查看您的程序如何运行,您可能正在访问不驻留在内存中的页面,并且ReadProcessMemory不会触发它们被分页,请尝试检查失败页面的内存信息类型。 -
仅供参考:“ERROR_PARTIAL_COPY 299 (0x12B) 只有部分 ReadProcessMemory 或 WriteProcessMemory 请求已完成”
标签: winapi windows-7 kernel32 readprocessmemory