比较生成的可执行文件的等效性

我需要比较使用相同编译器/标志编译的2个可执行文件和/或共享对象,并验证它们没有更改。我们在受监管的环境中工作,因此对于测试目的而言,确切地隔离可执行文件的哪些部分已经发生变化非常有用。 由于包含有关文件信息的标头,因此使用MD5Sums / Hashes不起作用。 有没有人知道一个程序或方法来验证2个文件是否在执行上是相同的,即使它们是在不同的时间构建的?     
已邀请:
一个有趣的问题。我在linux上有类似的问题。如果可执行文件的hashsum突然发生变化,OSSEC或tripwire等入侵检测系统可能会产生误报。这可能比Linux“prelink”程序修补可执行文件以便更快启动更糟糕。 为了比较两个二进制文件(ELF格式),可以使用“readelf”可执行文件,然后使用“diff”来比较输出。我确信有一些精致的解决方案,但不用多说,一个穷人在Perl中的比较器:
#!/usr/bin/perl -w

$exe = $ARGV[0];

if (!$exe) {
   die "Please give name of executablen"
}
if (! -f $exe) {
   die "Executable $exe not found or not a filen";
}
if (! (`file '$exe'` =~ /bELFb.*?bexecutableb/)) {
   die "file command says '$exe' is not an ELF executablen";
}

# 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 $2n";
      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-ed或NSF-ed(您不使用FTP,是吗?)将文件放入同一文件树中,比较文件:
diff --side-by-side --width=200 curl_machine1 curl_machine2 | less
在我的情况下,“.gnu.conflict”,“。geu.liblist”,“。gogot”和“.dynbss”部分存在差异,这可能适用于“预链接”干预,但在代码部分,“。text”,这将是一个坏标志。     
为了跟进,这是我最终提出的: 而不是比较最终的可执行文件&amp;共享对象,我们在链接之前比较了.o文件输出。我们假设连接过程具有足够的可重复性,这样就可以了。 它适用于我们的一些情况,我们有两个版本,我们做了一些小的改动,不应该影响最终的代码(代码漂亮的打印机),但如果我们没有构建中间输出,则无法帮助我们。     
您可以通过从ELF文件生成二进制文件来比较RO和RW初始化部分的内容。
objcopy <elf_file> -O binary <binary_file>
例如,使用生成的二进制文件来比较它们是否相同,使用
diff
。 在我看来,这足以让您生成相同的可执行文件。     
几年前我不得不做同样的事情。我们必须证明,在仅提供修订号,修订控制存储库,构建工具和构建配置时,我们可以从源重建可执行文件。注意:如果其中任何一项发生变化,您可能会发现不同之处 我记得可执行文件中有一些时间戳。诀窍是要意识到文件不仅仅是一堆无法解释的字节。该文件有部分,大多数不会更改,但会有一个部分用于构建时间(或某些此类事物)。 我不记得所有的细节,但你需要的命令是{objcopy,objdump,nm},我认为objdump是第一个尝试的。 希望这可以帮助。     

要回复问题请先登录注册