为什么ASLR似乎无法正常工作

时间:2016-08-07 20:08:06

标签: c linux aslr

我检查了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关闭了吗?

1 个答案:

答案 0 :(得分:7)

您的可执行文件必须与位置无关才允许这样做。

gcc -pie -fPIE -o test test.c

尝试以这种方式运行,每次运行时地址都应该明显改变。

非PI可执行文件应加载在存储在其ELF头中的固定的显式非随机地址中。这种假设允许编译器和链接器将绝对地址硬编码到输出中,使其在某些目标上更小更快。

在任何其他地址加载非PI可执行文件会使所有这些绝对引用无效,从而最多导致SIGSEGV和最差运行的一些随机代码。 main的地址不能安全随机化,因为允许编译器认为它不会,所以即使启用了ASLR也不会这样做。

要允许随机化,必须告诉编译器生成与位置无关的代码(-fPIE),并且必须将生成的可执行文件标记为位置无关(-pie),以便内核知道在任何地址加载都是安全的。

实现这一目标所需的选项很大程度上取决于工具链配置,-fpie-fPIE-fpic-fPIC,有些可能会默认生成PI代码。安全的选择是使用-fPIE进行编译并与-pie -fPIE链接。