8

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

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

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

+1

Вероятно, зависит от платформы .... – skaffman

+0

Хорошо, это Linux, скомпилированный с помощью GCC. – Luciano

ответ

1

Чтобы следить, вот что я придумал, наконец:

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

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

4

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

Для сравнения двух двоичных файлов (в ELF format) можно использовать исполняемый файл «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 

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

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

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

-1

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

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

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

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