[英]Why passing arguments to function via inline assembly isn't consistent?
我從原始函數跳到了我的鈎子,該鈎子運行了執行一個函數的程序集。 我試圖將參數從原始函數傳遞給函數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 。
第一跳:
組裝鈎:
我究竟做錯了什么?
默認情況下(不覆蓋調用約定),以下是CDECL調用約定:
void mWSARecv(LPWSABUF lpBuffers)
{
std::cout << "WSARecv: " << lpBuffers->buf << " Len: " << lpBuffers->len << std::endl;
}
根據調用約定,MSDN文檔說:
堆棧維護責任- 調用函數從堆棧中彈出參數。
這與STDCALL不同,后者具有用於參數清除的規則:
堆棧維護責任- 調用的函數從堆棧中彈出自己的參數。
考慮到這一點,您的代碼中的hookWSARecv
在以下hookWSARecv
行的hookWSARecv
中:
push[ebp + 0x24];
call mWSARecv;
popfd;
因為mWSARecv
是CDECL,所以在調用之后必須清除您推送的參數。 未能做到這一點意味着,當popfd
和后續的堆棧操作發生時,它們都將從錯誤的堆棧中恢復。 在這種情況下,要清理推入的一個4字節參數的堆棧,您需要在調用后向ESP添加4。 該修復程序如下所示:
push[ebp + 0x24];
call mWSARecv;
add esp, 4;
popfd;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.