我通过VirtualProtect
为当前线程的堆栈页面添加了PAGE_GUARD
保护,但是,在访问堆栈时,我安装的异常处理程序从未执行。
我假设操作系统只是默默地接受了保护页违规异常,因为它使用保护页来管理堆栈增长和堆栈溢出。
在这种情况下,是否有可能捕获这些异常?
这是我的C代码
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
LONG WINAPI BlanketExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) {
printf("exception code: %lx\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
return EXCEPTION_CONTINUE_SEARCH;
}
int main(void) {
// Install exception handler
SetUnhandledExceptionFilter(BlanketExceptionHandler);
ULONG_PTR stackBot = 0, stackTop = 0;
GetCurrentThreadStackLimits(&stackBot, &stackTop);
assert(stackBot < stackTop);
// turn all pages in the stack into guard-pages
DWORD savedProtect = 0;
if(!VirtualProtect((LPVOID) stackBot, stackTop - stackBot, PAGE_READWRITE | PAGE_GUARD, &savedProtect)){
fprintf(stderr, "[Error]: Could not add guard pages: %ld\n", GetLastError());
return 1;
}
// access some stack memory page. This should trigger the registered exception handler!
*(DWORD*) (stackTop - 0x1500) = 0xdeadbeef;
return 0;
}
需要使用编译代码
cl /nologo main.c /link /STACK:0x100000,0x100000
运行该代码不会从BlanketExceptionHandler
中得到任何输出,但是,使用VirtualQuery
时,我观察到堆栈页具有正确的保护。
我也试过通过AddVectoredExceptionHandler
安装异常处理程序,但也不起作用。
1条答案
按热度按时间ecbunoof1#
在这种情况下,是否有可能捕获这些异常?
否。如果您访问保护页,则例外(作为任何异常)首先将由内核代码处理。如果异常发生在当前线程堆栈范围内-内核处理程序从页面中删除
PAGE_GUARD
,其中exeception是,确保在此页下方-存在几个PAGE_GUARD
并在NT_TIB
中调整StackLimit := PAGE_ALIGN(MemmoryAccessAddress)
(您可以选中此选项)。并且不调用用户模式异常处理程序(如果这不是堆栈中的最后一页)代码示例:
和输出: