Как лучше всего сравнить два скомпилированных двоичных файла?

Недавно я обнаружил отличное расширение Visual Studio, которое находит ненужные операторы #include в проектах и ​​удаляет их. Я работаю над каким-то грубым устаревшим кодом, и он очень сильно удален. Единственная проблема в том, что я не могу быть уверен, что это не изменило сборку каким-то тонким образом. Мне приходит в голову, что проект все еще может быть построен, но #define где-то можно было изменить.

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

Идеи на данный момент:

  1. Разберите все двоичные файлы и сравните разборку с diff. (Хотя, я думаю, это не касается разделов данных).
  2. Используйте какую-то двоичную программу сравнения, которая знает о заголовках PE.

Любые идеи? А кто-нибудь знает инструмент, который понимает заголовки PE, как я описываю?

«А кто-нибудь знает хорошую двоичную программу сравнения, такую ​​как я описываю?» При почти 20 тысячах репутации вы должны понимать, что здесь вы находитесь в опасной близости от не по теме. :)
HolyBlackCat 08.11.2018 20:58

Да, думаю, это правда. Но это вопрос, на который, скорее всего, знают ответ только коллеги-программисты.

Benj 08.11.2018 21:00
при проверке двоичных файлов не было внесено никаких важных изменений Учитывая, что вы изменили грубый устаревший код, и он лишен огромного количества, вы внесли значительные изменения. Какое тестирование вы проводите? Потому что сейчас вам нужно переделать ВСЕ.
Andrew Henle 08.11.2018 21:00

@Andrew Я делаю это в начале графика проекта, поэтому он будет регрессировать. Насколько я понимаю, это технический долг. Кроме того, если можно показать, что двоичные файлы идентичны по функциям, я счастлив на этом этапе проекта.

Benj 08.11.2018 21:01

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

Ajay Brahmakshatriya 08.11.2018 21:08

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

Serge 08.11.2018 21:09

@AjayBrahmakshatriya Правда? Я никогда не слышал этого раньше. Мне даже больше интересно попробовать идею дизассемблера сейчас ...

Benj 08.11.2018 21:10

Компиляторы @Benj используют наборы, карты и многие другие структуры данных. Поведение многих из них не дает гарантий заказа. Я не могу предоставить вам пример того же источника, генерирующего разные двоичные файлы, но я твердо верю, что это происходит.

Ajay Brahmakshatriya 08.11.2018 21:12

@AjayBrahmakshatriya Возможно, вы правы, и в этом случае этот подход не сработает. Я собираюсь попробовать разобрать, чтобы вы знали, как это происходит.

Benj 08.11.2018 21:15

@Benj, вы можете прочитать обсуждение это. OP в этом вопросе опубликовал пример, в котором они получают другой результат. Также предоставили сборочный дамп.

Ajay Brahmakshatriya 08.11.2018 21:16

Вам не нужно дизассемблировать двоичный файл, вы можете сгенерировать сборку, используя опцию -S в gcc и clang. Я помню, что у cl есть флаг /FA. Однако будьте осторожны с номерами строк и другой отладочной информацией. Вы можете удалить его из вывода, чтобы сохранить только инструкции.

Ajay Brahmakshatriya 08.11.2018 21:18

@AjayBrahmakshatriya Это хорошая идея, я должен был подумать об этом.

Benj 08.11.2018 22:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
12
513
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Заголовок PE всегда находится в одном и том же месте и имеет размер только до 512 байт (точно). так что просто отсеките первые 512 байт и сравните результаты.

Я пропускаю их через xxd для преобразования файлов в шестнадцатеричный формат, затем сравниваю полученные текстовые файлы (подойдет любая программа сравнения текста, но для получения xxd вам понадобится командная строка git).

xxd -p -c 4 < Truncatedfile1.exe > output.diff1

или

tail -n -512 < File1.exe | xxd -p -c 4 > output1.hex
tail -n -512 < File2.exe | xxd -p -c 4 > output2.hex
git diff --no-index --color output1.hex output2.hex 

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

Спасибо! Похоже, этот метод сработал для вас? Некоторые в комментариях говорят, что компиляторы слишком недетерминированы, чтобы эта идея сработала.

Benj 08.11.2018 21:58

Что ж, я редактирую двоичные файлы с помощью автоматизированных материалов в двоичном масштабе, и как тестировщик программного обеспечения у меня есть некоторый опыт в проверке различий. Я просто подумал о том, как можно различать разделы данных, и вспомнил, что они обычно выровнены по двойному слову, поэтому я подумал, что xxd с 4 байтами на строку будет хорошей идеей также для перекомпилированных программ.

Ohnemichel 08.11.2018 22:13

Другие вопросы по теме