为什么 ASLR 似乎不起作用

Why does ASLR not seem to be working

我检查了 ASLR 是否启用如下,我认为是:

[user@localhost test]$ cat /proc/sys/kernel/randomize_va_space
2

我尝试使用以下程序对其进行测试:

test.c:

#include <stdio.h>
int main(void)
{
    printf("%p\n", main);
    return 1;
}

我预计,如果 ASLR 处于活动状态,每个 运行 的地址不同,对吧?但我每次都一样。我测试了 64 位和 32 位可执行文件。我正在使用 64 位 Arch Linux 系统来测试这个:

[user@localhost test]$ gcc test.c -o test
[user@localhost test]$ ./test
0x4004c6
[user@localhost test]$ ./test
0x4004c6
[user@localhost test]$ ./test
0x4004c6
[user@localhost test]$ ./test
0x4004c6
[user@localhost test]$ gcc -m32 test.c -o test
[user@localhost test]$ ./test
0x80483eb
[user@localhost test]$ ./test
0x80483eb
[user@localhost test]$ ./test
0x80483eb
[user@localhost test]$ ./test
0x80483eb

如您所见,每个 运行 的地址都是相同的。这不是说 ASLR 关闭了吗?

您的可执行文件必须是 position-independent 才能允许。

gcc -pie -fPIE -o test test.c

试试 运行 以这种方式连接它,地址应该在每个 运行.

上明显改变

Non-PI 可执行文件应加载到存储在其 ELF header 中的固定、显式 non-random 地址。此假设允许编译器和 linker 将 hard-code 绝对地址输入到输出中,使其在某些目标上更小更快。

在任何其他地址加载 non-PI 可执行文件会使所有这些绝对引用无效,导致最好的 SIGSEGV 和一些随机代码 运行ning 最坏的。 main 的地址无法安全地随机化,因为允许编译器假定它不会,所以即使启用了 ASLR,它也永远不会完成。

要允许随机化,必须告知编译器生成 position-independent 代码 (-fPIE),并且生成的可执行文件必须标记为 position-independent (-pie)这样内核就会知道在任何地址加载都是安全的。

需要哪些选项来实现这在很大程度上取决于工具链配置,-fpie-fPIE-fpic-fPIC,有些可能会默认生成PI代码.安全的选择是使用 -fPIE 和 link 以及 -pie -fPIE.

进行编译