Blog
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.
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.
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.
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.
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.
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.
Cybersecurity leader resources
Sign up for the Secure Leader and get the latest info on industry trends, resources and best practices for security leaders every other week
Latest from OffSec
OffSec News
Master Incident Response with Hands-On Training in IR-200: Foundational Incident Response
OffSec is excited to announce the immediate availability of a new course: IR-200: Foundational Incident Response.
Oct 29, 2024
4 min read
Enterprise Security
Beyond the Resume: Effective Techniques for Qualifying Top Cybersecurity Talent
Building a cybersecurity team takes more than resumes. Discover effective techniques to identify top talent ready to tackle today’s cyber threats.
Oct 24, 2024
6 min read
Enterprise Security
How to Upskill and Fill Cybersecurity Skill Gaps on Your Team With Custom Learning Paths
Learn how to upskill your team with tailored learning paths, ensuring relevant, actionable training for real-world challenges.
Oct 24, 2024
5 min read