组装远调用或远跳转(j* 指令)

ᔕIᑎ*_*ᑎᗪI 3 x86 assembly x86-64 clang objdump

我正在尝试创建一个调度表,该表更改由AllocateMemoryOnRemoteProcess.

其中的一个问题,我遇到的是几乎所有的Calls都挺Jumpsnearrelative和,只要我加载新的位置的组件,然后这些指令将无法正常工作。

据我所知,我应该将这些说明转换为far jumpfar call我在谷歌搜索期间看到的解决方案之一正在使用pushret喜欢:

push 0xdeadbeef
ret
Run Code Online (Sandbox Code Playgroud)

或者有人建议使用寄存器进行绝对寻址,例如:

mov %eax,0xdeadbeef
jmp %eax
Run Code Online (Sandbox Code Playgroud)

这些解决方案在我的情况下不起作用,因为只要我在函数例程中,更改堆栈状态或在第二种情况下更改寄存器%eax就会导致失败。

有人在这个问题中写道:

  • call far(使用操作码 9A)跳转到一个绝对段和偏移量。即,这就像一次设置 CS 和 ?IP。

所以看来我应该将操作码与9Afor一起使用far calls,但这仅适用于调用,我不知道使用此方法转换各种跳转!

我经常objdump用来反汇编二进制文件,然后使用clang以下命令用作汇编程序:

clang -c MyAsm.asm -m32
Run Code Online (Sandbox Code Playgroud)

但是当我用上面的命令组装时,结果是相对的。

例如什么时候MyAsm.asm是:

call   0x402af2
Run Code Online (Sandbox Code Playgroud)

结果objdump是:

    MyAsm.o:    file format Mach-O 32-bit i386

Disassembly of section __TEXT,__text:
__text:
       0:   e8 ed 2a 40 00  calll   4205293 <__text+0x402AF2>
Run Code Online (Sandbox Code Playgroud)

这些结果是相对的。

所以我的问题是:

  1. 我如何组装far callsfar jumpsj*指令)clang或任何其他工具(当然,这些工具适用于 80x86 和 Amd64 结构)?
  2. 是否有任何其他指令,如使用相对寻址的调用或跳转,所以我应该重新组装以避免出现问题?

fuz*_*fuz 8

如果您可以节省寄存器,我建议您使用

    movabs $addr,%rax
    jmp *%rax
Run Code Online (Sandbox Code Playgroud)

或者,如果您可以确保地址在地址空间的前 2 GB 内,

    mov $addr,%eax
    jmp *%eax
Run Code Online (Sandbox Code Playgroud)

我强烈建议你不要使用

    push $addr
    ret
Run Code Online (Sandbox Code Playgroud)

因为这破坏了返回预测,使得接下来的几个函数返回比必要的慢。远跳和呼叫(ljmplcall)是一个红鲱鱼。虽然它们在技术上可以使用,但它们不会帮助您实现目标,并且实际上用于不同的目的(更改cs),并且在现代处理器上以缓慢的微编码指令的形式实现。

如果您不能节省寄存器,您可以使用这种技巧:

    jmp *0f(%rip)
0:  .quad addr
Run Code Online (Sandbox Code Playgroud)

这应该可以正常工作,而且不需要您使用额外的寄存器。虽然它比使用寄存器慢。

请注意,条件跳转严格要求跳转目标是立即的。如果你想有条件地跳转到绝对地址,请使用这样的习惯用法:

    # for jz addr
    jnz 1f
    jmp *0f(%rip)
0:  .quad addr
1:
Run Code Online (Sandbox Code Playgroud)

  • @ᔕIᑎᗩKᗩᖇᐯᗩᑎᗪI 不,它没有。您可以使用“跳转”习语来解决此问题。让我更新我的答案来解释这一点。 (2认同)