2

我正在编写一个微小的字节码、解释语言(或框架?vm?)。我知道 WindowsPAGE_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 */运行;

PAGE_GUARD发生异常后Windows不会取消标记吗?为什么这段代码不能很好地工作?


而且,我不知道如何做这部分:(我也知道我应该提交/保护下一页,但这也是为了测试。)。我能怎么做?我想我应该 1. 获取受保护页面的地址 2. 提交/保护下一页,但我不知道该怎么做 1.

编辑:我知道该怎么做 1. 受保护的地址在这里:

exc->ExceptionRecord->ExceptionInformation[1]

感谢你的帮助!

4

1 回答 1

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() ) {}
于 2014-01-24T13:38:32.090 回答