0
votes

I have a jump from original function to my hook, which runs assembly that executes a function. I'm trying to pass arguments from the original function to the function mWSARecv.

Here's how I do it:

void mWSARecv(LPWSABUF lpBuffers)
{
    std::cout << "WSARecv: " << lpBuffers->buf << " Len: " << lpBuffers->len << std::endl;
}

__declspec(naked) int hookWSARecv() // Original -> Here
{
    __asm
    {
        pushad;
        pushfd;

        push[ebp + 0x24];
        call mWSARecv;

        popfd;
        popad;

        jmp WSARecvTramp;
    }
}

I then save registers and flags. Push the desired argument [ebp + 0x24] and call the function which outputs those. It works once, but the next time it causes an execption.

The original function calling convention is __stdcall.

First jump:

enter image description here

Assembly hook:

enter image description here

What am I doing wrong?

1
If mWSARecv is CDECL calling convention the caller has to cleanup the stack. You push 4 bytes with push[ebp + 0x24]; so you'd have to add add 4 to esp after. Maybe place add esp, 4 after the call mWSARecv - Michael Petch
@MichaelPetch Thank you! If mWSARecv would be STDCALL, It should auto cleanup the stack right? In that case adding 4, wouldn't be necessary? Also, could you please explain me, why do I have to add 4 to stack pointer? - J. Doe
In STDCALL the function you call cleans up the stack of the parameters passed. In CDECL the responsibility falls to the person calling the function. If mWSARecv is CDECL the 4 bytes pushed by push[ebp + 0x24];` have to be cleaned up by you (with something like add esp, 4). Failure to do the add of 4 to ESP (in this case) means when mWSARecv returns it will then execute popfd and popad but everything is shifted by 4 on the stack meaning everything that restored by those 2 instructions is corrupt. - Michael Petch
@MichaelPetch Thanks a lot, making much more sense now! :) - J. Doe

1 Answers

4
votes

By default (without overriding the calling convention) the following is CDECL calling convention:

void mWSARecv(LPWSABUF lpBuffers)
{
    std::cout << "WSARecv: " << lpBuffers->buf << " Len: " << lpBuffers->len << std::endl;
}

Per the calling convention, the MSDN documentation says:

Stack-maintenance responsibility - Calling function pops the arguments from the stack.

This is different from STDCALL which has this rule for argument cleanup:

Stack-maintenance responsibility - Called function pops its own arguments from the stack.

With this in mind the issue in your code is in hookWSARecv in these lines:

    push[ebp + 0x24];
    call mWSARecv;

    popfd;

Because mWSARecv is CDECL the parameters you push have to be cleaned up after the call. Failure to do this means that when popfd and subsequent stack operations occur they will all be restored from the wrong place on the stack. In this case to cleanup the stack of the one 4-byte parameter pushed you need to add 4 to ESP after the call. The fix would look like:

    push[ebp + 0x24];
    call mWSARecv;
    add esp, 4;
    popfd;