当linux有execve()
一个ELF时,它会将该ELF映射到进程的内存空间中,并从入口点开始运行代码。但是内核是如何决定ELF的加载地址和入口点的呢?
如果禁用 ASLR,它将查找.p_vaddr
每个 PT_LOAD 段并使用.e_entry
ELF 标头作为入口点。
但是如果启用 ASLR 会怎样呢?内核是否会简单地向上述所有内容添加随机移位,但保持它们的相对位置?
ELF的内容会影响内核的行为吗?就像.p_vaddr
PT_LOAD 段的最小值是零还是非零?比如.e_type
ELF header是ET_DYN还是ET_EXEC?
我特别谈论的是 x86_64。
我创建了一个简单的 C 程序,每次在 GDB 中加载它时,我都会看到分配给程序指令的相同内存地址。例如,一个函数what()
总是在内存位置 0x000055555555472d 加载。实际上,每次执行的堆栈都完全相同(不仅是堆栈的内容,还包括 rsp 指向的内存地址。
我知道可以通过将“/proc/sys/kernel/randomize_va_space”设置为 0 在 Linux 中禁用 ASLR,但我的 Debian 系统中的值为 2。
root@Sierra ~ % cat /proc/sys/kernel/randomize_va_space
2
Run Code Online (Sandbox Code Playgroud)
根据我对 ASLR 的理解,这些地址应该在每次运行时随机化。我的问题是为什么会发生这种情况?我做错了什么吗?