一、说明
大概一两年前在《漏洞战争:软件漏洞分析精要》听到bindiff(和补丁比较法),但一直都没去使用。前两天再回头看书感觉需要使用一翻,整个过程下来还是遇到了一些问题,值得记录一番。
二、安装
2.1 jdk安装
bindiff是一款java程序,因此需要安装jdk,我装的是jdk1.8其他版本兼容性不太清楚。
jdk下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html
2.2 ida安装
bindiff需要借助ida pro进行分析,所以需要安装ida pro。官方说明需要6.8及以上版本,但7.x版本也尚不支持。
ida pro安装可参考:https://www.cnblogs.com/lsdb/p/7500981.html
2.3 bindiff安装
下载地址:https://www.zynamics.com/software.html
bindiff同时支持windows、linux、mac;bindiff5只能装在win8和win10上;下载链接不明显但是是有链接的,直接中键点击文件名处即可下载。
双击运行安装程序
接受协议
选择安装组件和路径
指出自己ida pro安装的目录
确认安装
安装完成
三、bindiff使用
3.1 编写比较程序
我这里使用cfree创建两个控制台项目bindiff1和bindiff2,分另写入以下两分代码并各自编译。代码的区别就只是把if语句的大于号改为小于号。
bindff1代码:
# include <stdio.h>
int main(){
int a = ;
if (a > ){
printf("if brance\n");
}
else{
printf("else brance\n");
}
getchar();
}
bindff2代码:
# include <stdio.h>
int main(){
int a = ;
if (a < ){
printf("if brance\n");
}
else{
printf("else brance\n");
}
getchar();
}
3.2 使用ida创建数据库
bindiff不能直接分析exe程序,而只能先使用ida pro的.i64数据库基础上进行分析。
因此需要先用ida pro分别打开bindiff1.exe和bindiff2.exe再关闭,以创建.i64数据库。
3.3 bindiff载入文件并比较
到安装目录bin文件夹下双击bindiff.jar即可启动bindiff,界面如下:
主菜单----Diffs----New Diff
先后载入bindffi1.i64和bindiff2.i64,点击Diff进行比较
32位操作系统应该成功载入,64位操作系统可能会报错:“Can't find Diff engine at '...\differ64.exe'”
看意思是differ64.exe找不到,打开bindiff安装目录的bin文件夹,将bindiff.exe复制一份命名为bindiff64.exe,此时再重新载入比较即可。
Call Graph----两个文件的函数调用图
Matched Functions----两个文件的函数匹配度
Primary Unmatched Functions----
Secondary Unmatched Functions----
bindiff的主要简单使用是双击打开"Matched Functions"项,按相似度(Similarity)从低到高排序,相似度不为1的函数即为两个文件被改动的位置。
由上图可以看到,bindiff1.exe和bindiff2.exe只有_main相似度不为1,双击_main打开, 两个函数不同的位置会被以有底色形式标出
如下图可以看到只有一条指令不同:bindiff1.exe是"jle 0x401335"(小于等于则进入else)而bindiff2是“jg 0x401335”(大于则进入else)
由此我们可以推断出bindiff2.exe相对于bindiff1.exe做的改动是:bindiff1.exe是"if > else"而bindiff2.exe是"if < else"。与我们的改动完全一致。
3.4 将bindiff以ida插件形式使用
在上边的操作中我们需要先用ida打开文件创建数据库,再使用bindiff打开比较,这是比较麻烦的。bindiff允许直接以ida插件的形式使用。(在安装bindiff时已同步安装为插件所以不需要另行安装)
先使用ida打开bindiff1.exe,然后使用“Ctrl+6”打开窗口,如下图所示
点击“Diff Database...”载入bindiff2.i64。如下图,仍是类似单独使用时的那几个窗口。当然这只是简单查看比较最后还是要打开bindiff。
3.5 bindiff使用注意点
第一点,相同的高级语言代码使用不同编译器编译出来的内容是有区别的。比如我这里使用cfree编译,倘若同样的代码你用VC++去编译那函数数量可能会多不少。但当然识别出的改动位置还是一个意思的。
第二点,相同的高级语言代码使用相同编译器不同的编译模式编译出来的内容是有区别的。比如VC++优化模式和普通模式编译出的汇编代码是有区别的。
第三点,bindiff只能识别出汇编指令的区别不能识别出汇编指令操作数的区别。即如上边“jle 0x401335”和“jg 0x401335”会被不同底色标出,但如果是“jle 0x401335”和“jle 0x401336”那将不会被标出。
参考: