Bugtraq mailing list archives

Re: Code Red Revisited and Stack-Based Exception Handler Frame Bug


From: "Roland Postle" <mail () blazde co uk>
Date: Thu, 13 Feb 2003 23:08:00 +0000

On Tue, 11 Feb 2003 16:11:15 -0500, Peter Huang wrote:

As I followed the trail described by Mr. Szor and Mr. Chien’s article
(http://www.peterszor.com/blended.pdf), it became clear to me the following
was the transfer point to the abused exception handler like Code Red. For a
normal C/C++ function, it was OK to assume that sub-functions will not
depend on the values of EBX, EDI, and ESI and will not abuse them. However,
that assumption was proved wrong with the Code Red exploitation and should
be corrected. One simple way is to save EBX and xor EBX out before it
transfers the rein. A more panicky way is to save and xor out all the unused
registers like EBX, EDI, and ESI for this function before it calls ECX

Apparently this is exactly what happens now, except Microsoft chose to
nuke eax as well (see below). But it's a bit misleading to say this
made the Code Red exploitation possible. There are a numerous other
ways to find your shellcode in memory without relying on having a
register pointing directly at it, albeit some are more reliable than
others. In this case I believe the shellcode is some way down the stack
(?) in which case pointing the call ecx at some code like:

retn 10h

and arranging for the retn to pop a pointer to a 

mov eax, esp
call eax

would probably do the trick.

You could run around all day making sure registers didn't have values
that were useful to attackers, but all you'd end up doing is
introducing masses of overhead and making exploitation a bit more
challenging (and more satisfying). I hope you're not really suggesting
that *every* function call should begin with fresh registers? It's just
about justified in this case because exception handlers are one of the
more common things that get overwritten.

- Blazde

From XP SP1 ntdll.dll:

.text:77F79B4D _RtlpExecuteHandlerForUnwind@20 proc near ; CODE XREF:
RtlUnwind(x,x,x,x)+BDp
.text:77F79B4D 
.text:77F79B4D arg_0           = dword ptr  4
.text:77F79B4D arg_4           = dword ptr  8
.text:77F79B4D arg_8           = dword ptr  0Ch
.text:77F79B4D arg_C           = dword ptr  10h
.text:77F79B4D arg_10          = dword ptr  14h
.text:77F79B4D 
.text:77F79B4D                 mov     edx, offset loc_77F79BDF
.text:77F79B52                 lea     ecx, [ecx]
.text:77F79B54 
.text:77F79B54 ExecuteHandler@20:                      ; CODE XREF:
RtlpExecuteHandlerForException(x,x,x,x,x)+5j
.text:77F79B54                 push    ebx
.text:77F79B55                 push    esi
.text:77F79B56                 push    edi
.text:77F79B57                 xor     eax, eax
.text:77F79B59                 xor     ebx, ebx
.text:77F79B5B                 xor     esi, esi
.text:77F79B5D                 xor     edi, edi
.text:77F79B5F                 push    [esp+0Ch+arg_10]
.text:77F79B63                 push    [esp+10h+arg_C]
.text:77F79B67                 push    [esp+14h+arg_8]
.text:77F79B6B                 push    [esp+18h+arg_4]
.text:77F79B6F                 push    [esp+1Ch+arg_0]
.text:77F79B73                 call    ExecuteHandler2@20
.text:77F79B78                 pop     edi
.text:77F79B79                 pop     esi
.text:77F79B7A                 pop     ebx
.text:77F79B7B                 retn    14h
.text:77F79B7B _RtlpExecuteHandlerForUnwind@20 endp



Current thread: