In our previous Disarming Emet 4.x blog post, we demonstrated how to disarm the ROP mitigations introduced in EMET 4.x by abusing a global variable in the .data section located at a static offset. A general overview of the EMET 5 technical preview has been recently published here. However, the release of the final version introduced several changes that mitigated our attack and we were curious to see how difficult it would be to adapt our previous disarming technique to this new version of EMET. In our research we targeted 32-bit systems and compared the results across different operating systems (Windows 7 SP1, Windows 2008 SP1, Windows 8, Windows 8.1, Windows XP SP3 and Windows 2003 SP2). We chose to use the IE8 ColspanID vulnerability once again in order to maintain consistency through our research.
The very first thing that we noticed is that the global variable we exploited to disarm the ROP Protections (ROP-P) routine is not pointing directly to the ROP-P general switch anymore. This variable, which is now at offset 0x000aa84c from the EMET.dll base address, holds an encoded pointer to a structure of 0x560 bytes (See CONFIG_STRUCT in Fig. 1). The ROP-P general switch is now located at CONFIG_STRUCT+0x558 (Fig. 1, Fig. 2).
Encoded pointers are used to provide a layer of protection for the actual pointer values. These pointer values can be decoded by using the appropriate DecodePointer Windows API. Our first idea was to try to use the DecodePointer function to get the required pointer and then to zero out the general ROP-P switch. This API can usually be found in the Import Address Table (IAT) of several modules loaded by target processes. Additionally, since EMET.dll needs DecodePointer, we can extract the offset from the DLL base address directly from its IAT. The first step, as shown in our previous blog post, is to gather the EMET.dll base address. In this particular case, we will also save the EMET base address somewhere in memory in order to get the absolute address of DecodePointer later on. Once we decode the encoded pointer, disarming ROP becomes a very similar exercise as in our previous exploit.
The following ROP gadgets were used to disable the ROP Protections in the IE8 ColspanID exploit:
In our previous blog post, we bypassed EAF by using a known technique presented by the security researcher Piotr Bania. The technique makes use of the Windows syscall NtSetContextThread to clear the hardware breakpoints set by EMET on the Export Address Table of kernel32.dll and ntdll.dll. EMET 5 now protects the KERNELBASE.dll Export Address Table as well, but the only new protection implemented in version 5 against the use of the above technique is that now NtSetContextThread as well as NtContinue (which can also be used in a similar way to bypass EAF) are hooked by the toolkit.
“Unfortunately”, the hook eventually calls into the ROP-P routine, and since all the checks are already disarmed by the previous ROP chain, it is completely ineffective. The result is that no further changes to the shellcode were needed to bypass EMET 5 with all of its mitigations enabled except for EAF+. By resolving and calling NtSetContextThread, we were once again able to bypass EAF and successfully obtain a remote shell.
EAF+, on the other hand, introduces a few extra security checks. First of all, it offers the possibility of blacklisting specific modules that should never be allowed to read protected locations (EAT and MZ/PE header of specific modules). For IE, EAF+ blacklists by default mshtml.dll, Adobe Flash flash*.ocx, jscript*.dll, vbscript.dll and vgx.dll. However, since in our case we are resolving NtSetContextThread by directly calling GetProcAddress, we are implicitly bypassing this mitigation.
When we ran our exploit with EAF+ enabled, IE crashed without any explanations or EMET-related log entries in the Windows Event Viewer. Our first thought was that EMET detected the stack register being out of the allowed boundaries, as this check and the detection of a mismatch of stack and frame pointer registers are the other two mitigations introduced by EAF+.
We were able to verify this by setting a breakpoint at EMET+0x40BA6 (Fig. 3), which is a basic block belonging to the EAF/EAF+ ExceptionHandler (EMET+0x4084A) installed by the toolkit.
Since we have already disarmed EMET ROP mitigations as well as DEP/ASLR at this point, we were able to bypass the stack registers check executing the following instructions just before resolving NtSetContextThread:
The first three instructions simply recover the StackBase pointer value for the executing thread from the Thread Environment Block (TEB). We then add a negative offset to fall within StackBase and StackLimit and set ESP to point to this value.
At this point, we were happy enough as our exploit was working nicely with all the protections enabled. However, as we were reversing the EAF/EAF+ ExceptionHandler, we noticed something interesting. At offset EMET+0x00040E75 (Fig. 4) there is a call to NtSetContextThread, but rather than calling into the hooked Windows Native API, EMET calls a stub that sets up the syscall number into the EAX register and then jumps into NtSetContextThread+0x5 to bypass the EMET shim (Fig. 5).
The interesting part is that the pointer to this stub is an entry in the configuration structure that we used to disarm the ROP Protections. In other words, we can use this stub as an alternative way to bypass EAF+ as we can directly call into POINTER(CONFIG_STRUCT+0x518) without the need to resolve the NtSetContextThread address.
This discovery made us even more curious and we started to snoop around the entire structure. We saw that at specific static offsets from the beginning of the structure, you can find pointers to respective stubs for all the hooked Windows APIs:
This is particularly troublesome as it provides the attacker with access to the most powerful APIs completely unhooked and without the need of resolving their addresses once EMET CONFIG_STRUCT is gathered. However, since Deep Hooks are enabled by default, if the attacker plans to use one of the above APIs without disarming EMET in first place, they would need to call the deepest API in the chain.
As usual, the full exploit can be found at The Exploit Database. The exploit uses the stub at POINTER(CONFIG_STRUCT+0x518) to bypass EAF+ as well as the ROP chain presented in this blog post.
The Attack Surface Reduction (ASR) feature in EMET 5.0 helps reduce the exposure of applications by preventing the loading of specific modules or plugins within the target application. This protection can really be effective in cases where an attacker forces the target application to load a specific DLL to bypass ASLR (Java msvcr71.dll is a very typical case).
Protection provided by ASR does not affect our exploit in any way because we are using a memory leak to bypass ASLR in the IE ColspanID exploit. We are also not loading any extra modules to bypass DEP. Nevertheless, we conducted some research to understand where this mitigation is located within EMET.dll. Once again, we noticed that the actual checks are done within the very same ROP-P routine, thereby making ASR entirely ineffective once the ROP-P general switch has been zeroed out. However, if an attacker is planning to force the target application to load a blacklisted module to bypass ASLR, he wouldn’t be able to disarm the EMET ASR protection using our technique before loading the forbidden DLL.
Our testing on older operating systems shows that the offset to the CONFIG_STRUCT global variable changes to 0x000b0b4c due to the fact that a different EMET.dll is in use.
Nevertheless, offsets within the structure are consistent in all pre- and post-Vista Windows versions, both for the ROP-P general switch and for the unhooked APIs stubs. The only real differences are present when certain API functions are simply not available in the OS, such as in the case of KERNELBASE.DLL in Windows versions prior to Windows 7.
As we managed to successfully demonstrate, the difficulty in disarming EMET 5 mitigations has not increased substantially since version 4.x. More than anything, only our ROP chain has increased in size, while achieving the same effect of bypassing the protections offered by EMET. Here’s a video of our PoC IE exploit bypassing EMET v5.0: