在查其他资料时, 突然看到bindiff有新版了, 顺手下载了一个装上试试.
bindiff功能:用来无源码比较1个可执行程序工程的不同版本之间的实现区别. e.g. 程序A的1.0.0版和1.0.20之间的实现区别. 如果改动比较小, 很容易用bindiff看出具体区别出来. 如果变化比较大, 也能定位到底哪些函数实现变化了.
以前用bindiff_V4.20时, 写了一个笔记(use bindiff to diff patch). 那时是2017年.
现在的bindiff是V7.0(2021年发布的), 比较速度比以前版本快多了.
以前实验, 是将一个工程逻辑改改, 作为比较对象, 好使.
这次实验, 是将字符串内容改了, 作为比较对象, 不好使.
看了一下不好使的原因, 是因为代码逻辑确实没变化, 而是串表不同.
不过一般程序升级后, 极少出现逻辑不变, 只有字符串变化的情况.
最后手工导出了2份IDA程序的串表, 用BC4进行比较后, 解决了这个疑惑(为啥程序变了, bindiff比较不出来).




用VS2022写个控制台工程, 改改, 分别作为A程序和B程序(A升级后的版本)
A工程的代码
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("version_A: Hello, %ls!\n", uri.AbsoluteUri().c_str());
}
B工程的代码
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("version_B: Hello, %ls!\n", uri.AbsoluteUri().c_str()); // 就改了这一句, 字符串内容变了, 逻辑没变
}
将A工程编译为64位的release版, 生成 test_bindiff_A.exe, 拷贝到测试目录.
将B工程编译为64位的release版, 生成 test_bindiff_B.exe, 拷贝到测试目录.
将原始工程目录压缩, 备份为 test_bindiff_A.7z, 将原始工程源码目录删掉.
用IDA分别打开test_bindiff_A.exe, 分析完后, 保存为test_bindiff_A.exe.i64.
用IDA分别打开test_bindiff_B.exe, 分析完后, 保存为test_bindiff_B.exe.i64.
打开bindiff, 建立工作区, 建立工程, 比较test_bindiff_A.exe.i64和test_bindiff_B.exe.i64的区别.
很遗憾, 看不到区别.

可以看到相似度都是1, 说明函数都相同.
将相似度排序(升序, 降序), 看到最上面的相似度始终是1, 说明修改后的程序在逻辑上和升级前是完全相同的.
去看IDA中, 改的那句字符串的位置.

可以看到, 修改点在main函数10E2处.
双击字符串, 去看字符串地址

去bindiff中, 找到这个修改点(main函数10E2处).


可以看到程序修改前后, 逻辑都一样, 只是从一个相同的地址(43F0)载入了一个字符串.
上面在IDA中看字符串地址时, 已经看了, 知道字符串地址确实为43F0.
这就不能怪bindiff了, 程序逻辑代码确实一样, 只是字符串不一样.
打开IDA串表

在串表UI中右击, 有拷贝全部的功能.

然后打开一个记事本, 贴进去, 命名为string_tbl_A.txt
同理, 打开B程序, 拷贝串表, 然后打开一个记事本, 贴进去, 命名为string_tbl_B.txt
用BC4比较这2个串表的备份文本文件, 可以很清楚看到区别.

串表区别:
这样就可以比较串表的区别了.
看用到bindiff的同学说, bindiff不同版本和不同的IDA版本匹配才行.
看看如果bin文件的逻辑变了, 是否bindiff7可以正确分析出来IDA7.7的数据库文件?
再开一个C工程, 加一句.
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("version_B: Hello, %ls!\n", uri.AbsoluteUri().c_str());
printf("this is C prog\r\n"); // 在B的基础上加一句话
}
将源码目录压缩备份, 删除源码目录.
用IDA分析C程序(注意程序编译选项, IDA分析选项要相同, 否则一个exe生成的i64也有区别.), 生成 test_bindiff_C.exe.i64.
用bindiff比较A和C的区别.
看到 main函数的相似度不是1, 说明有变化.

观察main函数区别.

可以看出修改后的程序多打了一句print. 字符串地址为4408
去IDA中, 打开C程序, 看到4408的字符串内容如下

这说明bindiff好使, 如果程序逻辑发生了变化, 是能响应的.
结合bindiff和IDA, 就可以知道2个程序的逻辑有何变化.
bindiff7可以和IDA7.7 + win10配合使用.
bindiff7可以侦测到程序升级之后的变化.
bindiff7不能侦测到字符串表的变化, 需要结合IDA提供的"copy all"来导出串表, 用BC4比较导出后的2个串表的区别.