为什么ASLR似乎不起作用
我检查了ASLR是否启用,如下所示:
I checked if ASLR is enabled as follows and I think it is:
[user@localhost test]$ cat /proc/sys/kernel/randomize_va_space
2
我尝试使用以下程序对其进行测试:
I tried testing it with the following program:
test.c :
#include <stdio.h>
int main(void)
{
printf("%p\n", main);
return 1;
}
我希望,如果ASLR处于活动状态,则每次运行都应使用不同的地址,对吗?但是我每次都一样.我测试了64位和32位可执行文件.我正在使用64位Arch Linux系统对此进行测试:
I expected, if ASLR is active, to a different address for each run, right? But I got the same each time. I tested both for 64bit and 32bit executables. I am using a 64bit Arch Linux system to test this:
[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已关闭吗?
As you can see, the address is the same for every run. Doesn't this mean that ASLR is off?
您的可执行文件必须与位置无关,以允许这样做.
Your executable must be position-independent to allow that.
gcc -pie -fPIE -o test test.c
尝试以这种方式运行它,每次运行时地址都应该明显改变.
Try running it this way, the address should visibly change on each run.
非PI可执行文件应加载到存储在其ELF标头中的固定的,明确的非随机地址处.这种假设允许编译器和链接器将绝对地址硬编码到输出中,从而使某些目标上的地址更小,更快.
Non-PI executables are meant to be loaded at a fixed, explicitly non-random address stored in their ELF header. This assumption allows compiler and linker to hard-code absolute addresses into the output, making it smaller and faster on some targets.
在其他任何地址加载非PI可执行文件都会使所有这些绝对引用无效,从而导致SIGSEGV处于最佳状态,而某些随机代码处于最坏状态.不能安全地将 main
的地址随机化,因为允许编译器假定不会,因此即使启用了ASLR,也永远不会这样做.
Loading non-PI executables at any other address invalidates all those absolute references, resulting in SIGSEGV at best and some random code running at worst. The address of main
can't be randomized safely because the compiler was allowed to assume that it won't be, so it's never done even if ASLR is enabled.
为了允许随机化,必须告诉编译器生成位置无关代码(-fPIE
),并且生成的可执行文件必须标记为位置无关(-pie
)>),以便内核知道可以安全地加载到任何地址.
To allow randomization, the compiler must be told to generate position-independent code (-fPIE
), and the resulting executable must be marked as position-independent (-pie
) so that the kernel would know it's safe to load at any address.
要实现哪些选项取决于很大程度上取决于工具链配置, -fpie
, -fPIE
, -fpic
,-fPIC
,某些默认情况下可能会生成PI代码.安全的选择是使用 -fPIE
进行编译,并使用 -pie -fPIE
进行链接.
Which options are necessary to achieve that depends a lot on toolchain configuration, -fpie
, -fPIE
, -fpic
, -fPIC
, some may generate PI code by default. The safe bet is to compile with -fPIE
and link with -pie -fPIE
.