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(...)
LONG CALLBACK VectoredHandler(
__in PEXCEPTION_POINTERS ExceptionInfo)
if(lpMemInfo.Type != MEM_IMAGE)
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:
call +0 // poor's man get_pc()
mov eax, [esp]
add eax, HANDLER_OFFSET
push eax // install SEH handler
mov fs:, esp
xor eax, eax
mov byte [eax], 1 // oops
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
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?