为什么每次执行时函数的地址都不同?

时间:2020-01-10 14:01:55

标签: c++ c

可执行代码的地址是在链接时确定的,不是吗?

#include <stdio.h>
int main ()
{
     printf("%p", (void*)&main);
     return 0;
}

示例输出#1:

0x563ac3667139

示例输出2:

0x55e3903a9139

2 个答案:

答案 0 :(得分:19)

在许多现代系统上,它将在链接时确定相对于基址模块的功能地址。加载模块(exe,dll等)后,Address Space Layout Randomization (ASLR)为它提供一个不同的基地址。

这是出于安全考虑,这意味着功能的地址不可预测。这意味着某些攻击,例如可能溢出堆栈变量以覆盖返回地址或具有其他功能的函数指针(出于恶意目的),无法轻易预测要用其覆盖的地址,它会因运行而异

重定位基地址的能力还解决了冲突的实际问题,如果加载为同一基地址独立编译的a.dll和b.dll,将无法正常工作,因此能够重定位一个可以解决冲突。

在机器代码级别,这很好,因为大多数跳转和调用都使用相对指令偏移量,而不是绝对指令偏移量。尽管在加载模块时会动态修补某些构造,或使用某种形式的“表”填充正确的地址。

另请参阅Relocation (computing)

答案 1 :(得分:9)

这是一种称为address space layout randomization的安全技术。

它会在每次执行时故意移动内容,使攻击者更难知道进程中的数据位置并对其进行黑客攻击。