【问题标题】:Why does the address of a variable keep changing between runs? [duplicate]为什么变量的地址在运行之间不断变化? [复制]
【发布时间】:2012-01-23 08:48:25
【问题描述】:

我制作了两个相互复制的 C 程序。
使用 GCC 编译器在 Linux 上编译它们并获得两个独立的可执行文件。
然后我使用objdump 检查了两者的汇编代码,发现指令是相同的。甚至两个文件中对应指令的地址都是一样的。

程序是打印其中一个变量的地址。

程序运行时产生不同的地址,而且同一个程序每次运行时产生不同的地址。

为什么两个程序的代码行地址相同,但同一个程序每次运行时变量的地址都会发生变化?

我怀疑屏幕上打印的地址可能是虚拟地址,但如果是虚拟地址,为什么每次都不能相同? objdump得到的汇编代码中显示的地址也是虚拟的吗?

【问题讨论】:

  • 在现代 CPU+操作系统中,几乎所有可见地址都是虚拟的。此外,地址不必相同,因为在大多数编程语言中都没有这样的要求。

标签: c memory-address


【解决方案1】:

这是由于address space layout randomization

引用维基百科:

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

好处

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

例如,当我在我的 Ubuntu 10.10 机器上重复运行由以下 C 代码生成的相同可执行文件时:

#include <stdio.h>

int g = 0;

int main() {
  int x = 0;
  printf("%p %p\n", &x, &g);
}

局部变量(x)的地址不断变化,但全局变量(g)的地址保持不变。

【讨论】:

  • 你能解释一下为什么全局变量的地址不变吗?当我们随机更改关键数据区域的地址时。这也会改变进程虚拟内存中“数据”部分的地址范围——其中包含这个全局变量。
【解决方案2】:

是的,您将始终在地址变量中获得更改的值。这是因为,当您在运行模式下编程时,当您执行变量声明语句时,每次控制器都会根据可用的内存位置创建变量。这是唯一的原因,每次它返回不同的地址值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多