我试图重新编码一个简单的ftrace,但我无法理解像这样的FF间接调用:
{{1}}
它是否像具有偏移量的E8指令一样工作?如果没有,如何找到呼叫指向的地址?那个电话的回复地址?
答案 0 :(得分:3)
指令callq *0x200b76(%rip)
执行以下操作:
rip + 0x200b76
加载一个64位字,其中rip
是指令指针。根据评论,这应该是地址0x600ff0
,但如果您的代码被重新定位,它可能会有所不同。与正常call
(即操作码e8
)指令的区别在于,这是间接函数调用,其中我们调用的地址是从内存加载而不是在那里指定。这由星号(*
)表示。 call foo
call *foo
与mov $foo,%eax
相同mov foo,%eax
。
答案 1 :(得分:0)
跳跃可以用几个属性来表征:
直接或间接(即地址是在指令中给出还是从存储器指针中检索)。
相对(地址作为增量给出,相对给CALL
操作码所在的位置)或绝对(跳转到实际的,提供的地址)。间接跳跃总是绝对的。
靠近(在同一段)或远(在不同的段)。远距离总是绝对的。
现在,E8
是直接的,近的,相对的。相比之下,FF
是间接的,接近的和绝对的。有FF
的变体远近而非近,主要用于呼叫门AFAIK。有关CALL
s。
另见: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)
间接分支(间接跳转和间接调用)是二进制分析工具的主要挑战。您需要检查几种工具以了解这些工具如何处理间接分支。最受欢迎的二进制分析工具是:
这些技术使用不同的方法来解决间接分支(编译器模式,递归反汇编和传播)。 但是,我认为没有一种工具能够解决所有类型的间接分支。
重要说明: 间接分支是: