我检查了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关闭了吗?
答案 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
链接。