替代 x86 汇编“调用”指令?

Posted

技术标签:

【中文标题】替代 x86 汇编“调用”指令?【英文标题】:Substitutes for x86 assembly 'call' instruction? 【发布时间】:2011-10-27 00:29:15 【问题描述】:

x86 调用指令有哪些替代方法? 也许像推送返回地址然后跳转?

它们也是获取内存当前位置的命令吗?

【问题讨论】:

查看this answer 以及环境问题。 【参考方案1】:

call 指令实际上为您执行此操作。例如call my_func 会做类似的事情:

push ret_address
jmp my_func

从某种意义上说,后续的ret 调用只会使用您刚刚推回jmp 的地址。是否有您不想使用call 的特定原因,或者它对您不可用? 对于内存中的当前位置,您可以尝试读取eip 寄存器(无法写入)。

【讨论】:

我正在注入一个 asm 代码存根,它使用另一个进程调用内部函数(使用 C#)。基本上想知道他们是否会是一种更优雅的方式来调用该函数而不破坏任何寄存器或堆栈(以便在调用之前保留它们。)我使用的另一个解决方案是编写一个跳转指令,后跟函数地址静态的(类似于 windows 处理 dll 函数的方式。)但是,这意味着跟踪注入代码的缓冲区大小,在我看来这是不优雅的,但看起来这是目前唯一的选择。 另外我想我可以使用间接调用。 是的,你可以使用间接调用,如果你想完全替换函数调用并让它执行你的代码,你可以使用跳转绕道。 除了跳转绕道外,如果需要完全替换函数调用,可以直接在代码中修补相关的调用/跳转偏移。自定义替换函数应具有与原始函数相同的签名。当然,这不适用于间接调用和跳转,但它仍然很有帮助。 可以写入EIP寄存器,指令不叫MOV而是JMP。【参考方案2】:

如果我没有弄混什么,我会说这取决于。如您所见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 相对寻址一样。)【参考方案3】:

您可以将一个双字值和 jmp 推送到该过程。推送将是返回地址:

push return_address (push eax if address in eax)
jmp call_address

如果该特定调用存在参数,请记住还要推送参数。

内存中的当前位置是什么意思?我想你的意思是当前指令指针。您无法直接获取该值,但您可以使用 seh 处理程序(结构化异常处理程序)在导致已处理异常时获取该值。

【讨论】:

以上是关于替代 x86 汇编“调用”指令?的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

Android 逆向x86 汇编 ( push / pop 入栈 / 出栈 指令 | ret / retn 函数调用返回指令 | set 设置目标值指令 )

Android 逆向x86 汇编 ( push / pop 入栈 / 出栈 指令 | ret / retn 函数调用返回指令 | set 设置目标值指令 )

[架构之路-22]:目标系统 - 系统软件 - 汇编语言结构与X86指令系统以及CPU的工作原理函数调用与堆栈操作

X86汇编快速入门