我知道在 ELF 程序的整个执行过程中保持 GOT 可写是一个明显的攻击面,并且了解决定通过默认为 -z relro
和有时
-z now
来避免它(在编译器级别?发行版级别?不确定)。
我不明白的是,为什么我们仍然费心建立复杂的 PLT 结构来为延迟绑定做准备,然后在加载时完全填充它。默认为 -no-plt
不是更好吗?我缺少一些权衡吗?
-fno-plt
在 GCC 中默认不使用,因为它禁用了任何延迟绑定的可能性。不将其保留为默认值,可以让开发人员在需要时明确且知情地选择它作为选项。
即使使用了
-z relro
和
-z now
的链接时选项,仍然可以在运行时使用环境变量
LD_BIND_NOT
来修改
ld.so
的行为。这很有用,如此处记录的那样,可与
LD_DEBUG
结合使用进行调试和故障排除。但只有当 PLT 条目仍然存在时,这才有效。此外,这里还提供了需要 PLT 才能合理运行的 GNU 间接函数的参考。如果没有 PLT,GNU 间接函数
需要 TEXTRELs,这被认为是倒退。 GNU 间接函数在 glibc 中使用,例如用于增强运行时性能优化。 PLT 确实有很多用途,因此它可能是首选,而不是默认被踢出。即使不使用,拥有 PLT 条目确实有其优点。
此链接
作为对不同平台的一些讨论,包括对-fno-plt
的支持,以及一些使其成为默认平台的讨论,并提到了优点和缺点。