Security Basics mailing list archives

Re: Alternative to EIP


From: Savio <sena.savio () gmail com>
Date: Mon, 19 Nov 2007 17:01:57 -0200

On Nov 19, 2007 2:50 PM, Peter Manis <manis () digital39 com> wrote:
I have an application that I think I have found a flaw in and it is
dumping a lot of information to ECX, but EIP is not being overwritten
so I can't just throw in a jmp ecx.  Is there an alternative location
to place jmp code?  I found something about using SEH, but don't quite
understand how to use it in this situation and the more articles I
find on it the worse it gets.


Yes, SEH is an alternative as long as you can overflow a
local  variable in the scope of _try / _except. (I can't
think of any other way to write EIP, but that doesn't
necessarily mean there isn't one :-D).

I'll try a brief explanation on this topic, but you should
refer to [1] and [2] to better understand this approach.

Upon _try/_except the thread pushes a structure on stack
that looks like this:

struct _EXCEPTION_REGISTRATION {
        VPTR prev;
        VPTR handler;
}

The segment register FS:[0] shall always point to the
last ocurrence of this structure, so upon an exception
the windows kernel looks for the first handler and
asks whether it can handle the exception or not.

In case of a negative reply the windows kernel looks
for the prev->handler, and keep looking until a
handler is found. (A default handler takes care of
the exception if noone else wants to handle it).

The article [1] shows a really simple assembly to
ilustrate how you could explore this to write EIP:

__cdecl _except_handler(
    truct _EXCEPTION_RECORD *,
    void * ,
    struct _CONTEXT *,
    void *)
{ /* ... */ }

int main()
{
    DWORD handler = (DWORD)_except_handler;

    __asm
    {
        push    handler
        push    FS:[0]
        mov     FS:[0],ESP
    }
    *(PDWORD)0 = 0;

    /*...*/
    return 0;
}

As you can see both handler and prev are pushed into
stack. If a variable local to this scope can be
overflowed then it's possible to write the handler's
address. The first block of assembly can be translated
into a simple "_try {", therefore the following code
can be easily exploited:

int main(int argc, char *argv[]) {
        _try {
                char b[8];
                strcpy(b, argv[1]);
        } _except(...) {
                ....
        }
}

[1] http://www.microsoft.com/msj/0197/exception/exception.aspx
[2] http://www.howzatt.demon.co.uk/articles/oct04.html

I'm not sure whether I made myself any clear, not even if I
was assertive with my statements, but I hope this can help you
some ways.

You should write to vulndev@ next time. :-D

my best regards,

-- 
s4v


Current thread: