【问题标题】:Why passing arguments to function via inline assembly isn't consistent?为什么通过内联汇编将参数传递给函数并不一致?
【发布时间】: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 中,责任落在调用函数的人身上。如果 mWSARecvCDECL,则 push[ebp + 0x24];` 推送的 4 个字节必须由您清理(使用类似 add esp, 4 的内容)。未能将 4 添加到 ESP (在这种情况下)意味着当 mWSARecv 返回时,它将执行 popfdpopad 但堆栈上的所有内容都移动了 4,这意味着所有恢复的内容这 2 条指令已损坏。
  • @MichaelPetch 非常感谢,现在更有意义了! :)

标签: winapi assembly visual-c++ x86 calling-convention


【解决方案1】:

默认情况下(不覆盖调用约定)以下是CDECL 调用约定:

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

根据调用约定,MSDN 文档说:

堆栈维护责任 - 调用函数从堆栈中弹出参数。

这与STDCALL 不同,后者有此参数清理规则:

堆栈维护责任 - 被调用函数从堆栈中弹出它自己的参数。

考虑到这一点,您的代码中的问题在hookWSARecv 中:

    push[ebp + 0x24];
    call mWSARecv;

    popfd;

因为mWSARecvCDECL,所以你推送的参数必须在调用后清理。不这样做意味着当popfd 和随后的堆栈操作发生时,它们都将从堆栈上的错误位置恢复。在这种情况下,要清理推送的一个 4 字节参数的堆栈,您需要在调用后将 4 添加到 ESP。修复看起来像:

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

【讨论】:

  • 再次感谢您,感谢!不过,我还有一个问题,可能是 [ebp + 0x24] 参数的位置并不总是相同的吗?
  • @J.Doe 参数的位置将始终在 CA:LL 指令本身推送的返回地址之前的堆栈上。将参数压入堆栈的物理地址可以根据程序本身而改变。不过,我可能还没有完全理解你的新问题。
  • 谢谢,这就解释了。发生的问题还导致参数偏移量并不总是相同。一次是 0x24,另一次是 0x23。你知道我怎么能检测到这样的变化吗?谢谢!
  • 您正在使用父函数的ebp,而不是设置自己的堆栈帧。不一定有任何理由保持一致,至少它取决于调用 WSARecv 的函数。改为阅读与esp 相关的参数,这将是一致的。
猜你喜欢
  • 2014-06-16
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
相关资源
最近更新 更多