如何在 Linux 中比较二进制文件?

374 linux diff binary-files

我需要比较两个二进制文件并以以下形式获取输出:

<fileoffset-hex> <file1-byte-hex> <file2-byte-hex>

对于每个不同的字节。所以如果file1.bin

  00 90 00 11
Run Code Online (Sandbox Code Playgroud)

以二进制形式并且file2.bin

  00 91 00 10
Run Code Online (Sandbox Code Playgroud)

我想得到类似的东西

  00000001 90 91
  00000003 11 10
Run Code Online (Sandbox Code Playgroud)

有没有办法在 Linux 中做到这一点?我知道,cmp -l但它使用十进制表示偏移量,使用八进制表示字节,这是我想避免的。

Den*_*son 213

这将以十六进制打印偏移量和字节:

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'
Run Code Online (Sandbox Code Playgroud)

或者$1-1让第一个打印的偏移量从 0 开始。

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'
Run Code Online (Sandbox Code Playgroud)

不幸的是,它strtonum()是 GAWK 特有的,因此对于其他版本的 awk(例如,mawk),您将需要使用八进制到十进制的转换函数。例如,

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct,     dec) {for (i = 1; i <= length(oct); i++) {dec *= 8; dec += substr(oct, i, 1)}; return dec} {printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)}'
Run Code Online (Sandbox Code Playgroud)

为可读性而拆分:

cmp -l file1.bin file2.bin |
    mawk 'function oct2dec(oct,    dec) {
              for (i = 1; i <= length(oct); i++) {
                  dec *= 8;
                  dec += substr(oct, i, 1)
              };
              return dec
          }
          {
              printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)
          }'
Run Code Online (Sandbox Code Playgroud)

  • @gertvdijk:`strtonum` 是 GAWK 特有的。我相信 Ubuntu 以前使用 GAWK 作为默认设置,但在某些时候切换到了 `mawk`。在任何情况下,都可以安装 GAWK 并将其设置为默认值(另请参阅`man update-alternatives`)。有关不需要`strtonum`的解决方案,请参阅我的更新答案。 (3认同)
  • @Rodrigo:那个和其他各种方法只会显示文件是否不同。我的回答符合 OP 的要求,即实际显示差异是什么。 (2认同)

aki*_*ira 210

正如~quack指出的那样:

 % xxd b1 > b1.hex
 % xxd b2 > b2.hex
Run Code Online (Sandbox Code Playgroud)

进而

 % diff b1.hex b2.hex
Run Code Online (Sandbox Code Playgroud)

或者

 % vimdiff b1.hex b2.hex
Run Code Online (Sandbox Code Playgroud)

  • 在 Bash 中:`diff &lt;(xxd b1) &lt;(xxd b2)` 但是这个(或你的)的输出格式与 OP 要求的相差甚远。 (88认同)
  • 使用 vimdiff,它将为两个“文件”不同的行中的字节着色 (8认同)
  • 此命令不适用于字节添加删除,因为后面的每一行都将未对齐并被视为被“diff”修改。解决方案是每行放置 1 个字节并删除 [John Lawrence Aspden](http://superuser.com/a/332939/128124) 和 [me](http://superuser.com/) 提出的地址列a/897902/128124)。 (2认同)

ken*_*orb 143

diff + xxd

尝试diff以下 zsh/bash 进程替换组合:

diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • -y 并排显示差异(可选)。
  • xxd 是用于创建二进制文件的 hexdump 输出的 CLI 工具。
  • 添加-W200diff更广泛的输出(每行 200 个字符)。
  • 对于颜色,请colordiff按如下所示使用。

colordiff + xxd

如果你有colordiff,它可以为diff输出着色,例如:

colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)
Run Code Online (Sandbox Code Playgroud)

否则安装通过:sudo apt-get install colordiff

示例输出:

终端中的二进制文件输出 - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  颜色差异

vimdiff + xxd

你也可以使用vimdiff,例如

vimdiff <(xxd foo1.bin) <(xxd foo2.bin)
Run Code Online (Sandbox Code Playgroud)

提示:

  • 如果文件太大,请-l1000为每个文件添加限制(例如)xxd

  • 命令可以简化为`colordiff -y &lt;(xxd foo1.bin) &lt;(xxd foo2.bin)`。 (12认同)
  • 如果你只是想知道两个文件是否实际上相同,你可以使用 `-q` 或 `--brief` 开关,它只会在文件不同时显示输出。 (7认同)
  • 伟大的!仍然,`diff -u &lt;(xxd tinga.tgz) &lt;(xxd dec.out.tinga.tgz) | vim -` 会做得很好 (4认同)
  • 如果你没有 colordiff,这将在没有颜色的情况下做同样的事情:`diff -y &lt;(xxd foo1.bin) &lt;(xxd foo2.bin)` (3认同)
  • 我最喜欢的解决方案,对我帮助很大!使用选项`--suppress-common-lines` 只会显示不同的行 (2认同)
  • 警告! `colordiff` 截断每列的宽度。在我的系统上,这会导致微妙的“错误”输出。如果你进行二进制比较,会非常烦人。使用具有足够大数字的“-W”选项(140 足以与“xxd”一起使用)以避免该陷阱。 (2认同)

njd*_*njd 65

有一个名为DHEX的工具可以完成这项工作,还有另一个名为VBinDiff的工具。

对于严格的命令行方法,请尝试jojodiff

  • DHEX 很棒的是比较二进制文件是你想要做的。给它提供两个文件,它会将您直接带到一个比较视图,突出显示差异,并可以轻松移动到下一个差异。它还能够与大型终端一起工作,这在宽屏显示器上非常有用。 (11认同)
  • 我更喜欢 VBinDiff。DHEX即使在空闲时也在使用CPU,我认为它一直在重绘什么的。VBinDiff 不适用于宽终端。但是无论如何,宽终端的地址变得很奇怪,因为每行有超过 16 个字节。 (7认同)
  • vbindiff 让我们实际编辑文件,谢谢! (2认同)
  • 遇到第一个不同的字节后,@DanielBeauyat 压缩文件将完全不同。输出不太可能有用。 (2认同)
  • @1111161171159459134 jdiff 是同步和修补 jdiff 发现的差异的程序“套件”的一部分。但是,正如 Mark Ransom 所说,这对于压缩文件来说通常是不明智的。例外是“可同步”压缩格式(例如由 gzip --rsyncable 生成的格式),其中未压缩文件中的微小差异对压缩文件的影响应该有限。 (2认同)

Cir*_*郝海东 33

适用于字节添加/删除的方法

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)
Run Code Online (Sandbox Code Playgroud)

生成一个单次删除字节 64 的测试用例:

for i in `seq 128`; do printf "%02x" "$i"; done | xxd -r -p > file1
for i in `seq 128`; do if [ "$i" -ne 64 ]; then printf "%02x" $i; fi; done | xxd -r -p > file2
Run Code Online (Sandbox Code Playgroud)

输出:

64d63
<  40
Run Code Online (Sandbox Code Playgroud)

如果您还想查看字符的 ASCII 版本:

bdiff() (
  f() (
    od -An -tx1c -w1 -v "$1" | paste -d '' - -
  )
  diff <(f "$1") <(f "$2")
)

bdiff file1 file2
Run Code Online (Sandbox Code Playgroud)

输出:

64d63
<   40   @
Run Code Online (Sandbox Code Playgroud)

在 Ubuntu 16.04 上测试。

我喜欢odxxd,因为:

  • 是 POSIXxxd不是(Vim 附带)
  • -An删除地址列,没有awk

命令解释:

也可以看看:

  • 这种方法的好处是“od”非常强大。特别是,它允许比较长于一个字节的对象,例如 32 位浮点数。示例:`diff -u &lt;(od -tf4 -w1 fileA.bin) &lt;(od -tf4 -w1 fileB.bin)`。 (3认同)

Evg*_*eny 15

简答

vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)
Run Code Online (Sandbox Code Playgroud)

当使用 hexdumps 和 text diff 比较二进制文件时,尤其是xxd. 这个方法告诉 xxd 不输出地址,每行只输出一个字节,这反过来又准确地显示了哪些字节被更改、添加或删除。您可以稍后通过在更“正常”的十六进制转储(输出xxd first.bin)中搜索有趣的字节序列来找到地址。


小智 12

我建议使用 hexdump 将二进制文件转储为文本格式,使用 kdiff3 进行差异查看。

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex
Run Code Online (Sandbox Code Playgroud)

  • 即使在 bash `kdiff3 &lt;(hexdump myfile1.bin) &lt;(hexdump myfile2.bin)` 中也不需要创建文件 `myfile1.hex` 和 `myfile2.hex`。 (2认同)

小智 6

hexdiff程序旨在完全满足您的需求。

用法:

hexdiff file1 file2
Run Code Online (Sandbox Code Playgroud)

它显示两个文件的十六进制(和 7 位 ASCII),并突出显示任何差异。查看在man hexdiff文件中移动的命令,一个简单的命令q就会退出。

  • 但是在比较部分时它做得很糟糕。如果您在文件中插入一些字节,它会将之后的所有字节标记为更改 (5认同)

phk*_*phk 5

固件分析工具binwalk还通过其-W/--hexdump命令行选项将此作为一项功能,该选项提供诸如仅显示不同字节的选项:

    -W, --hexdump                Perform a hexdump / diff of a file or files
    -G, --green                  Only show lines containing bytes that are the same among all files
    -i, --red                    Only show lines containing bytes that are different among all files
    -U, --blue                   Only show lines containing bytes that are different among some files
    -w, --terse                  Diff all files, but only display a hex dump of the first file
Run Code Online (Sandbox Code Playgroud)

在 OP 的示例中,执行以下操作binwalk -W file1.bin file2.bin

binwalk -W file1.bin file2.bin

添加| less -r用于分页。