【问题标题】:How to use "cmp" to compare two binaries and find all the byte offsets where they differ?如何使用“cmp”比较两个二进制文件并找到它们不同的所有字节偏移量?
【发布时间】:2011-12-05 12:53:58
【问题描述】:

我希望 Bash 脚本循环能够显示两个二进制文件之间的所有差异,仅使用

cmp file1 file2 

它只显示我想使用 cmp 的第一个更改,因为它给出了每个更改所在的行号的偏移量,但是如果您认为有更好的命令,我愿意接受 :) 谢谢

【问题讨论】:

  • 偏移量有效,但比较二进制文件时行号无效,因为它们没有行的概念(只有文本有行)。
  • 是的,我明白了,在这种情况下,我使用行号来引用二进制文件的十六进制转储,所以我阅读了不同偏移量周围的内容:)

标签: bash shell unix


【解决方案1】:

我认为cmp -l file1 file2 可能会做你想做的事。从手册页:

-l  --verbose
      Output byte numbers and values of all differing bytes.

输出是偏移量表,file1 中的字节值和 file2 中所有不同字节的值。它看起来像这样:

4531  66  63
4532  63  65
4533  64  67
4580  72  40
4581  40  55
[...]

所以第一个区别是偏移量 4531,其中 file1 的 decimal octal 字节值为 66,而 file2 的字节值为 63。

【讨论】:

  • +1:这是“这样做的方法”,但问题是cmp 不查找插入或删除的材料;它只是检查'file1中偏移N处的字节是否与file2中偏移N处的字节相同;如果是,则不打印任何内容,否则打印差异。因此文件必须非常相似(例如,编译目标文件时的 Unix 时间戳中只有一些字节 - 它内置在某些目标文件中),但其余部分必须相同。向一个常量字符串添加 3 个字节,之后的所有内容都不同。
  • 谢谢堆,这正是我想要的,我过去尝试过,但我确实知道偏移量一侧的数字:) 谢谢堆!
  • 我已经通过添加有关不同字节格式的更正来编辑答案。这是 cmp 的一个没有很好记录的功能。我希望编辑是适当的。
【解决方案2】:

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

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)

生成一个删除单个字节 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

输出:

64d63
<  40

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

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

bdiff file1 file2

输出:

64d63
<   40   @

在 Ubuntu 16.04 上测试。

比起xxd,我更喜欢od,因为:

  • is POSIX,xxd 不是(Vim 自带)
  • -An 来删除没有awk 的地址列。

命令说明:

  • -An 删除地址列。这很重要,否则在添加/删除字节后所有行都会有所不同。
  • -w1 每行放一个字节,以便 diff 可以使用它。每行有一个字节至关重要,否则删除后的每一行都会变得异相和不同。不幸的是,这不是 POSIX,而是存在于 GNU 中。
  • -tx1 是您想要的表示形式,可以更改为任何可能的值,只要您每行保留 1 个字节即可。
  • -v 防止星号重复缩写 * 可能会干扰差异
  • paste -d '' - - 每两行加入。我们需要它,因为十六进制和 ASCII 进入不同的相邻行。取自:Concatenating every other line with the next
  • 我们使用括号() 来定义bdiff 而不是{} 来限制内部函数f 的范围,另请参见:How to define a function inside another function in Bash?

另见:

【讨论】:

  • 这有一个固有缺陷,它不会流式传输数据,而是将所有内容加载到 RAM 中,这意味着您将需要至少 2-3 倍文件大小作为内存,这是大多数二进制差异工具使用的.我发现唯一一个不像这样的行为是 xdelta3...
  • @Izzy 将其添加到显示使用它以及为什么使用它的答案中并获得支持:-)
  • 遗憾的是,据我所知,它不能。至少不是你期望的那种。它产生 VCDIFF 输出,这是一个高度压缩的二进制增量。因此,您可以对命令结构进行差异、修补和少量操作。我的评论更像是“请注意,这个答案会用 5GB 文件破坏你的主内存”
  • @Izzy 好的!不过很高兴知道。
【解决方案3】:

我发现的更有效的解决方法是使用 od 将二进制文件转换为某种形式的文本。

那么diff 的任何风格都可以正常工作。

【讨论】:

  • 是的,这真的取决于 OP 想要对差异做什么。 hexdump 的差异可能对人类更有价值,而 cmp 可能更容易让程序解析/使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 2017-07-26
  • 2012-08-20
  • 1970-01-01
相关资源
最近更新 更多