Sunday, January 4, 2015

Analyzing 2014-0282 Internet Explorer CInput Use-after-Free Vulnerability..!!


Sometime during the mid of the last year, Proof-of-Concept code for the Use-after-Free vulnerability was published on the exploit-db effecting Internet Explore 8, 9 and 10. I was kind of interested in picking up this exploit code and debug to see the inner workings of the exploit and checkout how it looks like in the debugger. Another motive of debugging this exploit was to spend some cycles to do the precision heap spray technique to control the placement of the shellcode on the heap address of our choosing. 

Let's start by taking a quick look at the published exploit code on exploit-db and walk through it to gain some basic understanding of what should we expect, when we execute this code inside the debugger.













In the above PoC code,  a form with the id "testfm" is created following which 2  "TextArea" and 2 "Input" elements and are created. If we notice the changer( ) function in the PoC code, it frees up the contents of the form where the "TextArea" objects are also freed up.  In the last portion of the script, element "child2" is being set to true and changer ( ) function is set to be called on the property change event of child2 element.

If you look at the code closely, in the last part, reset( ) function is called  and iterated over the form element, which actually calls the CFormElement::DoReset ( ) function. This function will basically iterate over the each of the 4 elements of the form and resets its properties, In the iteration where the "child2" element properties is reset, changer( ) function is called and the form properties is reset which will also free the "child3" element properties. Eventually, in the last iteration, it will try to reset the properties of "child3" element and since the object is already freed, Reset( ) function call on that element will crash.

Let's try to execute this code in the debugger and see if we encounter the crash in IE 8.












As expected, IE crashes in the debugger, if we checkout the state of the IE in the debugger we can apparently see that Instruction pointer ( EIP )  is pointing to the invalid memory and consequently it is crashing at that point since it is not able to disassemble the code.













Next step is to check the call stack and see if we can dig out some more details on the crash.











Highlighted portion in the above call stack apparently shows that IE crashed while executing CFormElement::DoReset( ) function. If we disassemble at the Return Address 0x665a1742, it would look following.









Seemingly, we can see that crash happened while calling the virtual method. ESI was pointing to the object memory in the heap. In the first "mov" instruction the Virtual Function table pointer was moved to EAX after which IE was attempting to call the virtual method at the offset 1CC into the virtual function table during which it crashed since code cannot be disassembled at that memory address. This is the classic case of Use-After-Free vulnerability where the object was freed previously and ESI register was pointing to the freed memory which was 0x60 ( 96 ) bytes in size . We can confirm it from the below debugger screenshot.









To further validate our observation,  we can enable the page heap and user stack trace and see if it crashes again at the "call" instruction. Page heap will enable us to track all the heap allocations, chunk sizes and also track the freed up memory. Let's enable the page heap using gflags.exe and re-run the exploit to check if it crashes again at the same point.


















Below is what I hit after enabling the page heap.












This is exactly what we expected. Apparently, IE8 crashed again at the "call" instruction while attempting to execute the virtual function method. Ggflags.exe keeps track of all the freed heap chunks and fills it up by 0xf0f0f0f0 which is used in the following call instruction to access the offset 1CC into the VFtable and then crashes. Disassembly at the crash location is following:







Following shows where the ESI and VFTable pointer was pointing to when the call was executed.




















Page heap will also allow us to visualize when the heap memory was freed and what was the size of the freed heap chunk. Take a look at this below screenshot especially the highlighted portion. This validates our conclusion.













Another way to figure out the size of the freed object is to disassemble the mshtml.dll. There would be a constructor allocating the memory using HeapAlloc( ) and we can check the size of the allocated chunk as shown below.










Next, If we can craft the exploit code in such a way that we make IE to reallocate the same freed memory with our controlled data, then essentially it would mean that we will be able to control the "Call" destination which consequently will lead to remote code execution. With our previous analysis, we already have the information on what should be the size of the heap memory that needs to be allocated. We can force Internet Explorer to re-allocate the same memory if we create the fake object of the same size ( 0x60 bytes ).

Before diving further, let's first briefly understand the concept of Low Fragmentation Heap ( LFH ) used for servicing the memory allocation requests in windows and Virtual Function method calls.

Low Fragmentation Heap

In Windows, when an application would request for certain size of the memory chunk, heap allocator will dynamically allocate the memory from the process heap and hand it over to the application for use. Later if the application no longer requires that chunk, it can free the allocated memory, after which the freed memory is tracked by the front-end cache manager. Since the application can request and free the memory as and when required, consequently the heap can be fragmented which is not the ideal condition. In order to minimize the heap fragmentation, cache manager will track the list of freed chunks and will allocate from the that list if possible.

Low Fragmentation Heap in Windows is basically a heap allocation policy where, given the certain amount of memory allocation request of size X, it will try to allocate the memory of that same size contiguously. Now, there are multiple things coming out here in favour of the attacker.

  • If the allocator is requested memory of size X, which it already finds in its free list of chunks, it would try to re-allocate the same memory chunk to the requesting application. This implies that if application frees certain chunk of memory and requests the same size of memory again, there is a high possibility that application will get the same memory chunk freed previously. 
  • Additionally, this sort of allocation behavior will also make the heap allocations predictable. This essentially means that, if certain threshold number of allocations of size X is given to the heap allocator, all of these blocks will be allocated together and we are almost certain that attacker can place his controlled data to the heap address that he likes. For eg. 0x0c0c0c0c.
Virtual Function method calls

In Object Oriented world, parent or a base class can supply the methods which can be overridden by the child or derived class in its definition. Until run time, compiler would not know if the method of the base class or the derived class is required to be called. To make this much simpler, objects would typically have first 4 bytes as the pointer to the Virtual Function table which is a pointer to the array of function pointers. Visualize the object's memory and virtual functions as below. 










In our analysis so far, We've seen that we are getting the crash while calling the virtual function at address EAX+1CC, where EAX holds the pointer to the VFtable. Our idea is, if we can control the call to this destination by:
  • Creating the enough fake object allocations of the same size, thereby forcing the IE to re-allocate the same previously freed memory. 
  • Create the fake virtual function table by allocating the large amount of heap memory with another object, thereby placing our controlled data [which will usually be the ROP gadgets], at the predictable address [ for Eg. 0x0c0c0c0c. I am just using this address as an example. We can use any other heap address like 0x0a0a0a0a, 0x0b0b0b0b etc. ].
If we can achieve both of these above mentioned conditions, we can do the arbitrary code execution. Now let's slightly modify the exploit code to see if we can achieve the first condition. We'll modify the changer( ) function in the exploit to perform good amount of fake object allocations and see that IE re-allocates the previously freed memory thereby corrupting the object's VPTR. In the below modified exploit code, we would attempt to overwrite the object's VPTR by 0x41414141, subsequently, the crash will happen while calling virtual method at address 0x41414141 + 0x1cc, which equals 0x4141430D.
















Apparently, we created 0x1000 "img" elements and set the image's title to the 0x60 bytes ( including  4 bytes of length and 2 bytes of null character. We need to use the unescape( ) here, else the string will be Unicode in the memory. If we re-launch IE with this exploit, we get the crash while calling the code at below address as expected.















This validates our claim and we've made IE to reallocate the previously freed memory and EAX holds the pointer to our fake virtual function table, which so far doesn't exist. Also, we are now certain that, we can corrupt the object VPTR and set it to something useful which we can control.

Precision Heap Spraying

Precision Heap Spray relates to our second condition that we want to achieve. Essentially,  we need to fill up good amount of heap memory with attacker controlled data, which includes the ROP gadgets + Shellcode that needs to be executed. ROP gadgets will mark the area of the memory where the shellcode resides, as executable, bypassing DEP, and finally will execute it. One of the primary thing that needs to be done here is to allocate the heap with precision, such that our ROP chain will start exactly from the address 0x0C0C0C0C [given that we wish to control the data placed at that address].

Given above conditions, we will have to overwrite the object's VPTR with the 0x0C0C0A40. Our exploit plan will finally look like the below diagram.

















Next, with the below basic heap spray script, we'll examine the allocations in Windbg and subsequently optimze the script to place our controlled data at the target address.

Looking this under Windbg, our allocations will come out to be like below. Apparently, the heap spray that we executed accounted for 98.8% of the memory which is a good indicator. Also check the size ( 0xfffe0 ) which confirms that it is the result of what we executed.

It is important to check in which heap chunk the target address is located, and turns out that it is in the chunk 0x0C090018 [ address might differ on other systems ]






Also, note below that data we want to place at the target address [ deaddead ] is not there at the moment.








Now, here is our mathematics to achieve the precise heap spray such that, our controlled data "deaddead" will be certainly placed at our target address 0x0C0C0C0C.

  • Subtracting the heap entry address from the target address gives us the total distance from the heap entry to our controlled data. 0x0C0C0C0C - 0C090018 = 30BF4 . We need to determine the offset into this heap chunk, such that when we add 0x1000 to the heap entry and subtract the resulting address from 0x0C0C0C0C, then value is less than 0x1000 [ i.e 4096 ]. With the little bit of experimentation, that heap address comes out to be 0x0C0C0018.
  • Subtracting 0x0C0C0018 from our target address 0x0C0C0C0C = BF4.  If we divide this by 2 and then again subtract 6 from the resulting value, i.e ( BF4 / 2 ) - 6 , for BSTR header of 4 bytes and null characters of 2 bytes we have value 5F4 
  • Now if we insert the padding of this size , we can align our shellcode exactly to the target address.

We'll have to modify the above basic heap spray script such that the data we'd like to place "deaddead" is at the target address. I will leave this as a exercise to the reader. If you do this correctly, it should look like below:








This validates our claim that with the careful crafting of the exploit, attacker can place the shellcode at the address of his choosing and eventually control the program execution. Finally, go ahead and embed the heap spray function into our main exploit POC code and we should see the Instruction Pointer register ( EIP ) overwritten with the dword "0x64616564".













Attacker can craft the exploit to place the Stack Pivot ROP gadget here which will pivot the ESP to the heap and start executing the ROP chain, subsequently bypassing Data Exexution Prevention and executing arbitrary code.

GAME OVER. !!.


No comments:

Post a Comment