it-roy-ru.com

Как проверить, выполняется ли исполняемый файл или DLL в режиме выпуска или отладки (C ++)

Мне нужно найти режим exe/dll был собран, глядя на его заголовки. [edit] Использование c ++ только без каких-либо внешних инструментов. [/ edit]

Существует старая дискуссия о том, как определить, была ли dll встроена в режим Release или Debug. http://forums.codeguru.com/archive/index.php/t-485996.html

Но, к сожалению, я не нашел четкого ответа.

11
ChatCloud

Мне нужно найти режим exe/dll был собран, глядя на его заголовки.

Если под "заголовками" вы подразумеваете PE-разделы или ресурсы (заголовки не сообщают вам ничего, а программы обычно не поставляются со своими заголовками разработки!), Это вид возможно, в определенных пределах и ненадежно. В противном случае, это совершенно невозможно, если вы сами не написали программу.

Как правило, это трудно сделать надежным способом, тем более, что "отладочная сборка" - это упрощение Microsoft Visual Studio, которое не существует как таковое в большинстве компиляторов. Например, с GCC вполне допустимо иметь оптимизированную сборку , которая, тем не менее, содержит символы отладки. Можно даже включать и выключать оптимизацию с помощью #pragma (и изменять уровень оптимизации и даже целевой компьютер!) И, таким образом, иметь оптимизированные функции (или группы функций) в неоптимизированной сборке, и наоборот.

Наличие отладочных символов - ваша лучшая догадка для программы, которую вы не написали. В любом случае невозможно (не реально, простым, автоматическим способом) определить из сгенерированного двоичного файла, был ли он оптимизирован или нет.

Разделы .debug$S и .debug$T содержат символы отладки и типы отладки соответственно. Есть и другие разделы, начинающиеся с .debug, но они устарели. Программа, которая была построена в "режиме отладки" и которая впоследствии не была удалена, будет содержать некоторые или все эти разделы.
Используя C++ без внешних инструментов, вы можете пропустить заглушку DOS "MZ" и заголовок PE. После этого идут заголовки разделов, которые вы можете проанализировать. Полная документация формата файла может быть загружена здесь .
Скорее всего, чтение файла и сопоставление строк для .debug будет таким же хорошим.

Точно так же вы можете посмотреть VERSIONINFO или файл манифеста (они также позволяют указать, является ли программа отладочной сборкой), но это не обязательно. Вы можете написать почти все, что вы хотите в них. Поскольку они даже менее надежны, чем поиск отладочных символов.

Еще один намек, опять же ненадежный, заключается в проверке того, с какими версиями системных библиотек связана программа. Если это отладочная версия, скорее всего, это была отладочная версия. Однако можно сделать сборку релиза и по-прежнему связываться с отладочными библиотеками, ничто не может помешать вам сделать это.

Следующим лучшим предположением будет отсутствие вызовов функции CRT assert (что можно сделать с простым совпадением строк), поскольку макрос assert (из которого он обычно вызывается) полностью удаляется в сборке с определенным NDEBUG. Нет использования этого символа, нет строки в двоичном коде.
К несчастью, программа, которая не имеет каких-либо утверждений, будет ошибочно идентифицирована как "сборка выпуска" независимо от ее фактической сборки, и вполне возможно переопределить макрос assert, чтобы сделать что-то совершенно другое (например, printf текст и продолжить). И, наконец, вы не знаете, содержит ли статическая сторонняя библиотека, с которой вы связываетесь (которая, очевидно, уже прошла препроцессор), вызовы assert, о которых вы не знаете.

Если вы хотите проверить программу, которую вы написали сами, вы можете использовать тот факт, что оптимизатор полностью удалит вещи, которые доказуемо недоступны или не используются. Может потребоваться 2-3 попытки, чтобы сделать это правильно, но в основном это должно быть так же просто, как определить переменную (или экспортированную функцию, если ваш компилятор/компоновщик не экспортирует символы, которые не используются) и записать два или три волшебные значения для него из местоположения программы, которое недоступно. Оптимизирующий компилятор, по крайней мере, свернет эти несколько избыточных ходов в один или, скорее, полностью уничтожит их все.
Затем вы можете просто выполнить поиск двоичных строк для магических значений. Если их нет, это оптимизированная сборка.

7
Damon

Вопрос очень хороший, и, как уже говорилось, нет никаких явных (уникальных) индикаторов, которые бы указывали на то, отлажено ли изображение или выпущено.

Как объяснено здесь и здесь , наличие каталога отладки НЕ является показателем того, было ли изображение построено в режиме выпуска. Очень часто выпущенные образы создаются с поддержкой отладки. Фактически, почти ВСЕ файлы образов ОС Windows созданы с поддержкой отладки (в противном случае не было бы никакой возможности связать эти выпущенные изображения с файлами символов с сервера Microsoft Symbols). Даже если эти изображения являются изображениями выпуска!

Даже наличие раздела .debug (на самом деле, имена разделов НЕ играют роли в спецификации PE, имя раздела может быть изменено и установлено по вашему желанию - загрузчик не заботится об этом!) НЕ является Индикатор Release против Debug image.

1
mox

Есть старый реверсивный инструмент, который называется LordPE. Это позволит вам открыть два файла и различать заголовки. Я скомпилировал программу "Hello World" в VS2008 в режиме Release и Debug и сравнил их. Как и на других постерах, я не видел ничего, что могло бы служить индикатором.

Но в качестве индикатора я обнаружил заполнение в бинарном разделе .text. Существует более ста байтов со значением 0xCC после последнего байта кода в разделе .text в версии отладки. В версии Release не было байтов 0xCC. Байты 0xCC будут отображаться как int3 или точки останова в отладчике.

1
lynxjerm

Поскольку мне нужно было проверить сотни dll и exe, я попробовал предложение Смерлина, запустив зависящий от.exe файл (версия 2.2) в консольном режиме и выполнив поиск "MSVCRTD" в выходном файле, сгенерированном с помощью зависимости.

Process p = new Process();
dllWalkerPath = "\""+ dllWalkerPath + "\"";
binaryFilePath = Path.GetFullPath(binaryFilePath); //path to folder containing the dll's to be verified
string exePath = Assembly.GetEntryAssembly().Location;
string outputFilePath = Path.GetDirectoryName(exePath) + dependsOutputName;
p.StartInfo = new ProcessStartInfo(dllWalkerPath, @"/c /oc:" + outputFilePath + " " + binaryFilePath) //dllWalkerPath contains the path to depends.exe 2.2
{
    UseShellExecute = false
};
p.Start();
p.WaitForExit();
0
Martin

Когда вы создаете проект C++ в Visual Studio, он генерирует две конфигурации для вас. Имена этих конфигураций Debug и Release. Конфигурация отладки включает генерацию отладочной информации, меньше оптимизации и поддержку Edit & Continue.

Но это только отправная точка. Вы можете создавать произвольные конфигурации и даже добавлять всю отладочную информацию в конфигурацию выпуска. Так что нет четкой сборки Debug или Release.

Вы можете попытаться определить, был ли определен символ препроцессора _DEBUG. Это редко изменяется и используется в ресурсе версии. Бит 0 поля FILEFLAGES обычно указывает, что символы _DEBUG были определены при компиляции ресурса.

0
harper