8

Ich muss 2 ausführbare Dateien und/oder gemeinsame Objekte vergleichen, kompiliert mit dem gleichen Compiler/Flags und verifizieren, dass sie nicht geändert haben. Wir arbeiten in einer regulierten Umgebung, daher wäre es für Testzwecke sehr nützlich, genau zu bestimmen, welche Teile der ausführbaren Datei sich geändert haben.Vergleichen von generierten ausführbaren Dateien für Äquivalenz

Die Verwendung von MD5Sums/Hashes funktioniert aufgrund der Header mit Informationen zur Datei nicht.

Kennt jemand ein Programm oder eine Methode, um zu überprüfen, dass 2 Dateien gleich sind, auch wenn sie zu einem anderen Zeitpunkt erstellt wurden?

+1

Wahrscheinlich hängt von der Plattform ab .... – skaffman

+0

Ok, es ist Linux mit GCC kompiliert. – Luciano

Antwort

1

zu verfolgen, hier ist das, was ich mit endlich kam:

Statt die endgültige ausführbare & gemeinsame Objekte zu vergleichen, verglichen wir die .o Ausgabedateien, bevor die Verknüpfung. Wir nahmen an, dass der Verknüpfungsprozess ausreichend reproduzierbar ist, dass dies in Ordnung wäre.

Es funktioniert in einigen unserer Fälle, wo wir zwei Builds haben, haben wir einige kleine Änderungen vorgenommen, die den endgültigen Code (Code-Pretty-Drucker) nicht beeinflussen sollten, aber uns nicht helfen, wenn wir nicht haben die Build-Intermediate-Ausgabe.

4

Eine interessante Frage. Ich habe ein ähnliches Problem auf Linux. Intrusion-Detection-Systeme wie OSSEC oder Tripwire können zu Fehlalarmen führen, wenn sich die Hashsumme einer ausführbaren Datei plötzlich ändert. Dies kann nichts schlimmer sein als das Linux "Prelink" -Programm, das die ausführbare Datei für schnellere Starts patcht.

Um zwei Binärdateien zu vergleichen (in der ELF format), kann man die "readelf" ausführbare Datei und dann "diff" verwenden, um Ausgaben zu vergleichen. Ich bin sicher, es gibt raffinierte Lösungen, aber ohne weiteres, einen Komparator des armen Mannes in 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; 
} 

Jetzt können Sie zum Beispiel laufen, auf der Maschine 1:

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

Und auf der Maschine 2 :

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

Nach copypasted haben, SFTP-ed oder NSF-ed (? Sie nicht FTP verwenden, tun Sie) die Dateien in den gleichen filetree vergleichen Sie die Dateien:

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

In meinem Fall gibt es Unterschiede in Abschnitt ".gnu.conflict", ".gnu.liblist", ".got.plt" und ".dynbss", was für eine "prelink" Intervention in Ordnung sein könnte, aber im Codeabschnitt ".text", was ein Bad Sign wäre.

-1

Vor ein paar Jahren musste ich das Gleiche tun. Wir mussten beweisen, dass wir die ausführbare Datei von der Quelle wiederherstellen konnten, wenn sie nur eine Revisionsnummer, ein Versionskontroll-Repository, Build-Tools und Build-Konfiguration erhielten. Hinweis: Wenn eine dieser Änderungen ändern, können Sie einen Unterschied sehen.

Ich erinnere mich, dass es einige Zeitstempel in der ausführbaren Datei gibt. Der Trick besteht darin, zu erkennen, dass die Datei nicht nur aus einer Menge Bytes besteht, die nicht interpretiert werden können. Die Datei hat Abschnitte, die meisten werden sich nicht ändern, aber es wird einen Abschnitt für die Zeit der Erstellung (oder so etwas) geben.

Ich erinnere mich nicht an alle Details, aber die Befehle, die Sie benötigen, sind {objcopy, objdump, nm}, ich denke objdump wäre der erste Versuch.

Hoffe, das hilft.