【问题标题】:How to call a function and pass arguments to it in x86 assembly如何在 x86 汇编中调用函数并将参数传递给它
【发布时间】:2018-01-31 18:23:22
【问题描述】:

英特尔处理器 视窗 10 64 位 C++ x86 汇编

我有两个程序,都是我用 C++ 编写的。为了简单起见,我将它们称为程序 A 和程序 B。它们实际上并没有做任何特别的事情,我只是用它们来测试一些东西并在此过程中获得一些乐趣。

想法是程序A将代码注入程序B,注入的代码将设置程序B中函数的参数,并调用程序B中的函数。

我必须说我从这个实验中学到了很多东西。由于我需要打开具有适当权限的进程的句柄,然后构造要注入的汇编代码,因此使用 CreateRemoteThread 调用它并随后进行清理。

我已经设法做到了这一点,并从程序 B 中调用了一个函数,该函数采用一个 UINT64 类型的参数。

我通过注入以下汇编代码来做到这一点:

b9 paramAddr
e8 funcAddr
c3

通过在程序 B 中使用 CreateRemoteThread 从程序 A 调用此代码 sn-p,我设法在地址处调用函数并传递参数。这很好用。没有什么太复杂的,只需调用一个接受一个参数的函数。这里需要注意的一点是,我在这段代码之前已经注入了参数,并且只是为 b9 提供了一个参数地址。

现在我没有做的是从程序 A 中调用程序 B 中的一个函数,该函数接受两个参数。

函数示例: myFunction(uint num1, int num2)

注入的过程是相同的,并且所有工作都很好 Windows API 提供了大量有据可查的功能。

我不能够做的是将两个参数传递给函数。这就是我的麻烦开始的地方。我一直在研究 x86 汇编函数调用约定。他们所做的只是

push param2
push param1
call functAddr
retn

执行 mov 到 esi

谁能澄清、解释并提供一个清晰的例子来说明如何在 x86 程序集中调用一个函数,该函数采用两个参数或类型为 uint 和 int。

感谢大家的时间和精力。

【问题讨论】:

  • 在 x86-64 上,一些参数在堆栈上的其他寄存器中传递。从en.wikipedia.org/wiki/X86_calling_conventions开始
  • 第一个参数在rcx,第二个在rdx(然后是r8r9)。您还需要创建一个home area,可能通过sub rsp, 20h
  • @MargaretBloom 取决于调用约定...
  • @Macmade 是的。使用 VC++ 编译的 Windows 64 位 C++ 代码,上次我检查时使用了这个调用约定。
  • 如果程序 A 不是调试器,则它无法使用 CreateRemoteThread。该 API 甚至存在是 Windows 中最大的单一设计错误的有力竞争者。

标签: c++ c function assembly x86


【解决方案1】:

由于您正在寻找一种方法来理解和澄清内部发生的事情,我建议您首先为您正在使用的特定机器生成一个汇编文件。如果您使用 gcc 或 g++,您可以使用 -S 标志来生成相关的汇编文件。一开始你可以实现一个有两个参数的函数,然后在你的主函数中调用这个函数。使用汇编程序文件,您应该可以很好地了解在调用函数之前堆栈是如何填充的以及返回值的放置位置。在下一步中,您应该将您在汇编文件中看到的内容与x86 calling convetion 进行比较。

【讨论】:

  • ABI 也与操作系统有关,而不仅仅是机器。
  • @Macmade 感谢您的评论。我编辑了我的答案。
  • 非常感谢您的指导。我又检查了几次函数的汇编代码。简单的问题是您必须确定参数的顺序,然后以相反的顺序传递它们。此外,您必须查看哪些参数进入堆栈以及哪些参数将进入注册表。
猜你喜欢
  • 2016-10-24
  • 2016-12-08
  • 2011-01-19
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
相关资源
最近更新 更多