我正在写一个小字节码,解释语言(或框架?vm?)。我知道Windows在堆栈上使用PAGE_GUARD
,我想使用它。
首先,我保留虚拟内存并在一页上执行MEM_COMMIT / PAGE_GUARD。
pStack->end = VirtualAlloc(NULL, MaxSize, MEM_RESERVE, PAGE_READWRITE);
if (pStack->end != NULL)
{
pStack->bp = pStack->sp = pStack->base = pStack->end + MaxSize;
if (VirtualAlloc(pStack->base - PageSize, PageSize, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD) != NULL)
(我知道我应该提交(非PAGE_GUARD)一个页面,但是它用于测试PAGE_GUARD
。)
我写__except
如下:
__except (StackOnSEHExcept(GetExceptionInformation())) {}
/* A */
...
DWORD StackOnSEHExcept(PEXCEPTION_POINTERS exc)
{
if (exc->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
(我也知道我应该提交/保护下一页,但也是为了测试。)
当我触摸堆栈的内存时,会发生STATUS_GUARD_PAGE_VIOLATION
。但之后,/* A */
运行;
在发生异常后,Windows是否取消标记PAGE_GUARD
?为什么这段代码不能很好地运作?
并且,我不知道如何做这个部分:(我也知道我应该提交/保护下一页,但它也用于测试。)。我能怎么做?我想我应该1.获得guarded-page的地址2.提交/保护下一页,但我不知道怎么做1.
编辑:我知道怎么做1.守卫地址在这里:
exc->ExceptionRecord->ExceptionInformation[1]
感谢您的帮助!
答案 0 :(得分:1)
在发生异常后,Windows是否取消标记PAGE_GUARD?
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx
...该地区的页面成为警卫页面。任何访问保护页面的尝试都会导致系统引发STATUS_GUARD_PAGE_VIOLATION异常并关闭保护页面状态。因此,警卫页面可以作为一次性访问警报。
试试这个:
DWORD OnSEH()
{
::OutputDebugString( L"SEH!\n" );
return (DWORD) EXCEPTION_CONTINUE_EXECUTION;
}
static void Test()
{
const DWORD pageSize = 4096;
void* baseAddr = ::VirtualAlloc(NULL, pageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
DWORD oldAttr = 0;
void* protectedAddr = baseAddr;
BOOL ok = ::VirtualProtect( protectedAddr, pageSize, PAGE_READWRITE | PAGE_GUARD, &oldAttr );
if( !ok ) {
int lastError = ::GetLastError(); lastError;
return;
}
::OutputDebugString( L"Reading the guarded page\n" );
__try {
int* testAddr = static_cast<int*>( protectedAddr );
int value = *testAddr; value;
::OutputDebugString( L"Continue execution\n" );
}
__except( OnSEH() ) {}