【发布时间】:2017-04-27 16:42:36
【问题描述】:
我从原始函数跳转到我的钩子,它运行执行函数的程序集。我正在尝试将参数从原始函数传递给函数 mWSARecv。
我是这样做的:
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;
}
}
然后我保存寄存器和标志。推送所需的参数 [ebp + 0x24] 并调用输出这些参数的函数。它工作一次,但下一次它会导致执行。
原来的函数调用约定是__stdcall。
第一次跳转:
组装钩子:
我做错了什么?
【问题讨论】:
-
如果
mWSARecv是 CDECL 调用约定,则调用者必须清理堆栈。您使用push[ebp + 0x24];推送 4 个字节,因此您必须在 esp 之后添加 add 4 。也许在call mWSARecv之后放置add esp, 4 -
@MichaelPetch 谢谢!如果 mWSARecv 是 STDCALL,它应该自动清理堆栈吗?在那种情况下加4,就没有必要了吗?另外,请您解释一下,为什么我必须在堆栈指针中添加 4?
-
在 STDCALL 中,您调用的函数会清理传递的参数堆栈。在 CDECL 中,责任落在调用函数的人身上。如果
mWSARecv是 CDECL,则 push[ebp + 0x24];` 推送的 4 个字节必须由您清理(使用类似add esp, 4的内容)。未能将 4 添加到 ESP (在这种情况下)意味着当 mWSARecv 返回时,它将执行popfd和popad但堆栈上的所有内容都移动了 4,这意味着所有恢复的内容这 2 条指令已损坏。 -
@MichaelPetch 非常感谢,现在更有意义了! :)
标签: winapi assembly visual-c++ x86 calling-convention