【问题标题】:Why is the address of a function different on each execution? [duplicate]为什么每次执行时函数的地址都不同? [复制]
【发布时间】:2020-01-10 14:01:55
【问题描述】:

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

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

示例输出 #1:

0x563ac3667139

示例输出 #2:

0x55e3903a9139

【问题讨论】:

  • ASLR.
  • 严格来说,代码会引发 UB,因为 p 转换说明符仅用于 void 指针(至少在 C 中)。所以任何数字都可能被打印出来。
  • @alk 您当然可以在printf() 中对 (void *) 执行显式强制转换,然后它就不再是 UB。但仍有可能打印出任何数字……现在,这是什么意思?
  • @Ctx:仍然是 C++ 中的 UB。取不到main的地址。
  • @LightnessRacesBY-SA3.0 在 C++ 中这是无可争辩的,正确的

标签: c++ c


【解决方案1】:

在许多现代系统上,在链接时它将确定函数相对于基地址模块的地址。当模块(exe、dll 等)被加载时,Address Space Layout Randomization (ASLR) 给它一个不同的基地址。

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

重定位基地址的能力也解决了冲突的实际问题,如果你加载为同一个基地址独立编译的a.dll和b.dll,那将不起作用,所以能够重定位一个人解决了冲突。

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

另见Relocation (computing)

【讨论】:

    【解决方案2】:

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

    它会在每次执行时故意移动东西,使攻击者更难知道数据位在您的进程中的位置并破解它们。

    【讨论】:

    • 不是加载位置的地址吗?到目前为止,我认为这是程序安装的真实地址?
    • @TruthSeeker 此方法仅在引入 ̵C̵h̵e̵e̵s̵e̵c̵a̵k̵e̵ PIE(位置无关的可执行文件)后才有效。使用标志-no-pie,这将在固定位置加载主二进制文件,main() 的地址将不再变化。
    猜你喜欢
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    相关资源
    最近更新 更多