http://voneinem-windbg.blogspot.com/2008/02/shooting-pageguard-flag-with.html
转自这篇链接
XP上存在BUG,当一个线程ReadProcessMemory到另一个线程的内存时,会导致PAGE_GUARD丢失,另一个线程将失去chkstk的能力,会无法扩展堆栈
相关的逻辑制成测试代码如下:
PBYTE g_pStart1Thread = 0;
PBYTE g_pEnd1Thread = 0;
void MyTestProc_inner(HANDLE hWait)
{
char buffer_hello[4096] = {};
buffer_hello[0] = 'h';
buffer_hello[1] = 'e';
buffer_hello[2] = 'l';
buffer_hello[3] = 'l';
buffer_hello[4] = 'o';
printf("buffer=%s\n", buffer_hello);
g_pStart1Thread = (BYTE*)buffer_hello - 400000;
g_pEnd1Thread = (BYTE*)buffer_hello + sizeof(buffer_hello);
WaitForSingleObject(hWait, INFINITE);
printf("1 thread goon\n");
call_test();
printf("1 thread success end\n");
}
void MyTestProc(void * p)
{
MyTestProc_inner(reinterpret_cast<HANDLE>(p));
_endthread();
}
int main()
{
//return _tmain2();
SetDebugPrivilege(TRUE);
//一个线程读另一个线程才行
HANDLE hWaitForMe = CreateEvent(NULL, FALSE, FALSE, NULL);
uintptr_t hThread = _beginthread(MyTestProc, 0, hWaitForMe);
// give the thread time to start
::Sleep(1000);
//开始读取1线程的内存
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
if (hProcess)
{
{
MEMORY_BASIC_INFORMATION meminfo;
PBYTE pAddress = g_pStart1Thread;
//从低到高遍历每个区域
while (
pAddress <= g_pEnd1Thread &&
(VirtualQueryEx(hProcess, pAddress, &meminfo, sizeof(meminfo)) == sizeof(meminfo))
)
{
if (meminfo.State != MEM_FREE)//跳过已经释放的
{
MyMemRegion regioninfo;
regioninfo.addr = (BYTE*)meminfo.BaseAddress;
regioninfo.sz = meminfo.RegionSize;
g_vetRegions.push_back(regioninfo);
printf("%p: %u B, P=%X\n", meminfo.BaseAddress, (DWORD)meminfo.RegionSize, meminfo.Protect);
}
pAddress = (PBYTE)meminfo.BaseAddress + meminfo.RegionSize;
}
}
printf("=================================================================ANY KEY\n");
getchar();
for (size_t i = 0; i < g_vetRegions.size(); i++)
{
BYTE* pbb = (BYTE*)malloc(g_vetRegions[i].sz);
if (pbb)
{
memset(pbb, 0, g_vetRegions[i].sz);
SIZE_T SZ_Read = 0;
if (ReadProcessMemory(hProcess, g_vetRegions[i].addr, &pbb[0], g_vetRegions[i].sz, &SZ_Read)) {
CStringA str((char*)&(pbb[0]), 5);
printf("read ok sz=%u \"%s\"\n", (DWORD)SZ_Read, (LPCSTR)str);
}
else {
printf("read fail %u\n", GetLastError());
}
free(pbb);
}
else
{
printf("alloc fail %u\n", GetLastError());
}
}
printf("=================================================================\n");
{
MEMORY_BASIC_INFORMATION meminfo;
PBYTE pAddress = g_pStart1Thread;
//从低到高遍历每个区域
while (
pAddress <= g_pEnd1Thread &&
(VirtualQueryEx(hProcess, pAddress, &meminfo, sizeof(meminfo)) == sizeof(meminfo))
)
{
if (meminfo.State != MEM_FREE)//跳过已经释放的
{
printf("%p: %u B, P=%X\n",
meminfo.BaseAddress,
(DWORD)meminfo.RegionSize,
meminfo.Protect
);
}
pAddress = (PBYTE)meminfo.BaseAddress + meminfo.RegionSize;
}
}
printf("=================================================================\n");
CloseHandle(hProcess);
}
else
{
printf("err open proc %u\n", GetLastError());
}
//SetEvent 1GOON
SetEvent(hWaitForMe);
WaitForSingleObject(reinterpret_cast<HANDLE>(hThread), INFINITE);
printf("success end\n");
getchar();
return 0;
}