我正在尝试修改自己的ELF文件的可执行内容,以查看是否可行。我编写了一个程序,该程序读取和解析ELF文件,搜索应更新的代码,对其进行更改,然后在更新节标题中的sh_size字段后将其写回。
但是,这不起作用。如果我只是简单地交换一些字节和其他字节,它就可以工作。但是,如果更改大小,它将失败。我知道有些sh_offsets彼此紧邻。但是,当我减小可执行代码的大小时,这无关紧要。
当然,我的程序中可能存在一个错误(或多个),但是我已经很努力地进行了研究。
除了寻求调试程序方面的帮助外,我只是想知道,除了sh_size字段之外,还有什么要更新才能使它起作用的(减小大小时)?除了该字段之外,还有什么会使长度更改失败的事情吗?
编辑:
看来安迪·罗斯(Andy Ross)完全正确。即使在这个非常简单的程序中,我也遇到了__libc_start_main中的一些间接寻址,我不能轻易修改这些间接寻址来更新它将达到的偏移量。
不过,我很好奇,什么是仍然设法尽可能解决这个问题的最佳方法?我知道我无法在所有情况下都解决此问题,但是对于某些简单程序,应该可以更新使其运行所需的内容?我应该尝试编写自己的虚拟机还是尝试开发一个“调试器”以将每个可疑问题指令替换为INT 3?有任何想法吗?
文本段可能在内部与相对偏移量关联。因此,一个功能可能试图跳转到“当前地址加194个字节”。如果您将内容移动到现在的跳转目标为190字节的位置,您显然会破坏内容。在某些体系结构(例如x86-64而不是i686)上,常量数据也是如此。没有一种简单的方法可以通过完全反汇编来了解内部引用在哪里,实际上,要找到它们全部都是计算上不确定的(即,试图找出运行时计算分支的所有可能的跳转目标都是“停顿问题”)。
基本上,这在一般情况下是无法解决的,因此,如果您要尝试打补丁的其他人提供了ELF二进制文件,则需要尝试其他技术。但是,只要(非常好!)小心,就有可能生成一个库,其中所有内部引用都通过GOT / PLT进行访问,可以像这样对它们进行切片和重新链接。你想达到什么目的?