4、Diff工具深度使用:GNU Diff、Colordiff、Vimdiff、Beyond Compare对比技巧
做补丁分析,说白了就是找不同。但怎么找、用什么找,差别可大了去了。
我刚开始做漏洞分析那会儿,只会用 diff -u 看个大概。后来有一次,一个关键补丁里藏了个变量类型转换的漏洞,我愣是没看出来。为什么?因为普通 diff 只告诉我「这行变了」,但没告诉我「这行是怎么变的」。从那以后,我开始认真研究各种 diff 工具。
今天我就把这几把刷子都抖搂出来。GNU Diff、Colordiff、Vimdiff、Beyond Compare,各有各的脾气,也各有各的绝活。
4.1 GNU Diff:命令行下的基本功
GNU Diff 是 Linux 下的标配,也是所有 diff 工具的祖宗。你别看它长得丑,功能其实很扎实。
我个人最常用的几个参数:
-u:上下文格式,显示改动前后几行。比默认格式清晰十倍。-r:递归比较目录。补丁包经常是一堆文件,这个必须用。-N:把新增文件当成空文件来比较。不然新文件会直接被忽略。-w:忽略空白差异。有些补丁只是改了缩进,用这个能过滤噪音。
举个例子,比较两个版本的补丁目录:
diff -urN patch_v1/ patch_v2/
嗯,这里要注意。如果你只写 diff -r,输出会乱成一锅粥。加上 -u 之后,每段差异前面都有文件名和行号,一眼就能定位。
diff -urN 设成别名。我习惯在 .bashrc 里写 alias diff='diff -urN',省得每次敲一堆参数。
4.2 Colordiff:给黑白世界加点颜色
GNU Diff 的输出是黑白的。看多了眼睛疼,尤其是几百行的补丁,找差异点跟大海捞针似的。
Colordiff 就是干这个的。它本质上是个 Perl 脚本,把 diff 的输出染上颜色。新增的行是绿色,删除的行是红色,上下文是默认色。
安装很简单:
sudo apt install colordiff # Debian/Ubuntu
sudo yum install colordiff # CentOS/RHEL
用法更简单,直接把 diff 换成 colordiff:
colordiff -urN patch_v1/ patch_v2/
我曾经在分析一个内核补丁时,用 colordiff 一眼就发现了一个被删除的空行——那个空行原本是某个宏定义的结尾。补丁作者删了它,导致宏定义范围变了,引发了一连串的编译错误。这种细节,黑白 diff 根本看不出来。
4.3 Vimdiff:在编辑器里直接对比
如果你跟我一样,大部分时间泡在 Vim 里,那 Vimdiff 就是你的神器。
启动方式:
vimdiff file1.c file2.c
或者先打开一个文件,再执行:
:vertical diffsplit file2.c
Vimdiff 最牛的地方是什么?是同步滚动和差异跳转。你滚动左边,右边跟着动。按 ]c 跳到下一个差异点,按 [c 跳到上一个。这比肉眼一行行扫快多了。
我个人习惯的用法:
- 先用
:diffupdate刷新比较结果。有时候改了文件,Vim 不会自动重算差异。 - 用
zo和zc折叠/展开代码块。只看有差异的部分,省得被无关代码干扰。 - 按
dp把当前差异「推」到另一边。这个在合并补丁时特别好用。
举个例子。有一次我在分析一个安全补丁,左边是旧代码,右边是新代码。按 ]c 跳了七八次,突然发现一个差异点:新代码里多了一个 if (ptr == NULL) return -EINVAL;。旧代码里没有这个检查。嗯,这就是漏洞点——空指针解引用。
4.4 Beyond Compare:图形化对比的王者
说到图形化对比工具,Beyond Compare 是我用过最顺手的。虽然它收费,但值那个价。
它有几个功能,是命令行工具完全没法比的:
| 功能 | 说明 | 我的用法 |
|---|---|---|
| 三路合并 | 同时对比三个版本(原版、你的修改、他的修改) | 分析补丁冲突时,一眼看出谁改了哪里 |
| 语法高亮 | 根据语言类型着色,差异点用颜色块标出 | 看 C 代码时,变量类型、函数名一目了然 |
| 文件夹对比 | 递归对比目录结构,显示新增/删除/修改的文件 | 分析大型补丁包时,先看文件级差异,再深入看代码 |
| 差异统计 | 显示每个文件有多少处差异,总共有多少行变化 | 快速评估补丁的「影响范围」 |
我印象最深的一次,是分析一个 Android 安全补丁。那个补丁改了 30 多个文件,用 Beyond Compare 打开,左边是旧版,右边是新版。我先把文件夹对比打开,发现有个文件是新增的——security/patch_manager.c。点进去一看,好家伙,整个文件都是新写的,里面有个权限检查的逻辑漏洞。如果只用命令行 diff,我可能根本不会注意到这个新增文件。
4.5 实战对比:选哪个?
你可能会问:这么多工具,到底用哪个?
我的建议是:
- 快速扫一眼:用 Colordiff。几秒钟出结果,适合初步判断补丁大小。
- 深入分析代码逻辑:用 Vimdiff。同步滚动 + 差异跳转,效率最高。
- 处理大型补丁包:用 Beyond Compare。文件夹对比 + 三路合并,没有对手。
- 写脚本批量对比:用 GNU Diff。配合
grep、awk做自动化分析。
说白了,没有最好的工具,只有最合适的场景。我自己的习惯是:先用 Colordiff 扫一遍,看看补丁改了哪些文件、大概改了多大。然后用 Vimdiff 逐个文件深入分析。如果遇到特别复杂的合并场景,再请出 Beyond Compare。
嗯,工具是死的,人是活的。关键不是你用哪个工具,而是你能不能从差异中看出漏洞的蛛丝马迹。下一章,我会讲怎么从补丁的「上下文」里挖出隐藏的漏洞——那才是真正的硬功夫。