为什么这个 retn 指令不从函数返回?

逆向工程 艾达 视窗 混淆 可执行
2021-06-22 06:28:01

我在 Windows 上用 IDA 反汇编了一个 exe 文件,看到了这个函数的序言:

艾达

我看到当retn执行而不是返回时,它会跳转到sub_1314cba4.

  1. 为什么retn指令实际上没有返回?我认为在入口点返回将始终退出该过程。

  2. 为什么堆栈没有损坏?例如,该函数不分配任何堆栈空间sub esp, 0x...

  3. 这种行为很奇怪吗?

2个回答
  1. 的地址sub_1313cba4被移动到 PC/IP,但不能直接移动,因为这无法完成。它是通过将地址推送到堆栈并依赖于retn将获取堆栈顶部的内容并将执行重定向到那里的事实来完成的。

  2. 好吧,这取决于您所说的损坏堆栈的含义。堆栈只是内存中的一个地方,只有不正确处理其中的数据才会造成损坏。例如,尝试将执行重定向到不代表代码的地址。如果应用程序在构建时时刻牢记堆栈中的内容,它就可以正确地继续执行。

  3. 在正常的应用程序中它被认为是奇怪的,因为这不是正常的方式。如果我们谈论的是破解程序、恶意软件或任何混淆的二进制文件,那么这是标准做法。这样做是为了使逆向过程更加复杂,因为以这种方式调用函数对于工具来说更难遵循。这也使逆向者更难遵循应用程序的逻辑。

我的回答:

  1. 这是为什么?您正在查看的程序可能使用了一些软件混淆,因为这不是从函数返回的常用方法。我的猜测是这个函数只是为了打破自动二进制分析。

    现在,这里究竟发生了什么……事实上,这很简单,将 的地址sub_1313cba4压入堆栈并ret执行指令。基本上,ret只会做一个pop eip(注意,这样的指令不存在,因为我们无法eip在 i386 中寻址寄存器)。因此,它会加载子程序的地址sub_1313cba4进入 eip,并开始执行它(内存方面,我的意思是堆栈,仍将因为它是现在没有新的堆栈帧将被创建,使例程必须考虑到这一点正常工作)。

    这种做法会因为不遵守规则而完全失去对调用堆栈的跟踪(并且会干扰许多二进制分析工具,例如 IDA)。

  2. 这个函数怎么不破坏堆栈?此函数确实会损坏 [call] 堆栈。从这一点开始恢复调用堆栈将非常困难。但是,它可能是软件程序员的意图。正如我之前所说,我真的怀疑这里有一些软件混淆。

  3. 这种行为很奇怪吗?是的,这完全是非标准的,可能是有意为之。