4

我正在努力将地址映射到它们的符号以进行调试(获取调用堆栈)。MS dbghelp.dll 可以从地址中分辨出符号(请参阅SymFromAddrMSDN)。但是,它不起作用,我想知道这怎么可能起作用,因为地址似乎随着程序的每次运行而改变:

#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:\dev\Sandbox\Debug>Sandbox.exe
Address: 901320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: ce1320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: 3a1320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: 3f1320

不同的程序怎么会像从堆栈跟踪中读取地址并将其映射到函数?这对我来说听起来很神奇。我在链接的文档中没有找到任何内容说我必须从地址或其他内容中减去一些内容。

据我了解,因为我们克服了实模式,所以每个进程都有一个虚拟内存空间,所以不再需要为加载地址掷骰子了。如果是 DLL,我会理解绝对地址的不确定性,但不是主要的可执行文件。

用VS2008在Win7上试过。

4

4 回答 4

6

地址空间布局随机化

于 2013-04-25T12:18:39.523 回答
3

因为您的代码被编译为使用地址空间布局随机化,这使得代码不太容易受到“StackOverflows”的攻击。

如果你真的想改变它,有一个链接器选项

于 2013-04-25T12:19:47.900 回答
3

有一个安全功能可以随机化一些地址,因此潜在的攻击者无法利用已知的固定相对位置。

于 2013-04-25T12:19:58.130 回答
2

正如其他人已经提到的那样,它是ASLR在行动。

看起来您需要做的是在调用SymLoadModuleEx(). 是BaseOfDll参数。

我不知道它到底存储在故障转储中的什么位置(如果这是其他程序必须使用的东西),但是正在运行的程序可以使用GetModuleHandle()(在此处讨论)获取它自己的图像基地址。

您可能还想保存加载到进程中的所有 DLL 的名称和基地址,而不仅仅是 EXE 本身的名称和基地址。

于 2013-04-25T12:46:36.450 回答