组装远程呼叫或远程跳转(j *指令)

时间:2018-01-29 09:44:57

标签: assembly x86 clang x86-64 objdump

我试图创建一个调度表,用于更改AllocateMemoryOnRemoteProcess分配的另一个地址中某些指令的位置。

我遇到的一个问题几乎都是Calls,所有类型Jumps都是nearrelative,只要我在新版本中加载程序集位置,然后这些说明不起作用。

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

push 0xdeadbeef
ret

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

mov %eax,0xdeadbeef
jmp %eax

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

this question中有人写道:

  
      
  • 调用far(使用操作码9A)跳转到绝对段和偏移量。   也就是说,它就像是一次设置CS和?IP。
  •   

所以我似乎应该将9A的操作码用于far calls,但这只适用于调用,我不知道用这种方法转换各种类型的跳转!

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

clang -c MyAsm.asm -m32

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

例如MyAsm.asm为:

call   0x402af2

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>

这些结果是相对的。

所以我的问题是:

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

1 个答案:

答案 0 :(得分:4)

如果您可以备用注册表,我建议您使用

class Client():
    def __init__(self):
        host = socket.gethostname()
        port = 5000
        client_socket = socket.socket()
        client_socket.connect((host, port))
        gui = Dialog(client_socket)
        gui.show()
        message = ""

        while message.lower().strip() != 'bye':

            data = client_socket.recv(1024).decode()
            print('message: ', data)

        client_socket.close()

if __name__ == '__main__':
    client = Client()

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

    movabs $addr,%rax
    jmp *%rax

我强烈建议您不要使用

    mov $addr,%eax
    jmp *%eax

因为这会破坏返回预测,使得接下来的几个函数返回的速度比必要的慢。远程跳跃和通话( push $addr ret ljmp)都是红鲱鱼。虽然它们可以在技术上使用,但它们无法帮助您实现目标,实际上是出于不同的目的(更改lcall)并在现代处理器上实现为缓慢的微编码指令。

如果你不能备用一个寄存器,你可以使用这种技巧:

cs

这应该只是工作,此外不要求你使用额外的寄存器。它虽然比使用寄存器慢。

请注意,条件跳转严格要求跳转目标立即生效。如果你想要一个条件跳转到绝对地址,请使用这样的成语:

    jmp *0f(%rip)
0:  .quad addr