0
votes

I have a hook function that executes inline assembly:

__declspec(naked) int hookConnect()
{
    __asm
    {
        pushad;
        pushfd;

        push [esp + 0x2C];
        pop sockAddrBackup;

        push[esp + 0x2C];
        push[esp + 0x2C];
        call mConnect;

        popfd;
        popad;

        call connectTramp;

        ret;
    }
}

It saves the registers and flags. Then saves one of the args to a variable and finally pushes 2 args and calls my custom function which just logs args.

After that, it restores registers, flags. At this time I want to call the trampoline:

Trampoline:

5 original bytes  
jmp (original func + 5 bytes)

Which executes first 5 bytes, jumps to original func and executes it, then returns to my hook function.

At this point, I want to return to the caller of the original func, but since the leave is called when function finishes, it breaks the stack?

How could I preserve the stack through the execution? Save return address before calling?

1
Your code has call but your description has jmp. It seems like jmp would be correct. Also note that you have to copy complete instructions rather than stopping after 5 bytes. There are libraries like MS Detours that take care of all of this for you. - Ben Voigt
@BenVoigt I'm calling connectTramp; which contains first 5 bytes of original func and that jumps to continue on executing original func and as it is a call, it'll then return. I don't like detours :) - J. Doe
I have no idea what "the leave is called when function finishes" means, but I found your problem. You are correct that the stack layout is broken in your code. - Ben Voigt
@BenVoigt Thank you again! And what I meant was assembly "leave" instruction does destroy the stack frame. - J. Doe

1 Answers

2
votes

By calling the trampoline, you're placing another stack frame above the original arguments, which means they aren't where the original code expects to find them (there are two return addresses on the stack instead of just one).

You must either

  1. Jump to the trampoline (your hook won't be able to have an epilogue)

or

  1. Copy the original arguments onto the stack before calling the trampoline, and clean them up after it returns, being careful to preserve the return value.