2013-04-25 2 views
3

Я борюсь с отображением адресов на их символы для целей отладки (получение вызова). MS dbghelp.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:\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 

Как мог другая программа когда-либо читать адрес, как из stacktrace и сопоставить его с функциями? Для меня это звучит как волшебство. Я не нашел ничего в связанной документации, в которой говорится, что мне нужно будет вычесть что-то из адреса или что-то еще.

В моем понимании, так как мы преодолеем реальный режим, каждый процесс имеет пространство виртуальной памяти, так что больше не нужно бросать кости для адреса загрузки. Я бы понял неопределенности абсолютного адреса в случае DLL, но не основного исполняемого файла.

Пробовал на Win7 с VS2008.

+0

Несколько ответов по этому вопросу, спасибо! Я был как WTF !!! Как, на самом деле, это дамп стека, полезный тогда с этой супер-MS-защитой через безвестность? ?! – Borph

+0

Потому что все отладчики могут иметь дело с модулями, загружаемыми в случайном порядке. DLL перемещаются все время. – MSalters

ответ

3

Потому что ваш код компилируются использовать Address Space Layout Рандомизацию, что делает код менее уязвимый для атак с «StackOverflows».

Если вы действительно хотите это изменить, для этого есть linker option.

2

Это ASLR в действии, как и другие уже упомянутые.

Похоже, что вам нужно указать базу изображений для вашего исполняемого файла при вызове SymLoadModuleEx(). Это параметр BaseOfDll.

Я не знаю, где именно он хранится в дампе аварийной ситуации (если это то, с чем должна работать другая программа), но работающая программа может получить свой собственный базовый адрес изображения, используя GetModuleHandle() (обсуждается here).

Возможно, вы захотите сохранить имена и базовые адреса всех DLL-файлов, загружаемых в этот процесс, а не только те из самого EXE.

+0

Да, спасибо! Я теперь вычитал базовый адрес в текущем коде, поэтому в файле журнала есть относительные адреса, и он сработал. GetModuleHandle() сделал трюк. В будущем я мог бы делать со всеми DLL, но позже. – Borph

Смежные вопросы