Thursday, July 7, 2011

Post-mortem Analysis of a Use-After-Free Vulnerability (CVE-2011-1260)

Recently, I've been looking into the exploitation of use-after-free vulnerabilities. This class of bug is very application specific, but armed with just the right amount of knowledge these vulnerabilities can be exploited to bypass most modern OS exploit mitigations. After reading Nephi Johnson's (@d0c_s4vage) excellent article[1] on exploiting an IE use-after-free vulnerability, I decided to ride his coattails and show the steps I used to analyze his proof-of-concept crash code.

As shown in his blog post, here is Nephi's test case that crashes IE:
Internet Explorer crashes at mshtml!CElement::Doc+0x2

76c.640): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=004aedc0 ecx=004e00e9 edx=00000000 esi=0209e138 edi=00000000
eip=6d55c402 esp=0209e10c ebp=0209e124 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
mshtml!CElement::Doc+0x2:
6d55c402 8b5070          mov     edx,dword ptr [eax+70h] ds:0023:00000070=????????

Here is the order of execution leading to the crash:

mshtml!CTreeNode::ComputeFormats+0x42
6d58595a 8b0b            mov     ecx,dword ptr [ebx]
6d58595c e89f6afdff      call    mshtml!CElement::Doc (6d55c400)
mshtml!CElement::Doc:
6d55c400 8b01            mov     eax,dword ptr [ecx]
6d55c402 8b5070          mov     edx,dword ptr [eax+70h] ds:0023:00000070=????????
6d55c405 ffd2            call    edx

This is a classic C++ use-after-free vulnerability. IE is trying to call a function within a previously freed object's virtual function table. In the disassembly above, a pointer to some object [EBX] has a pointer to its virtual function table [ECX] that subsequently calls a function at offset 0x70 in its vftable [EAX+0x70].

What we need to find out is what type of object was freed and how many bytes get allocated for that object. That way, we can craft fake objects of that size (using javascript) whose vftable at offset 0x70 point to our shellcode.

Since mshtml!CTreeNode::ComputeFormats+0x42 points to the object in question (in EBX), I set a breakpoint in Windbg on that instruction and got the following:
As can be seen above, EBX points to a freed CObjectElement object. How can we know for sure that the object was freed and that it points to a CObjectElement object? Enabling the page heap and user stack traces of every call to malloc and free will do the trick. This technique also allows us to observe the size allocated to CObjectElement.
The size that gets allocated to the CObjectElement object is 0xE0. It is also handy to see the call stacks of what allocated and freed the object. The size allocated for the object was determined via dynamic analysis. There's more than one way to skin a cat though. The same information can be gleaned via static analysis. A brief glance of the mshtml!CObjectElement::CreateElement function (which was called in the call stack above) in IDA shows that 0xE0 bytes is allocated for CObjectElement.


According to the disassembly (for CObjectElement::CObjectElement), the actual size of the class is 0xDC. However, 0xE0 is allocated on the heap because the compiler rounded up the size to the nearest DWORD boundary.


Lastly, although it is not always necessary for exploitation, let's determine the actual function that should have been called at the time of the crash. This can be accomplished several ways in Windbg.
The function that should have been called was mshtml!CElement::SecurityContext.

So to refresh our memories, what was needed to begin exploiting a use-after-free bug?

1) The type of object referenced after being freed
2) The size allocated to the object

There is no magic command that will give you this information and as usual, there is always more than one way to obtain this information. The key is to understand what lead to the crash. The next step is to utilize javascript to declare string variables that will allocate fake objects in the heap that point to attacker controlled shellcode (via heap spraying). This can be accomplished reliably without needing to point to a typical address like 0x0C0C0C0C which serves as both an address in the heap and a NOP slide. More on that in a future blog post...

References:

1. N. Johnson, "Insecticides don't kill bugs, Patch Tuesdays do,"
June 16, 2011, http://d0cs4vage.blogspot.com/2011/06/insecticides-dont-kill-bugs-patch.html

13 comments:

  1. Actually, 0xDC is already "at the dword boundary". But the object size _is_ 0xE0. The last mov to [esi+0DCh] occupies offsets 0xDC to (not including) 0xE0.

    ReplyDelete
  2. Noob oversight. Thanks for pointing that out.

    ReplyDelete
  3. Awesome stuff :), I'm in the same boat, I have been researching this exploit and trying to get a good understanding myself.

    ReplyDelete
  4. BP mshtml!CTreeNode::ComputeFormats+0x42 10 ".printf \"Object Pointer:\\t%08x\\nVFTable Pointer:\\t%08x\\nVFTable:\\t\\t%08x\\nObject Type:\\n\", ebx, poi(ebx), poi(poi(ebx)); ln poi(poi(ebx)); g"

    what is 10 after "BP mshtml!CTreeNode::ComputeFormats+0x42"

    ReplyDelete
  5. It skips over the first 10 breakpoints. I did it just to eliminate extraneous information about irrelevant objects.

    ReplyDelete
  6. You Say: "As can be seen above, EBX points to a freed CObjectElement object. How can we know for sure that the object was freed and that it points to a CObjectElement object? Enabling the page heap and user stack traces of every call to malloc and free will do the trick. This technique also allows us to observe the size allocated to CObjectElement".

    Where you you see that CObjectElement points to a freed object? The only free data i see is the VFTable of mshtml!CPhraseElement method:

    mshtml!CPhraseElement::`vftable' =
    Object Pointer: 00608808
    VFTable Pointer: 00610023
    VFTable: 00000000

    Thanks for your replay

    ReplyDelete
    Replies
    1. Great question. I could have been a lot more clear in my explanation.

      You'll notice that the last object address before the crash is 00608808 which was used by some other object (mshtml!CPhraseElement) in this case. Notice that the last reference to address 00608808 referred to the CObjectElement instance.

      The example that follows simply shows definitively that the address in EBX was actually freed before crashing. Enabling the page heap is what triggered the access violation.

      I hope that answers your question.

      ~Matt

      Delete
  7. Could you please let us know the exact version number of IE ?

    ReplyDelete
    Replies
    1. That I couldn't tell you. It's whatever version of IE was installed prior to KB2530548. The vulnerable version of mshtlml.dll is also going to vary depending upon your OS configuration.

      Delete
  8. //# At time of crash, [EBX] points to freed memory:

    how do we say that the [EBX] points to freed memory?

    Thanks
    Nolen

    ReplyDelete
    Replies
    1. Hi Nolen,

      Are you asking how I knew that [ebx] pointed to freed memory? If so, refer to the output of the Windbg instruction that follows: !heap -p -a poi(ebx)

      Delete
  9. Forgive me for gravedigging this, but if EBX (or any other general register) is an object pointer, is it always the case that the contents of EBX compose its VFTable pointer and that the contents of the VFTable pointer compose the VFTable itself? Otherwise, how did you determine the following for your breakpoint:

    Object pointer : EBX
    VFTable pointer : poi(EBX)
    VFTable : poi(poi(EBX))

    Thank you!

    ReplyDelete