【问题标题】:Why aren't memory addresses of C variables fixed?为什么 C 变量的内存地址不固定?
【发布时间】:2015-05-12 11:53:16
【问题描述】:

我是一名 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. 

【问题讨论】:

  • 你能发布结果吗?对我来说,它每次都显示相同的地址。 ready0ready 或两者的地址是否不同?它们不在同一个存储区域。
  • 没有法律规定地址必须相同。使用什么地址将受到过程中之前发生的事情的强烈影响。此外,分配给流程的段可能因流程的一个实例而异。
  • 我更新了,是的,它们都不同。

标签: c linux unix operating-system


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    来自维基:

    *

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

    好处

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

    *

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多