在问我的问题之前,我想介绍一些我想确保我得到正确的技术细节:
与位置无关的可执行文件 (PIE) 是一个无论加载到哪个内存地址都能够执行的程序,对吧?
ASLR(地址空间布局随机化)几乎指出,为了保持地址静态,我们会以某种方式随机化它们,
我已经读过,特别是在基于 Linux 和 Unix 的系统中,实现 ASLR 是可能的,无论我们的代码是否是 PIE,如果它是 PIE,所有跳转、调用和偏移都是相对的,因此我们没有问题。如果不是,无论代码是可执行文件还是共享对象,代码都会以某种方式被修改并编辑地址。
现在这让我问几个问题
如果 ASLR 可以在不是 PIE 并且是可执行文件且不是共享/可重定位对象的代码中实现(我知道重定位如何在可重定位对象中工作!!!!),它是如何完成的?ELF 格式不应该包含任何部分来说明代码部分中函数的位置,以便内核加载程序可以修改它,对吗?ASLR 应该是一个内核功能,例如,一个包含例如这些指令的可执行文件。
伪代码:
inc_eax: add eax, 5 ret main: mov eax, 5 mov ebx, 6 call ABSOLUTE_ADDRES{inc_eax}
如果它们没有存储在 ELF 文件中的某个可重定位表中并且不是相对的以便将可执行文件加载到某个随机地址中,那么内核可执行加载程序如何知道如何更改地址?
假设我错了,为了实现 ASLR,你必须有一个 PIE 可执行文件。所有段都是相对的。如何编译 C++ OOP 代码并使其工作,例如,如果我有一个类的某个实例使用指向其结构中的虚拟表的指针,并且该虚拟表应该保存绝对地址,因此我不会能够为使用运行时虚拟表的 C++ 程序编译纯 PIE,并且 ASLR 再次是不可能的......我怀疑虚拟表将包含相对地址,并且每次调用都会有一个不同的虚拟表一些虚函数...
我最后一个也是最不重要的问题是关于 ELF 和 PIE - 是否有一些特殊的方法来检测 ELF 可执行文件是 PIE?我熟悉 ELF 格式,所以我怀疑有没有办法,但我可能错了。无论如何,如果没有办法,内核加载程序如何知道我们的可执行文件是否是 PIE,因此它可以在其上使用 ASLR。
我把这一切都搞砸了,如果有人能在这里帮助我,我会很高兴的。