【问题标题】:How can I determine the location of disassembled code within an executable?如何确定可执行文件中反汇编代码的位置?
【发布时间】:2010-12-11 12:05:01
【问题描述】:

我有一个包含错误的可执行文件(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,而是无条件地跳转到失败情况(即它应该像 fork() 返回 -1 )

不幸的是,我是反汇编/二进制补丁的新手,所以我不知道如何去做。特别是,我的问题是:

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

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

感谢您提供的任何建议!

【问题讨论】:

    标签: assembly executable patch otool


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      otxHex Fiend 将成为您的朋友。 otx 会给你一个带有文件相对偏移量的反汇编,Hex Fiend 会让你修补跳转。请记住,0x90 是 NOP 的 (x86) 操作码,因此 9090909090 是 fork() 调用的合适替代品。 (请记住,它不会生成返回值,因此 eax 中可能会出现一些奇怪的东西。)

      【讨论】:

        【解决方案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,如果您不能使用反汇编程序。

        【讨论】:

        • @Jeremy Friesner,我很高兴能帮上忙 :)
        • 老帖子,但只有一件事,jll和jle中显示的地址是绝对的,不是相对的,相对的就是操作数本身。例如jll跳转到它的地址加上0xDB(不是0xDF,跳转是相对于下一条指令的地址),也就是0x0002cf02。这些地址在文件内,据我所知,没有 jmp 和 call 永远不会落在文件之外(它可以转到 __TEXT 段的其他部分,但永远不会超出它)。
        猜你喜欢
        • 2020-07-09
        • 1970-01-01
        • 2019-09-18
        • 1970-01-01
        • 2014-08-05
        • 1970-01-01
        • 2012-09-02
        • 1970-01-01
        • 2012-10-23
        相关资源
        最近更新 更多