【问题标题】:Detect call instruction before IP检测IP前的呼叫指令
【发布时间】:2012-10-12 20:26:53
【问题描述】:

在 x86 上,在调用之后,压入堆栈的地址指向调用指令之后的位置。该指令在 x86 机器上可以是可变长度的。有没有办法检测使用了哪种调用?

例如,间接调用 *(%eax) 是 FF 10,但这也可能是直接调用 0x10FF10FF 的一部分。即

12: ff 10                   call   *(%eax)
14: e8 fb 10 ff 10          call   10ff1114 <main+0x10ff1114>

例如如果我找到 FF 10,那么在 E8 之前检查 3 个字节是否足够?还有哪些我没有想到的隐藏陷阱?

【问题讨论】:

  • 只有这些是您想要区分的情况吗?
  • 现在我只需要检测它是间接调用还是其他任何东西。

标签: assembly x86


【解决方案1】:

由于您获得的信息比平时略多,因此不太可能。但我会确切地说明即使有额外的信息,它仍然是不可能的。

额外的信息来自于知道它跳转到哪里,并且知道返回地址。如果差异与返回地址之前的 dword 不匹配,则它不是直接调用。所以这是你可以相对容易地找到的东西,而不必弄乱反向解码(这通常是不可能的,只有靠运气和启发式方法以及不是专门设计来克服它的代码,即使这样,跳跃也可能来了从任何地方任何地方进入)。

但是,代码可能是这样的:

  push returnaddr
  mov eax, calladdr
  jmp eax ;or whatever way you like, showing a silly jump through reg for no reason
  ...
  call calladdr
returnaddr:

现在它仍然匹配,以一种你不可能检测到的方式。

因此,您唯一能查明的就是这是否绝对不是直接调用。您无法确定是否使用了任何特定方式 - 显然可以替换上述 sn-p 中的 call calladdr 以使其看起来像任何所需的模式。

【讨论】:

  • 是的,如果只有 jmp 之前的 returnaddr 会指向“jmp”之后的地方……但通常使用 jmp 来使 returnaddr 成为一个完全不同的地址。但如果我涵盖大多数正常情况,我可以忍受这个限制。另外,现在我更好地理解了为什么有时代码在调试器中崩溃而没有堆栈跟踪,除了一些奇怪的地址。谢谢。
【解决方案2】:

基本上,你不能。您也无法区分进行调用和将某个地址压入堆栈然后进行跳转之间的区别。您可以做出有根据的猜测,但除非您实际上在某种仿真器中运行了代码,从而生成了完整的指令跟踪(记录),否则某些恶意代码总是有可能欺骗您。

【讨论】:

  • 嗯,我错过了它可能是跳跃的事实。这真的让事情变得更难了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-08-26
  • 2014-06-13
相关资源
最近更新 更多