需要帮助理解FF间接调用指令x86

时间:2017-05-06 12:58:12

标签: assembly x86 intel

我试图重新编码一个简单的ftrace,但我无法理解像这样的FF间接调用:

{{1}}

它是否像具有偏移量的E8指令一样工作?如果没有,如何找到呼叫指向的地址?那个电话的回复地址?

3 个答案:

答案 0 :(得分:3)

指令callq *0x200b76(%rip)执行以下操作:

  1. rip + 0x200b76加载一个64位字,其中rip指令指针。根据评论,这应该是地址0x600ff0,但如果您的代码被重新定位,它可能会有所不同。
  2. 将堆栈上下一条指令的地址作为返回地址。
  3. 跳转到我们在第一步中读取的基准值。
  4. 与正常call(即操作码e8)指令的区别在于,这是间接函数调用,其中我们调用的地址是从内存加载而不是在那里指定。这由星号(*)表示。 call foo call *foomov $foo,%eax相同mov foo,%eax

答案 1 :(得分:0)

跳跃可以用几个属性来表征:

  • 直接或间接(即地址是在指令中给出还是从存储器指针中检索)。

  • 相对(地址作为增量给出,相对CALL操作码所在的位置)或绝对(跳转到实际的,提供的地址)。间接跳跃总是绝对的。

  • 靠近(在同一段)或远(在不同的段)。远距离总是绝对的。

现在,E8是直接的,近的,相对的。相比之下,FF是间接的,接近的和绝对的。有FF的变体远近而非近,主要用于呼叫门AFAIK。有关CALL s。

的简洁表,请参阅here

另见:How can I tell if jump is absolute or relative?

那么你的问题:

  

如何找到呼叫指向的地址

15表示指针相对于RIP(如果它是相对的,例如RAX,那么你就有ff 90)。相对于RIP的偏移量位于15之后的四个字节中 - 在您的示例中,这些是0x00200b76。有关解码的其他说明,请参阅Why call instruction opcode is represented as FF15?

  

该通话的回复地址

返回地址始终是紧跟在CALL指令之后的指令。因此,如果CALL位于地址0x100000,则返回地址将为0x100006

答案 2 :(得分:0)

间接分支(间接跳转和间接调用)是二进制分析工具的主要挑战。您需要检查几种工具以了解这些工具如何处理间接分支。最受欢迎的二进制分析工具是:

  • IDA Pro
  • Radare2
  • Dyninst
  • Ghidra
  • BAP

这些技术使用不同的方法来解决间接分支(编译器模式,递归反汇编和传播)。 但是,我认为没有一种工具能够解决所有类型的间接分支。

重要说明: 间接分支是:

  1. 间接跳转
  2. 间接调用函数
  3. 尾部函数和
  4. 止回功能