【发布时间】:2011-10-27 00:29:15
【问题描述】:
x86 调用指令有哪些替代方法? 也许像推送返回地址然后跳转?
它们也是获取内存当前位置的命令吗?
【问题讨论】:
-
查看this answer 以及环境问题。
x86 调用指令有哪些替代方法? 也许像推送返回地址然后跳转?
它们也是获取内存当前位置的命令吗?
【问题讨论】:
call 指令实际上为您执行此操作。例如call my_func 会做类似的事情:
push ret_address
jmp my_func
从某种意义上说,后续的ret 调用只会使用您刚刚推回jmp 的地址。是否有您不想使用call 的特定原因,或者它对您不可用?
对于内存中的当前位置,您可以尝试读取eip 寄存器(无法写入)。
【讨论】:
如果我没有弄混什么,我会说这取决于。如您所见here 有近调用和远调用,但我们只考虑近调用。还有两种可能
E8 <offset> # relative
FF <address> # absolute
而FF 表示绝对“跳跃”,而E8 确实表示相对于当前eip。
所以如果你有例如
E8 32 45 ab 6f
意思是
call 0x3245ab6f
这将转化为
push %eip
add $0x3245ab6f, %eip
而不是
push %eip
jmp $0x3245ab6f
【讨论】:
call 推送自身过去的地址,即下一条指令的地址。 x86 没有架构上可见的%eip,因此在添加调用指令的长度后,您至少应该注释您的伪代码以解释您的%eip 是已经增加的EIP。 (但是,是的,相对位移是相对于指令的结尾,即返回地址,就像 64 位 RIP 相对寻址一样。)
您可以将一个双字值和 jmp 推送到该过程。推送将是返回地址:
push return_address (push eax if address in eax)
jmp call_address
如果该特定调用存在参数,请记住还要推送参数。
内存中的当前位置是什么意思?我想你的意思是当前指令指针。您无法直接获取该值,但您可以使用 seh 处理程序(结构化异常处理程序)在导致已处理异常时获取该值。
【讨论】: