在IP之前检测呼叫指令

时间:2012-10-12 20:26:54

标签: assembly x86

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

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

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

E.g。如果我找到FF 10,那么在E8之前检查是否有3个字节 - 是否足够或没有?我还没有想到其他隐藏的陷阱?

2 个答案:

答案 0 :(得分:3)

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

额外的信息来自于知道它跳到哪里,以及知道返回地址。如果差异与返回地址之前的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:

现在,无论如何,它都会以一种你无法察觉的方式进行匹配。

所以你唯一能发现的是它是否绝对不是直接电话。您无法确定使用任何特定方式 - 显然可以替换上述代码段中的call calladdr,使其看起来像任何所需的模式。

答案 1 :(得分:2)

基本上,你不能。你也无法区分完成一个调用和在堆栈上推送一些地址然后进行跳转。你可以做出有根据的猜测,但除非你真的在某种模拟器中运行代码来完成一个完整的指令跟踪(记录),否则一些恶意代码总是可能欺骗你。