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

时间:2021-07-21 03:11:13

I'm an undergraduate CS student who just learned about virtual memory. I did an experiment with the following program.

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

#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. 

2 个解决方案

#1


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)...). Details are given (for Linux notably) in your ABI spec & in execve(2) syscall. Your (and mine) ABI is often AMD64 ABI.

在过去,你通常是对的;进入main的堆栈指针通常是相同的(但它也取决于您的环境,请参阅environ(7)...)。在您的ABI规范和execve(2)系统调用中给出了详细信息(特别是Linux)。您(和我的)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) . So the stack pointer at entry to main is a bit random.

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

Hint: you might want to disable ASLR if you use gdb watchpoints.

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

#2


It's due to address space layout randomization.

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

From 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. 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.

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

*

#1


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)...). Details are given (for Linux notably) in your ABI spec & in execve(2) syscall. Your (and mine) ABI is often AMD64 ABI.

在过去,你通常是对的;进入main的堆栈指针通常是相同的(但它也取决于您的环境,请参阅environ(7)...)。在您的ABI规范和execve(2)系统调用中给出了详细信息(特别是Linux)。您(和我的)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) . So the stack pointer at entry to main is a bit random.

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

Hint: you might want to disable ASLR if you use gdb watchpoints.

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

#2


It's due to address space layout randomization.

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

From 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. 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.

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

*