如何确定可执行文件中反汇编代码的位置?

时间:2009-10-30 04:11:17

标签: assembly executable patch otool

我有一个包含bug的可执行文件(C ++,i386,在MacOS / X Tiger下编译,如果重要)。错误的修复是直截了当的 - 在代码中有一个地方,它调用fork(),它不应该。因为修复很简单,并且因为此时从头开始重新编译可执行文件很困难(请不要问),我想直接修补可执行文件/二进制文件。

作为迈出的第一步,我在我的可执行文件上运行了“otool -tV MyExecutableName”,瞧,我在反汇编输出中找到了这个:

./MyExecutableName:
(__TEXT,__text) section
[... many lines omitted ...]
0002ce0d        subl    $0x10,%esp
0002ce10        calll   0x0051adac
0002ce15        movzbl  0x14(%ebp),%esi
0002ce19        calll   0x00850ac9      ; symbol stub for: _fork
0002ce1e        cmpl    $0x00,%eax
0002ce21        jll     0x0002cf02
0002ce27        jle     0x0002ce34
[... many more lines omitted ...]

所以我想做的是替换第0002ce19行的操作码,这样它就可以无条件地跳转到失败的情况下(即它应该像fork()一样返回-1)而不是calll'ing _fork。 )

不幸的是,我在反汇编/二进制修补方面是一个完全新手,所以我不知道如何去做。特别是,我的问题是:

1)我应该将哪些字节写入位置0002ce19到0002xe1d以获得我想要的内容?我假设它将是“jmp 0x0002cf02”的组合等价物,但我如何弄清楚这些字节是什么?

2)“otool -tV”打印的偏移量似乎偏移到可执行文件的__TEXT段。如何计算打印偏移量与文件顶部之间的字节差值,以便我可以编辑/修补文件中的正确字节?

感谢您提供任何建议!

3 个答案:

答案 0 :(得分:3)

我不熟悉MacOS / X,但我可以给你一些提示。

解决问题的正确方法是使用反汇编程序修补文件。

0002ce19        calll   0x00850ac9

可以替换为

0002ce19        movl   eax, -1 ; mov eax, 0xFFFFFFFF

您看到的偏移是相对的,因此您无法在文件中找到它们 例如,jll 0x0002cf02实际上是jll 0x000000DF

如果我没错,可以使用下面的代码块

0002ce19        calll   0x00850ac9      ; symbol stub for: _fork
0002ce1e        cmpl    $0x00,%eax
0002ce21        jll     0x0002cf02
0002ce27        jle     0x0002ce34

将具有这种组合形式(20字节):

0x  E8   AB3C8200
    83F8 00
    0F8C DF000000
    0F84 0B000000

如果该序列在文件中是唯一的,那么如果您不能使用反汇编程序,则可以尝试将E8AB3C8200更改为B8FFFFFFFF

答案 1 :(得分:2)

最简单的方法可能是mov $-1, %eax代替通话。您可以通过将其放在.s文件中,编译它并转储结果来找出对应的字节,如果它比补丁位置短,则使用no​​ps填充。我得到“b8 ff ff ff ff”,这恰好适合。

您可以通过运行__TEXT并查找偏移来找到otool -l的开头。

答案 2 :(得分:1)

otxHex Fiend将是您的朋友。 otx将为您提供具有文件相对偏移的反汇编,Hex Fiend将允许您修改跳转。请记住,0x90是NOP的(x86)操作码,因此9090909090是fork()调用的合适替代品。 (请记住,它不会产生返回值,所以奇怪的东西最终可能会出现在eax中。)