Vulnerability Development mailing list archives

Re: win32 call dword ptr [eax] help needed


From: "wirepair" <wirepair () roguemail net>
Date: Wed, 10 Sep 2003 07:47:18 -0700

Thank you very very much for taking the time to respond. Unfortunately I have Zero C++ knowledge. I only code in C, and for the most part just *nix. I am kind of unsure as to how one would tell if this is in the heap or the stack. In Unix (linux anyways) it is very easy because the addresses are easily identifiable 0xbfffxxxx , stack ect. I pushing an insane amount of data into the buffer and it still crashes on the call dword ptr[eax+4]. I tried putting in much less data and this was the *only* function I could overwrite. I have not tried overflowing the buffer and seeing if i can keep the thread alive (I forgot to mention this is a multithreaded app, sorry) past the first call. It looks like #4 is the way i will probably head. I don't know anything about windows internal memory allocation/heap structures so if this is in the heap i'm definitly SoL. As for relying on hardcoded addresses in the stack/heap where ever the hell I am, it *definitly* changes, and oddly enough the address seems to change every 3-4 days. Thanks again for your reply and I have another question brewing on the server portion of this program. Anyone got any good documents on overwriting the SEH in a multithreaded application? (I already read Havlar Flake's ppt.)
Thanks!
-wire


On Tue, 09 Sep 2003 17:16:49 -0300
 Gerardo Richarte <gera () corest com> wrote:
wirepair wrote:
But i'm having serious issues making this exploit reliable. Currently, I'm referencing hardcoded values in the stack.

Execution flow is altered via a:
.text:10011032                 call    dword ptr [eax+4]

James Michael Wakefield wrote:
I'm coming up against this problem myself at the moment.

  This happened to me too, and is probably pretty common, probably
more in windows, where there is more C++ code, but it also happens in
*nix. There are a bunch of things going on, one, as Dave said, may be
that you are overwriting an object's vtable in the heap, another may
be that you are just overwriting some function pointers. But from what
you said, and from now on is all guess work, I believe you are
overwriting a pointer to an object, not the object itself, not its
vtable directly, you are overwriting a pointer to an object, may be
passed as argument to the function where the bug is... so, in C++

        (as I said, this is all guess work, and I don't even know
what application it is we are talking about, so EVERYTHING may be
wrong)

        vuln_function(SomeClass *obj_arg, char *str_arg) {
                char *buf;

                ...

                strcpy(buf,str_arg);

                ...

                obj_arg->someMethod();

                ...
        }

        In this example, if you overflow buf, you'll overwrite some local
variables, the saved frame pointer, the saved return address and the saved
argument [note that your object pointer may be anywhere, not only in an
argument and not only in the stack, lets assume you are changing an object
pointer].

        So, when the line "obj_arg->someMethod()" is reached, this may be
a possible assembly of it:

        mov ecx, [ebp+8]        ; pointer to object in eax
        mov eax, [ecx]          ; pointer to SomeClass' vtable
        call [eax+4]            ; call 2nd method of SomeClass

        each object, as first field, have a poitner to its class' vtable,
and vtables are no more than a list (array) of function pointer (for the
compilers I know at least).

        For the level of indirections you said you have, I guess this, or
something pretty similar is going on:

Here is where my problem is, I need to find two reliable addresses.
one address to contain another address to contain the address of my shellcode.

        So, let me say, this has become pretty common lately.

        now, what to do?

        Several options... but first, why do you think relaying on a hardcoded
address for the stack is not reliable enough? What does stack addresses depend
on on windows? Well... stack addresses in windows tend to be more reliable than
what we think, this is not to say that it's always ok to trust them, but when
talking about reliability we should ponder all options, and then choose the
more reliable... so we need to know what things depend on, or why the change.

        Simply said, on windows, stack addresses depend on the program itself,
and on the thread that's using that stack (they don't depend on program's args
or environment, as in *nix). So, for a given program, with only one thread,
it's pretty common that the stack address will stay "fixed". Now, let me add
that this is not "science", it's just empirical observation (plus some other
things). In multi threaded programs, if the threads are created and used
allways in the same order, it's also possible that the address can be trusted.
(Similar things happen, in for example, Solaris' lightweight threads).

        So... anyway, let's go back to what to do in your situation.

        Several ideas.

        1. James' idea of trying to supply your own pointers and code, and
          somehow raise the possibilities of hitting both. This can work,
          it depends on lots of things though.

        2. If the overflow is in heap, doing what Dave said

        And, assuming the overflow is in stack, as I think you said:

        3. making an even bigger overflow if possible, hit and change the
          Exception Registration Record, and using JMP EBX (in 2k), or
          a similar techinque in XP.

       4. trying to make the code survive the call [eax+4] without crashing,
          trying to make the code survive everything else until the return
          of the vulnerable function and then use the overwritten return addr
          to jump to your code (probably through a jmp esp)

        3 may look interesting, but on some situations it may not be desirabe.
(for example, if the exploited applicacation knows how to survive an exception,
etc). There is not much to say about it, there is at least one exception handler
in the stack for every application, again, if the application is multithreaded,
it depends on what thread's stack you are overflowing, etc. After changing the
ERR you'll need to make the application/thread crash, but in your case this is
pretty easy :-) [just make call [eax+4] do it for you]

        4 may be complicated, but we had good lcuk when we needed it... lets
go back to what we are doing: Overwriting a pointer to an object. So, if we
find any fixed pointer to an object, whose 2nd vtable entry will not crash,
that's your option...

        Now, when an object is instantiated in C++, some space is allocated for
its data, and in its first field the "class pointer" is stored, so the "new" for
SomeClass may look like:

        newObjetc = malloc(space_needed)
        ((int*)newObject)[0] = &SomeClass_vtable

        so, in assembly, the second line would be something like:

10013106:  C7 06 22 35 02 10         mov dword ptr [esi], offset SomeClass_vtable

        then, in the middle of this instruction you have a pointer to
the class pointer (SomeClass_vtable, in this stupid example, the pointer is
10023522, and is at the address 10013108)... Now, at 10023522 you can find
the vtable, and if the 2nd entry is a function that won't crash in your
situation, the that's what you need.
        You just change whatever needed to 10013108, so eax will be 10023522,
and [eax+4] will be your "void function"...

        now, if mi assuptions are not correct (overflow is in stack, and you
are overwriting an object pointer), then, this is not probably going to work
for you, but I hope at least it makes sence to somebody :-)

        let me know if all this words were helpful
        gera


--
Visit Things From Another World for the best
comics, movies, toys, collectibles and more.
http://www.tfaw.com/?qt=wmf


Current thread: