Re: win32 call dword ptr [eax] help needed

From: Gerardo Richarte (gera_at_corest.com)
Date: 09/09/03

  • Next message: Steve Ryan: "Re: Ethernet ( MAC ) Address Reliability"
    Date: Tue, 09 Sep 2003 17:16:49 -0300
    To: vuln-dev@securityfocus.com
    
    

    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


  • Next message: Steve Ryan: "Re: Ethernet ( MAC ) Address Reliability"

    Relevant Pages

    • Re: [SC-L] Off-by-one errors: a brief explanation
      ... concept to the public called 'overwriting the frame pointer', ... was a stack based off by one, it allowed you to overwrite the LSB ... > terminator value to signify the last element of the array. ...
      (SecProg)
    • Re: I feel stupid... "Invalid combination of opcode and operand", was, now is FORTH question
      ... TOS in ebx - top of stack - first stack element ... PSP in ebp - parameter stack pointer - pointer to stack, ... execute next at the end of their definition. ... High level Forth definitions merely organize the ...
      (comp.lang.asm.x86)
    • Re: win32 call dword ptr [eax] help needed
      ... I am kind of unsure as to how one would tell if this is in the heap or the stack. ... Anyone got any good documents on overwriting the SEH in a multithreaded application? ... >vtable directly, you are overwriting a pointer to an object, may be ... >talking about reliability we should ponder all options, ...
      (Vuln-Dev)
    • [0xbadc0ded #04] smtp.proxy <= 1.1.3
      ... A remotely exploitable format string vulnerability exists in smtp.proxy ... Since the 'line' buffer is ... Since smtp.proxy is started from a superserver, like inetd, the stack ... To determine the address of a function pointer we could either try to ...
      (Bugtraq)
    • [Full-Disclosure] [0xbadc0ded #04] smtp.proxy <= 1.1.3
      ... A remotely exploitable format string vulnerability exists in smtp.proxy ... Since the 'line' buffer is ... Since smtp.proxy is started from a superserver, like inetd, the stack ... To determine the address of a function pointer we could either try to ...
      (Full-Disclosure)