为什么每次运行时函数的地址都会改变?
Why does the address of a function change with every run?
我正在努力将地址映射到它们的符号以进行调试(获取调用堆栈)。msdbghelp .dll可以从地址(参见SymFromAddr
, MSDN)中区分符号。然而,它不起作用,我想知道这是如何工作的,因为地址似乎随着程序的每次运行而改变:
#include <iostream>
void Foo() {}
int _tmain(int argc, _TCHAR* argv[])
{
const long unsigned int addr = reinterpret_cast<long unsigned int>(&Foo);
std::cout << "Address: " << std::hex << addr << std::endl;
return 0;
}
输出:D:devSandboxDebug>Sandbox.exe
Address: 901320
D:devSandboxDebug>Sandbox.exe
Address: ce1320
D:devSandboxDebug>Sandbox.exe
Address: 3a1320
D:devSandboxDebug>Sandbox.exe
Address: 3f1320
不同的程序怎么可能从堆栈跟踪中读取地址并将其映射到函数中呢?这听起来像魔法。我在链接的文档中没有发现任何东西说我必须从地址或其他东西中减去什么。
在我的理解中,因为我们克服了实模式,每个进程无论如何都有一个虚拟内存空间,所以不再需要为加载地址掷骰子了。我能理解dll中绝对地址的不确定性,但不能理解主可执行文件。
地址空间布局随机化
因为你的代码被编译为使用地址空间布局随机化,这使得代码不容易受到来自"StackOverflows"的攻击。
如果你真的想改变它,有一个链接器选项。
有一个安全特性可以随机化一些地址,因此潜在的攻击者无法利用已知的固定相对位置。
这是ASLR的作用,正如其他人已经提到的。
看起来您需要做的是在调用SymLoadModuleEx()
时为可执行文件指定映像库。是BaseOfDll
参数
我不知道它存储在崩溃转储中的确切位置(如果这是其他程序必须使用的东西),但是运行的程序可以使用GetModuleHandle()
(这里讨论)获得自己的映像基址。
您可能希望保存加载到进程中的所有dll的名称和基址,而不仅仅是EXE本身的名称和基址。
相关文章:
- 将数组的地址分配给变量并删除
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 变量没有改变?通过向量的函数调用
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 被解释为低级别const的const对象的地址
- 是否有保证堆分配的块地址不会改变(隐式)
- c++指针:在不改变地址的情况下改变内容
- 指针地址改变-函数
- 我的对象在矢量中的地址改变了
- 为什么每次运行时函数的地址都会改变?
- Reference_wrapper不会相应地改变地址
- 在另一个函数内部改变指针数组所包含的地址
- 链接列表中的指针地址不会改变
- 为什么这个地址在gdb中改变
- 根据信号和返回地址改变程序执行流程
- 动态数组改变内存地址位置
- 使用引用改变变量的地址