只是出于好奇,我想知道是否可以在程序执行期间重新定位一段代码。例如,我有一个函数,每次执行后都应该在内存中替换该函数。我们想到的一个想法是使用自修改代码来做到这一点。根据一些在线资源,可以在Linux上执行自修改代码,但我仍然不确定这种动态重定位是否可能。有没有人有这方面的经验?
3 回答
是的,动态重定位绝对是可能的。但是,您必须确保代码是完全独立的,或者它通过绝对引用访问全局/外部函数。如果您的代码可以完全独立于位置,这意味着它所做的唯一引用是相对于自身的,那么您已经设置好了。否则,您将需要在加载时自己进行修复。
使用 GCC,您可以-fpic
用来生成与位置无关的代码。-q
将或传递--emit-relocs
给链接器将使其发出重定位信息。ELF 规范(PDF 链接)包含有关如何使用该重定位信息的信息;如果您不使用 ELF,则必须为您的格式找到适当的文档。
正如卡尔所说,这是可以做到的,但你正在打开一罐蠕虫。在实践中,唯一不厌其烦的人是学者或恶意软件作者(现在穿上我的防火斗篷)。
您可以将一些代码复制到 malloc 的堆区域中,然后通过函数指针调用它,但取决于操作系统,您可能必须在段中启用执行。您可以尝试将一些代码复制到代码段中(注意不要覆盖以下函数),但操作系统可能已将此段设为只读。您可能想查看 Linux 内核并了解它是如何加载其模块的。
如果所有这些不同的函数在编译时都存在,那么您可以简单地使用函数指针来跟踪要调用的下一个函数。如果您绝对必须在运行时修改函数并且无法就地进行修改,那么您还可以使用一个函数指针,该指针在创建/加载时使用新函数的地址进行更新。然后系统的其余部分将通过函数指针调用自修改函数,因此不必知道或关心自修改代码,您只需在一个地方进行修复。