将跳转命令写入x86-64二进制文件

Joh*_*ite 1 macos assembly patch x86-64

我正在使用GDB调试Mac OS X 64位应用程序。我看到跳过一大堆代码可以解决我所有的问题。

但:

如何修补可执行文件以实现跳转?我希望应用程序在没有调试器的情况下自动跳转到代码中的定义点。

这就是我想做的:

在地址0x1000027a9(由调试器提供)处跳转到address 0x100003b6e。我正在努力通过HexEdit进行操作,但是没有成功。我在任何地方都读到了关于jmp到绝对地址操作码的信息(FF似乎是正确的操作码,但这是一个调用,而不是跳转...),但是没有任何效果。错误的访问,segfault。

我怎样才能做到这一点?

nrz*_*nrz 5

您想要的不是一个call,而是一个jmp,而您想要一个直接的jmp。直接跳转通常使用相对于下一条指令地址的寻址(请参阅我对SO问题的回答:如何在x86中编码相对较短的jmp)。相对于跳转指令的末尾是另一种查看指令的方法。

因此,您现在0x1000027a9正要跳到0x100003b6e

0x100003b6e- 0x1000027a9= 0x000013C5= 5061d,因此绝对不适合短时跳转(rel8在Intel文档中),但您需要jmp rel32。它也适用rel16,但是x86-64(在64位模式下)不支持。

因此,您想要一个jmp rel32。该代码相对于之后的下一条指令进行jmp编码,并且由于该指令的长度为5个字节(E9 xx xx xx xx),因此rel32将为0x000013C0。由于x86是Little-endian体系结构,因此编码为E9 C0 13 00 00

为了确认这一点,我用NASM汇编了一个小的测试可执行文件,并用ndisasm对其进行了反汇编(请注意,我遗漏了第一个0x10000000字节,但是由于跳转是相对的,因此它不会更改编码中的任何内容):

000027A8  90                nop
000027A9  E9C0130000        jmp dword 0x3b6e ; this is the instruction you need.
000027AE  90                nop
Run Code Online (Sandbox Code Playgroud)