IE crash analysis
Today we will analyse a crash of Internet Explorer.
Reven scenario generation
According to Exodus Intelligence, a vulnerability was silently fixed in MS13-055 patch along with other things. They showed on their blog how to exploit it.
We generated our REVEN scenario where we give an html file to Internet Explorer that triggers the vulnerable crash.
We let REVEN execute the scenario, and since IE stops by raising an exception we tell reven to stop analysing when it reaches the symbol KiUserExceptionDispatcher. After 30 minutes (more or less depending on the pc it ran on) we have our trace. It is about 10 069 180 sequences long (51 273 145 instructions, 52 028 972 with IRQ and page fault instructions).
At the end of the scenario we see the exception being raised after an invalid fault, when trying to dereference 0x10. This invalid address is calculated from a base pointer (likely that of a structure) which is null.
Now we will use REVEN’s built-in slicer script (it leverages its
capabilities) to find out where this null pointer comes from. We
$ ./slicer.p Enter the initial sequence : 10069179 Enter the initial instruction : 1 Enter the ending sequence : 9819179 Enter the initialy tainted register [eax]: ecx
We ask it to operate up to 250 000 sequences back (around 1 000 000
instructions). Just to give you an idea it will take :strike:
around 4 minutes when we wrote this article less than 2 seconds now.
The time depends on how many operations are affected, on the kind of
You can see that the furthest point reached by the slicer is sequence #9819823, with xor ebx, ebx.
Browsing around this sequence in the gui, we see that the sequence right
before is the destructor of the
Then, as shown in the slicer’s results, this zeroed ebx will be stored in the memory location 0x4ef8dc on sequence #9821517.
Allocations / Deallocations
We found our invalid dereferencing occurred on a piece of memory that depends on something that has been modified during a destruction. This is a hint that something might be wrong with allocations and deallocations, so let’s explore that path.
REVEN is able to track all the allocations/deallocations, for now through the use of a script. Note: In the very near future we will integrate this features into the GUI and will make it also track the dereferencings so it knows about use after free, double free, etc. by default.
It tells us that the memory location 0x4ef8d0 was allocated at sequence #7051584 (the allocation had a size of 0xc8, so from 0x4ef8d0 to 0x4ef998). If we look 3 sequences later in the execution, at #7051587, we can see that we are in the constructor of the CSelectionManager() object, so we just constructed a CSelectionManager object.
This CSelectionManager object is then freed at sequence #9821532 and never reallocated after that.
But we know a dereferencing occurred at the address 0x4ef8dc, while executing the sequence #10069177. So here we have a case of use after free.
Timeline of the events
From the results of the slicer and of the allocation script we deduce this timeline:
#7051584 => allocation of 0x4ef8d0 to 0x4ef998 #9819823 => xor ebx, ebx #9821517 => mov DWORD PTR [esi+0xc], ebx // mov [0x4ef8dc], 0 #9821532 => free of 0x4ef8d0 #10069177 => mov eax, DWORD PTR [esi+0xc] // mov eax, [0x4ef8dc] #10069178 => mov esi, eax #10069179 => lea ecx, [esi+0x10] #10069179 => mov xxx, DWORD PTR[ecx] // deref of 0x10
Going to the first use after free
Now with the
memory range history
we will see all the accesses made to the CSelectionManager object by
asking for all the operations that happened on the memory range
You can see that the first use after free in the
object occurs at #10068868, which is before the one that raises the
exception at #10069177. This is pretty usual in use after free, race
condition, etc.: the bug appears at one location but the software can
crash much later. Here we see directly the first invalid behaviour of
If we explore this first invalid access, we can see that edi has the
0x4ef8d0 value (in c++ it would be the this pointer), indeed we are in
CSelectionManager::FireOnBeforeEditFocus(). The object tries
to access to its data, but since the object was freed they can be either
valid or not, and here the object apparently still has valid data.
At the previous sequence #10068867 we’re returning from the function EdUtil::FireOnBeforeEditFocus().
REVEN’s “percent” feature can take us to the call corresponding to the
ret instruction of the
We end up on the sequence #7965463, and the this pointer still points to the same object. We just jumped more than 2 000 000 sequences backward.
So our object called the method
took a path that lead to its destruction, and when returning from
EdUtil::FireOnBeforeEditFocus() it was a freed object with invalid data.
Why did the CSelectionManager object get freed ?
Back to sequence #9821531 where the CSelectionManager object is freed, we can see that 8 sequences before the method CSelectionManager::Release() was called. With both the symbol being CSelectionManager::Release() and the instruction dec DWORD PTR[ecx+0x8] inside the sequence, it looks like the reference counter of the object is stored at 0x4ef8d4.
If we double click on the operand
dword ptr[ecx+0x8] of the instruction
dec DWORD PTR[ecx+0x8], a link will pop allowing us to go directly on
the memory location pointed by this operand 0x23:0x4ef8d8. Then if we
ask for the history of this memory location we can see every inc and dec
on the reference counter.
Now between #7965463 (where
is called) and #10068867 (where
CSelectionManager::FireOnBeforeEditFocus() returns) there are 7 writes
to this location, and the value of the ref count is 1 at the call.
The two firsts are
CTask::AddRef(), they increment the ref count; the
3rd and 4th comes from
decrement the ref count.
Example of a
AddRef() with the memory history :
So after those we’re left with a ref count equals to 1.
The last and interesting one is triggered by the destructor of the
CHTMLEditor() object at #9821518.
So the destruction of the
CHTMLEditor object caused a decrement in the
reference counter of the
CSelectionManager object which leads to the
destruction of the
We could go further in the analysis and try to figure out why the
CHTMLEditor object got freed, but the goal of this article is to show
you some of REVEN’s features, so we’ll stop here.
We just saw an example of crash analysis for Internet Explorer. We started with an invalid exception code and went to the invalid dereferencing using the many features of REVEN such as the slicer & data tainting that led us back to the destructor of the CHTMLEditor object, the memory history which showed us the uses after free of the CSelectionManager object that didn’t cause crashes and the accesses to its reference counter, the visual studio name demangling which helped us understand where we are in the code, the percent feature which helped us travel back and forth fast in the trace, etc.
I hope you enjoyed this article. If you have any technical question you are welcome to post a comment.