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



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


为什么retn指令实际上没有返回?我以为在入口点返回将始终退出该过程。
为什么堆栈没有损坏?例如,该函数不会使用sub esp, 0x...分配任何堆栈空间。
这种行为奇怪吗?


#1 楼


sub_1313cba4的地址被移到PC / IP,但不能直接移到PC / IP,因为不能这样做。这是通过将地址压入堆栈并依靠retn将获得堆栈顶部的内容并重定向到那里的执行这一事实来完成的。
这取决于您破坏堆栈的含义。堆栈只是内存中的一个位置,只能通过不正确处理其中的数据来造成损坏。例如,尝试将执行重定向到不代表代码的地址。如果在构建应用程序时始终牢记堆栈中的内容,则它可以正确继续执行。
在正常应用程序中,这被认为很奇怪,因为这不是正常方法。如果我们谈论的是漏洞,恶意软件或任何模糊的二进制文件,则这是标准做法。这样做会使反转过程更加复杂,因为以这种方式调用函数对于工具而言更难遵循。这也使反向器更难遵循应用程序的逻辑。


#2 楼

我的答案:



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

现在,这里到底发生了什么...实际上,这很简单,将sub_1313cba4的地址压入堆栈并执行ret指令。基本上,ret只会执行pop eip(请注意,由于我们无法寻址i386中的eip寄存器,因此该指令不存在)。因此,它将把子程序sub_1313cba4的地址加载到eip中并开始执行它(内存上下文,我的意思是堆栈,将保持原样。不会创建新的堆栈帧,因此子例程必须使用此地址)

这种方式将完全不遵循规则而完全失去对调用堆栈的跟踪(并且会扰乱许多二进制分析工具,例如IDA)。

此功能为何不会损坏堆栈?此功能确实会损坏[call]堆栈。从这一点开始将很难恢复调用堆栈。但是,它可能是软件的程序员想要的。正如我之前所说,我真的怀疑这里有些软件混淆。
这种行为奇怪吗?是的,这完全是非标准的,可能是预定的。