Export Address Table Filtering (EMET v2)

I'll tell you the truth: Export Address Table Filtering, the feature of the upcoming release of EMET, "designed to break nearly all shell code in use today", intrigued me a bit.

Since I wasn't able to find docs about the actual implementation, I started to think about how that could be done and I wrote a simple POC that uses VirtualProtect to flag the relevant pages of the .data section of ntdll and kernel32 with PAGE_GUARD to intercept read operations over the PEB.Ldr. A Vectored Exception Handler is then used to handle the exception and to check if the faulting address is within the code section of a module(MEMORY_BASIC_INFORMATION.Type == MEM_IMAGE). Here is the pseudo-code:

BOOL WINAPI DllMain(...)
{
    [...]
    AddVectoredExceptionHandler(1, VectoredHandler);
    VirtualProtect(PLDR,
        PAGE_SIZE,
        PAGE_READWRITE|PAGE_GUARD,
        &old_protect);
    [...]
}
LONG CALLBACK VectoredHandler(
    __in PEXCEPTION_POINTERS ExceptionInfo)
{
    [...]
    if(ExceptionInfo->ExceptionRecord->ExceptionCode ==
        STATUS_GUARD_PAGE_VIOLATION)
    {
        VirtualQueryEx(GetCurrentProcess()      ,
            (LPVOID)ExceptionInfo->ExceptionRecord->ExceptionAddress,
            &lpMemInfo,
            sizeof(MEMORY_BASIC_INFORMATION)))

        if(lpMemInfo.Type != MEM_IMAGE)
            ShellcodeDetected();
    [...]

Yesterday I found this .doc. It explains pretty much everything: they use hardware breakpoints to intercept read operations and a Vectored Exception Handler to check if the faulting address belongs to a module.... pretty much the same thing, isn't it?

Then I started to think about how EAT filtering could be bypassed, obviously there are many ways to find the address of a function without touching the EAT, but I was looking for a quick way to just fix existing shellcodes and make them working under EMET. Since EMET is going to use hardware breakpoints it will be probably faster than the PAGE_GUARD approach because while you can put a breakpoint on a single DWORD using debug registers, the granularity of VirtualProtect is PAGE_SIZE.

But hardware registers can be zeroed out, disabling the protection, by taking advantage of the Structured Exception Handling and without even using a single API. And so, I thought, you can easily add to a metasploit shellcode something like this:

START:
    call +0                  // poor's man get_pc()
    mov eax, [esp]
    add eax, HANDLER_OFFSET
    push eax               // install SEH handler
    push fs:[0]
    mov fs:[0], esp
    xor eax, eax
    mov byte [eax], 1   // oops
    [...]

HANDLER:
    xor eax, eax
    mov ebx, [esp+0xc]  // context
    add [ebx+0xb8], 3   // eip += len("mov byte [eax], 1")
    mov [ecx+0x4], EAX  // clean debug registers
    mov [ecx+0x8], EAX
    mov [ecx+0xc], EAX
    mov [ecx+0x10], EAX
    mov [ecx+0x14], EAX
    mov [ecx+0x18], EAX
    ret

right? Well, not quite really! Because this is not gonna work with SAFESEH enabled! :)

Btw, is there a way to quickly disable PAGE_GUARD using only position independent code and without touching EAT?