【问题标题】:How to modify an ELF file in a way that changes data length of parts of the file?如何以更改文件部分数据长度的方式修改 ELF 文件?
【发布时间】:2015-04-26 19:31:50
【问题描述】:

我正在尝试修改我自己的 ELF 文件的可执行内容,看看是否可行。我编写了一个程序,它读取和解析 ELF 文件,搜索它应该更新的代码,对其进行更改,然后在更新节标题中的 sh_size 字段后将其写回。

但是,这不起作用。如果我只是用其他字节交换一些字节,它就可以工作。但是,如果我更改大小,它会失败。我知道一些 sh_offsets 是直接相邻的;但是,当我减小可执行代码的大小时,这并不重要。

当然,我的程序中可能存在错误(或多个),但我已经煞费苦心地解决了。

除了寻求帮助来调试我的程序之外,我只是想知道,除了 sh_size 字段之外,我还需要更新以使其工作(减小大小时)吗?除了那个字段,还有什么会导致更改长度失败的吗?

编辑:

看来安迪·罗斯是完全正确的。即使在这个非常简单的程序中,我也遇到了 __libc_start_main 中的一些间接寻址,我无法通过简单的修改来更新它将达到的偏移量。

不过,我很好奇,要尽可能解决这个问题,最好的方法是什么?我知道我不能在每种情况下都解决这个问题,但是对于一些简单的程序,应该可以更新使其运行所需的内容?我应该尝试编写自己的虚拟机还是尝试开发一个“调试器”,用 INT 3 替换每个可疑的问题指令?有什么想法吗?

【问题讨论】:

  • 它是什么ELF文件?你是怎么制作的?它是动态链接的还是静态链接的可执行文件,还是某个共享对象?见stackoverflow.com/a/12551737/841108
  • ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接(使用共享库),未剥离

标签: linux elf


【解决方案1】:

文本段可能在内部与相对偏移量相关联。所以一个函数可能试图跳转到,比如说,“当前地址加上 194 个字节”。如果你移动东西使得跳转目标现在是 190 字节,你显然会破坏东西。某些架构上的常量数据也是如此(例如 x86-64 但不是 i686)。要知道内部引用在哪里,没有简单的方法可以完全反汇编,事实上,要找到它们在计算上是不可确定的(即,试图找出运行时计算分支的所有可能的跳转目标是停止问题)。

基本上,这在一般情况下是无法解决的,因此如果您尝试修补来自其他人的 ELF 二进制文件,则需要尝试其他技术。但是(非常好!)小心,可以生成一个库,其中所有内部引用都通过 GOT/PLT,可以像这样分割和重新链接。你想完成什么?

【讨论】:

  • 解决方法是:如果它缩小,则用 nops 填充;如果它增长,则通过调用替换并将真实代码放在其他地方;并希望没有人跳到代码修改部分的中间。
  • 啊,当然。感谢您的输入。实际上,我只是在一个简单的 hello world 程序上执行此操作;我不会想到它会弄乱初始化代码中的一些相对偏移量或类似的东西。我遇到了一个错误: __libc_csu_init () => 0x00000000004005f0 <__libc_csu_init> 中的 0x00000000004005f0: 6c ins BYTE PTR es:[rdi],dx 我看不出任何可能在 main 之前的相对偏移量会如何受到影响main 的大小?
【解决方案2】:

除了我需要更新的 sh_size 字段之外,还有什么其他的东西需要更新才能完成这项工作

听起来您正在修补一个完全链接的二进制文件(ET_EXECET_DYN)。请注意,在静态链接完成后,.sh_size用于任何事情。您可以剥离整个节表,二进制文件将继续正常工作。运行时重要的是 ELF 中的 segments,而不是 sections

ELF代表executablelinking格式,executablelinking形成“双重性质”精灵。部分在(静态)链接时间用于组合成段;在执行时使用(又名运行时,又名动态链接时)。

当然,您还没有确切地告诉我们,当您缩小二进制文件时,您的修补策略是什么,以及结果以何种方式被破坏。安迪·罗斯的回答很可能是你断线的真正原因。

【讨论】:

    猜你喜欢
    • 2013-03-29
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    相关资源
    最近更新 更多