8-bit video game blocks with pixel art of the Learn One and Learn Enterprise logos

Level up your training with limited-time offers - Discounts for Individuals and Enterprise

Blog

Exploit Development

Nov 18, 2014

Disarming and Bypassing EMET 5.1

Last week Microsoft released EMET 5.1 to address some compatibility issues and strengthen mitigations to make them more resilient to attacks and bypasses. We, of course, were curious to see if our EMET 5.0 disarming technique has been addressed by the latest version of the toolkit.

5 min read

Author: Matteo Memelli

EMET 5.1 released

Last week Microsoft released EMET 5.1 to address some compatibility issues and strengthen mitigations to make them more resilient to attacks and bypasses. We, of course, were curious to see if our EMET 5.0 disarming technique has been addressed by the latest version of the toolkit.

After a quick analysis of the EMET.dll function that verifies which protection needs to be applied whenever a critical function is called, it is clear that now the global variable (EMET+0xF2A30 in EMET 5.1) we used in our previous techniques to disarm EMET 4.X and 5.0 is better protected.

EMET 5.1 Analysis Figure 1

Mitigations Switch Hardening

As previously seen, this global variable stores a pointer to a structure (we called it CONFIG_STRUCT in our previous posts) that among other information, includes a flag acting as a general switch for most of the EMET mitigations at CONFIG_STRUCT+0x558. EMET 5.0 hardened this pointer by encoding it with the Windows API EncodePointer. In EMET 5.1 a pointer to CONFIG_STRUCT is stored in another variable that we called EMETd, as can be seen in the next figure. It is the EMETd address that is now stored in the global variable at EMET+0xF2A30.

EMET 5.1 Analysis Figure 2

EMETd is a 12 byte structure defined as follows:

[cc lang=”c”]
struct EMETd
{
DWORD size;
LPVOID lpCONFIG_STRUCT;
DWORD writable;
}
[/cc]

Both CONFIG_STRUCT and EMETd are initialised in a function at EMET+0x254D5 (refer to previous figure). EMET 5.1 adds an “extra safety layer” by using the result of a CPUID instruction to xor-encode the EMETd pointer, after encoding it with EncodePointer.

EMET 5.1 Analysis Figure 3

CPUID is called passing 0x1 as an argument (EAX=0x1), which means the toolkit uses “Processor Info and Feature Bits” to perform the xor encoding. The instruction returns the CPU’s signature in EAX, feature flags in EDX and ECX and additional feature info in EBX.

Another important change is the fact that the data structure is now located on a read-only memory page, which of course increases the difficulty in switching off EMET mitigations by overwriting the general switch flag.

EMET 5.1 Analysis Figure 4

Adapting the Disarming Approach

Rather than trying to build a ROP chain to recreate the xor-decoding logic, we tried to look for an easier option. More specifically we looked at borrowing a code chunk in an EMET.dll function that would do the work for us. The code starting at basic block EMET+0x67372 is a good candidate, as it decodes the EMETd pointer and returns the CONFIG_STRUCT address in the EDX register.

EMET 5.1 Analysis Figure 5

As shown in the previous figure, to successfully return from the above code, we need to control both EBP and ESI registers. The next step is to take care of the memory page protection.

In our last post we showed how CONFIG_STRUCT can be leveraged to obtain a list of unhooked Windows APIs, and we stressed the fact that this could lead to further points of failure. In our case, we can for example, access ntdll!NtProtectVirtualMemory at CONFIG_STRUCT+0x1b8 (the offset didn’t change from EMET 5.0 to 5.1) and change the CONFIG_STRUCT memory page protections before zeroing out the global mitigations switch at CONFIG_STRUCT+0x558.

Of course once the unhooked ntdll!NtProtectVirtualMemory is available to us, other options are possible – like for example directly patching EMET shims in order to bypass the checks.

EAF and EAF+ were once again bypassed by calling the unhooked version of ntdll!NtSetContextThread located at POINTER(CONFIG_STRUCT+0x518) as we did for EMET 5.0.

Wrapping Up

To summarise the technique, a successful disarming ROP chain will need to perform the following steps:

  • Gather the EMET.dll base address.
  • Get the “decoding helper” code at address EMET+0x67372.
  • Return into EMET+0x67372 and obtain the CONFIG_STRUCT address in the EDX register.
  • Call ntdll!NtProtectVirtualMemory to make the CONFIG_STRUCT memory page writable.
  • Zero out the global protections switch at POINTER(CONFIG_STRUCT+0x558).

We have used this technique and implemented a proof of concept bypass using the Internet Explorer 8 Fixed Col Span ID exploit we’ve used to bypass EMET 4.x and 5.0. The full EMET 5.1 disarming exploit code can be downloaded from the Exploit-DB. The technique was tested against 32-bit systems and results were compared across different operating systems (Windows 7 SP1, Windows 2008 SP1, Windows 8, Windows 8.1). A video of this exploit in action can be seen below:

Disarming EMET 5.1 (Enhanced) from Offensive Security on Vimeo.

Conclusion

We started looking at EMET since version 4.0 and it’s come a long way since. There’s no doubt that Microsoft are stepping up their efforts at making EMET ever more effective. This sort of layered defense goes a long way in disrupting commodity attacks and increasing the level of effort required for successful exploitation.