为什么C变量的内存地址没有固定?

时间:2015-05-12 11:53:17

标签: c linux unix operating-system

我是刚学过虚拟记忆的本科CS学生。我做了一个以下程序的实验。

#include<stdio.h>
int ready0; 
int main(void) {
  int ready;
  printf("ready0 at %p, ready at %p. \n", (void*)&ready0, (void*)&ready); 
} 

我认为既然程序只处理虚拟内存,程序看起来它应该是机器上运行的唯一进程。我还查看了反汇编的代码,它看起来非常具有确定性。因此,如果我多次运行程序,结果应该是相同的。但是,实验表明情况并非如此。为什么实验与我的预期不同?是什么原因导致每次运行程序时结果都不同?

如果您有兴趣,请参阅Mac OS X Yosemite上的几个实验结果。

$ ./sp
ready0 at 0x102b18018, ready at 0x7fff5d0e876c. 
$ ./sp
ready0 at 0x107c09018, ready at 0x7fff57ff776c. 
$ ./sp
ready0 at 0x10aa9c018, ready at 0x7fff5516476c. 
$ ./sp
ready0 at 0x10d56d018, ready at 0x7fff5269376c. 
$ ./sp
ready0 at 0x10da1c018, ready at 0x7fff521e476c. 
$ ./sp
ready0 at 0x109aff018, ready at 0x7fff5610176c. 
$ ./sp
ready0 at 0x107c31018, ready at 0x7fff57fcf76c. 
$ ./sp
ready0 at 0x10fab1018, ready at 0x7fff5014f76c. 

2 个答案:

答案 0 :(得分:3)

在过去,你通常是对的;入口main的堆栈指针经常是相同的(但它也取决于您的环境,请参阅environ(7) ...)。详细信息(特别针对Linux)在ABI规范&amp;在execve(2)系统调用中。你(和我的)ABI通常是AMD64 ABI

出于安全考虑,当前系统ASLR - 地址空间布局随机化 - (您可以在系统范围内禁用echo 0 > /proc/sys/kernel/randomize_va_space以root身份运行;这会打开一个安全漏洞)。因此,main入口处的堆栈指针有点随机。

提示:如果您使用gdb观察点,则可能需要禁用ASLR。

答案 1 :(得分:2)

由于地址空间布局随机化。

来自维基:

*

  

地址空间布局随机化(ASLR)是一种计算机安全性   涉及随机排列关键数据位置的方法   区域,通常包括可执行文件的基础和位置   进程的地址空间中的库,堆和堆栈。

优势

  

地址空间随机化阻碍了某些类型的安全攻击   使攻击者更难以预测目标地址。   例如,试图执行返回libc攻击的攻击者必须   找到要执行的代码,而其他攻击者试图   执行堆栈注入的shellcode必须先找到堆栈。   在这两种情况下,相关的内存地址都会被隐藏起来   攻击者。必须猜测这些值,并且错误的猜测是   由于应用程序崩溃,通常无法恢复。

*