Security Research
Showing results for 
Search instead for 
Do you mean 

Double-Dip: Using the latest IE 0-day to get RCE and an ASLR Bypass

Abdul_Hariri ‎05-06-2014 06:47 AM - edited ‎05-06-2014 08:42 AM



The last couple of days there has been a big buzz regarding an IE 0-day being exploited in the wild.  The exploit was caught by FireEye. The FireEye blog stated that a Flash bug has been used to bypass ASLR. This caught our attention here in the ZDI, and made us wonder if we can actually bypass ASLR and DEP using the same IE bug without the Flash one.


Initial Crash


The browser would crash with pageheap on in the following function:



The stack trace at crash time:



The free happened here:






In order to fill up the freed memory, we would need to get the length of the object:



Filling up the freed object is relatively easy from there and the crash would look like this:





According to the online reports, the exploit found in the wild used Flash to bypass ASLR.

Let’s take a look at the ASM around the crash spot to understand the options that we have to gain RCE.  The following was performed on IE11 on 32-bit Windows 8.1.


If we take one step backwards to check the functions and instructions around CMarkup::IsConnectedToPrimaryMarkup, we notice that right before returning there’s a CALL instruction that might be controllable:



It seems legit, and definitely in our control:



So far, we know we can gain RCE from the bug.  Now the question is whether or not we are able to leak out of this bug.


ASLR Bypass


The plan is to find an instruction that would allow for a controlled:

  1. write-4
  2. write-0
  3. ADD [controlled],X
  4. INC [controlled]
  5. DEC [controlled]
  6. AND [controlled],XXXXXXX
  7. Etc..


The above options would allow us to do one of the following:

  1. Change the length of some BSTR in memory to leak memory
  2. Tricking IE into thinking that some number is an actual object , thus triggering a type confusion


There are a couple of functions that are called after CMarkup::IsConnectedToPrimaryMarkup.  I won’t cover all the function calls, but I will highlight the ones of interest.




Inside this function there’s a call to CElement::ClearRunCaches() that we can reach.

And inside CElement::ClearRunCaches() there’s a call to CMarkup::ClearRunCaches().


CMarkup::ClearRunCaches() contains interesting instructions that we can reach and control. Some of them allow controlled null writes, and others would allow zero’ing out the least significant bit (LSB) of a controlled address like this AND instruction:



This definitely helps in creating type confusion.


Another function of interest, and which I’ve personally used to trigger type confusion, is CView::AddInvalidationTask().




If we check the assembly inside of this function closely we’ll notice that we have something quite interesting:



There’s an INC instruction that we potentially control.

But do we really control it?



Yep, we do.


This gives us two options, either modify some BSTR length or trigger a type confusion by INC’ing a controlled location and setting the LSB to 0.


The strategy that I took to trigger a type confusion is the following:


  1. Place a value in memory that IE thinks is a Number
  2. INC that value, so then, LSB is 0, and IE then thinks it’s an object
  3. Modify the location that the address points to and craft your fake object
  4. Use that object to read memory and leak a memory address


If everything went as planned, we’ll be able to leak base addresses:




Exploitation problems


There are some problems that I ran through:

  1. Attempting to re-trigger the bug more than once
  2. Crashing on a CLock:CLock
  3. Bypassing the CALL right before the RET


In order to re-trigger the bug more than once (which is required to trigger the type confusion), I had to re-build the document again. This can be done easily by re-writing the exact HTML elements required to trigger the bug using a simple document.write().


The second problem was crashing on a CLock:CLock making it difficult for us to continue execution.


If we step back a bit inside MSHTML!CView::AddInvalidationTask, we will notice that there’s a call to CView::PostCloseView.


Inside CView::PostCloseView, there’s a test that we should take and exit pre-maturely:



If we don’t take that jump, and exit cleanly, we CLock::CLock will end up being called right after being triggered, thus it won’t allow multiple triggers.


The final problem is bypassing the CALL instruction that was used by the attackers to get RCE.


This is an easy problem to solve:



If ECX is 0 at the test, then we can bypass that virtual call, and thus return cleanly.

This is all in our control. So, problem solved.


This is the path that I took to exploit the bug (Node in RED should be avoided):




It’s pretty expensive to use two bugs when you can actually use one. The Flash bug has been used more than once. Using known bugs increases the chances of detection and thus an attacker would not have been caught as quickly without it.  Investing time and focus into exploit primitives around use-after-free vulnerabilities will be beneficial and will minimize the number of bugs necessary for code execution.


Abdul Aziz Hariri

HP ZDI, Senior Security Researcher

0 Kudos
About the Author


on ‎05-06-2014 08:38 AM

Creative way! Could you email me a poc?

June 6 - 8, 2017
Las Vegas, Nevada
Discover 2017 Las Vegas
Join us for HPE Discover 2017 in Las Vegas. The event will be held at the Venetian | Palazzo from June 6-8, 2017.
Read more
Each Month in 2017
Software Expert Days - 2017
Join us online to talk directly with our Software experts during online Expert Days. Find information here about past, current, and upcoming Expert Da...
Read more
View all