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:
Assembly hook:
What am I doing wrong?
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;