简体   繁体   English

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

[英]Why aren't memory addresses of C variables fixed?

I'm an undergraduate CS student who just learned about virtual memory. 我是一名CS本科生,刚刚了解虚拟内存。 I did an experiment with the following program. 我对以下程序进行了实验。

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

I think that since the program only deals with virtual memory, it should seem to the program that it is the only process running on the machine. 我认为,由于该程序仅处理虚拟内存,因此在程序看来,它是计算机上唯一运行的进程。 I also looked at the disassembled code, which looks very deterministic. 我还看了看反汇编的代码,它看起来很确定。 Thus, if I run the program for many times, the result should be identical. 因此,如果我多次运行该程序,结果应该是相同的。 However, experiments show that this is not the case. 但是,实验表明事实并非如此。 Why do the experiments differ from what I expected? 为什么实验与我预期的不同? What caused the results to differ each time I run the program? 是什么导致每次我运行该程序时结果都不同?

If you're interested, here's several experiment results on Mac OS X Yosemite. 如果您有兴趣,这里是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. 

In the old days you would usually have been right; 在过去,您通常是对的。 the stack pointer at entry to main would often have been the same (but it also depends upon your environment, see environ(7) ...). 指向main入口的堆栈指针通常是相同的(但它也取决于您的环境,请参见environ(7) ...)。 Details are given (for Linux notably) in your ABI spec & in execve(2) syscall. 在您的ABI规范和execve(2) syscall中提供了详细信息(尤其是Linux Your (and mine) ABI is often AMD64 ABI . 您(和我的)ABI通常是AMD64 ABI

Current systems have, for security purposes, ASLR - address space layout randomization - (which you could disable system-wide with echo 0 > /proc/sys/kernel/randomize_va_space to be run as root; this opens a security hole) . 为了安全起见,当前系统具有ASLR (地址空间布局随机化)((您可以通过echo 0 > /proc/sys/kernel/randomize_va_space禁用系统范围的root用户运行权限;这会打开一个安全漏洞)。 So the stack pointer at entry to main is a bit random. 因此,进入main的堆栈指针有点随机。

Hint: you might want to disable ASLR if you use gdb watchpoints. 提示:如果使用gdb监视点,则可能要禁用ASLR。

It's due to address space layout randomization. 这是由于地址空间布局随机化。

From Wiki: 从Wiki:

* *

Address space layout randomization (ASLR) is a computer security method which involves randomly arranging the positions of key data areas, usually including the base of the executable and position of libraries, heap, and stack, in a process's address space. 地址空间布局随机化(ASLR)是一种计算机安全方法,它涉及在进程的地址空间中随机安排关键数据区域的位置,通常包括可执行文件的基础以及库,堆和堆栈的位置。

Benefits 好处

Address space randomization hinders some types of security attacks by making it more difficult for an attacker to predict target addresses. 地址空间随机化使攻击者更难预测目标地址,从而阻碍了某些类型的安全攻击。 For example, attackers trying to execute return-to-libc attacks must locate the code to be executed, while other attackers trying to execute shellcode injected on the stack have to find the stack first. 例如,尝试执行返回libc攻击的攻击者必须找到要执行的代码,而其他尝试执行注入到堆栈中的shellcode的其他攻击者则必须先找到堆栈。 In both cases, the related memory addresses are obscured from the attackers. 在这两种情况下,相关的内存地址都会被攻击者遮盖。 These values have to be guessed, and a mistaken guess is not usually recoverable due to the application crashing. 必须猜测这些值,并且由于应用程序崩溃,通常无法恢复错误的猜测。

* *

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM