我正在使用GDB调试Mac OS X 64位应用程序。我看到跳过一大堆代码解决了我所有的问题。
但:
如何修补可执行文件以实现跳转?我希望应用程序在没有调试器的情况下自动跳转到代码中的已定义点。
这就是我想要做的:
地址0x1000027a9
(由调试器给出)跳转到地址0x100003b6e
。我正在努力通过HexEdit来做,但没有成功。我在任何地方读到jmp到绝对地址操作码(FF
似乎是正确的操作码,但它是一个调用,而不是跳转...)但没有任何作用。访问不好,段错误。
我怎样才能做到这一点?
你想要的不是call
,而是jmp
,你想要一个直接的jmp
。直接跳转通常使用相对于下一条指令地址的寻址(参见my answer to SO question: How encode a relative short jmp in x86)。相对于跳转指令的结束是另一种看待它的方式。
所以,你在0x1000027a9
,想跳到0x100003b6e
。
0x100003b6e
- 0x1000027a9
= 0x000013C5
= 5061d
,因此最终不适合短距离跳跃(英特尔文档中的rel8
),但你需要jmp rel32
。它也适合rel16
,但在x86-64(64位模式)中不支持。
所以,你想要一个jmp rel32
。这是相对于jmp
之后的下一条指令编码的,并且由于指令的长度是5个字节(E9 xx xx xx xx
),rel32
将是0x000013C0
。由于x86是一个小端架构,因此编码为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