Сравнение сгенерированных исполняемых файлов на соответствие - PullRequest
8 голосов
/ 12 июля 2010

Мне нужно сравнить 2 исполняемых файла и / или общих объекта, скомпилированных с использованием одного и того же компилятора / флагов, и убедиться, что они не изменились. Мы работаем в регулируемой среде, поэтому было бы очень полезно для целей тестирования определить, какие именно части исполняемого файла изменились.

Использование MD5Sums / Hashes не работает из-за заголовков, содержащих информацию о файле.

Кто-нибудь знает о программе или способе проверки того, что 2 файла одинаково выполняются, даже если они были созданы в разное время?

Ответы [ 4 ]

4 голосов
/ 15 ноября 2011

интересный вопрос.У меня похожая проблема на Linux.Системы обнаружения вторжений, такие как OSSEC или tripwire, могут генерировать ложные срабатывания, если хэш-сумма исполняемого файла внезапно изменяется.Это может быть ничем не хуже, чем программа Linux «prelink», исправляющая исполняемый файл для более быстрого запуска.

Чтобы сравнить два двоичных файла (в формате ELF ), можно использовать "readelf "исполняемый файл" и затем "diff" для сравнения результатов.Я уверен, что есть изысканные решения, но без лишних слов, компаратор бедняков в Perl:

#!/usr/bin/perl -w

$exe = $ARGV[0];

if (!$exe) {
   die "Please give name of executable\n"
}
if (! -f $exe) {
   die "Executable $exe not found or not a file\n";
}
if (! (`file '$exe'` =~ /\bELF\b.*?\bexecutable\b/)) {
   die "file command says '$exe' is not an ELF executable\n";
}

# Identify sections in ELF

@lines = pipeIt("readelf --wide --section-headers '$exe'");

@sections = ();

for my $line (@lines) {
   if ($line =~ /^\s*\[\s*(\d+)\s*\]\s+(\S+)/) {
      my $secnum = $1;
      my $secnam = $2;
      print "Found section $1 named $2\n";
      push @sections, $secnam;
   }
}

# Dump file header

@lines = pipeIt("readelf --file-header --wide '$exe'");
print @lines;

# Dump all interesting section headers

@lines = pipeIt("readelf --all --wide '$exe'");
print @lines;

# Dump individual sections as hexdump

for my $section (@sections) {
   @lines = pipeIt("readelf --hex-dump='$section' --wide '$exe'");
   print @lines;
}

sub pipeIt {
   my($cmd) = @_;
   my $fh;
   open ($fh,"$cmd |") or die "Could not open pipe from command '$cmd': $!\n";
   my @lines = <$fh>;
   close $fh or die "Could not close pipe to command '$cmd': $!\n";
   return @lines;
}

Теперь вы можете запустить, например, на машине 1:

./checkexe.pl /usr/bin/curl > curl_machine1

И на компьютере 2:

./checkexe.pl /usr/bin/curl > curl_machine2

После копирования, SFTP-или NSF-файлов (вы не используете FTP, не так ли?) Файлы в одном файловом дереве, сравните файлы:

diff --side-by-side --width=200 curl_machine1 curl_machine2 | less

В моем случае различия существуют в разделе ".gnu.conflict", ".gnu.liblist", ".got.plt" и ".dynbss", что может быть хорошо для "предварительной ссылки"вмешательство, но в разделе кода, ".text", который будет плохим знаком.

1 голос
/ 11 февраля 2011

В заключение, вот что я наконец-то придумал:

Вместо сравнения конечных исполняемых файлов и общих объектов, мы сравнили выходные файлы .o перед компоновкой.Мы предполагали, что процесс компоновки был достаточно воспроизводимым, чтобы это было нормально.

Это работает в некоторых наших случаях, когда у нас есть две сборки, в которые мы внесли небольшое изменение, которое не должно повлиять на окончательный код(Code pretty-printer), но это не помогает нам, если у нас нет промежуточного результата сборки.

0 голосов
/ 26 сентября 2018

Вы можете сравнить содержимое инициализированных разделов RO и RW, сгенерировав двоичный файл из файла ELF.

objcopy <elf_file> -O binary <binary_file>

Использовать сгенерированные двоичные файлы для сравнения, если они идентичны, используя diff,например.

На мой взгляд, этого достаточно, чтобы предоставить вам тот же исполняемый файл.

0 голосов
/ 04 октября 2013

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

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

Я не помню все детали, но вам понадобятся следующие команды: {objcopy, objdump, nm}, я думаю objdump будет первым, кто попробует.

Надеюсь, это поможет.

...