当前位置: 首页 > 工具软件 > BinDiff > 使用案例 >

bindiff 太慢,两小时没结果

彭允晨
2023-12-01

安装了bindiff7.0  两个小时也没有结果了,看了文档才知道是版本错了。

版本 7 中的新功能

  • IDA:支持IDA Pro 7.6 SP1,最低要求版本仍为7.4
  • Ghidra:BinExport Ghidra 扩展现在包含在包中。这仍被视为测试版,需要手动从 Ghidra 导出文件以绑定它们。
  • Binary Ninja:包含用于 Binary Ninja 的 BinExport 插件。这仍然被认为是测试版。使用第三方 BD Viewer 或手动导出到 bindiff 文件。
  • 函数名称现在导出到 `.BinDiff` 结果文件中,使后处理更容易
  • 提高了本机 BinExport 插件的速度。与 BinDiff 6 相比,从 IDA Pro 和 Binary Ninja 导出的速度提高了 30%。
  • 用户界面:在所有平台(包括 Linux)上提供基于 JDK 16 的更新 Java 运行时
  • 用户界面:在所有平台上提供更好的 HiDPI 支持
  • 安装包:反汇编插件现在被符号链接到每个用户的插件目录中,而不是被复制到目标反汇编安装中。
  • 用户配置现在使用 JSON 格式,使未来的更改更容易并修复了一些长期存在的序列化问题。
  • macOS:与 macOS 11“Big Sur”兼容的公证二进制文件/包
  • macOS:支持 ARM64(又名“Apple Silicon”)和 x86-64 的通用二进制文件
  • 修复了特制的 .BinExport 文件可能导致越界内存访问的安全问题。感谢趋势科技移动安全研究团队的 Mickey Jin 的报告。

bindiff7.0 需要ida7.4-ida7.6 ,难怪我的ida7.0 两个小时没结果。

但是版本不支持连个提示都没有,这也有点XX了。

bindiff版本ida版本
4.16.5以上
4.26.8以上
4.36.95
57
67.4
77.4-7.6sp1

这个版本一定要对应,不然很可能几小时没结果。版本对的话,10M左右的IDB一把几秒钟就对比结束了,最多几分钟,肯定不会上小时。

表格中说以上,但是以上的范围可能比价小。。。比如bindiff4.1 支持6.5以上,6.8也在6.5以上,但是bindiff4.1就不支持了。看更新说明,这个软件每次都要根据ida sdk编译,不支持也在情理之中。 

bindiff这个对某些静态编译的库也有奇效。

bindiff原理:

以下内容为机器翻译,准确度请自行评估。原网页:

https://www.zynamics.com/bindiff/manual/index.html

本节提供有关 BinDiff内部工作原理的背景信息。建议想要充分利用产品的任何人以及想要了解不同配置选项的详细信息的任何人阅读。

BinDiff 处理可执行文件的抽象结构,忽略反汇编中的具体汇编级指令。每个函数都会根据函数的(标准化)流图的结构获得一个签名。签名包括:

  • 代码块数
  • 代码块之间的边数
  • 调用子函数的次数

一旦生成了两组签名(用于两个可执行文件),就会创建初始匹配。这是通过选择每个可执行文件中具有共同特征的所有功能的子集来实现的。如果签名在两个检查的签名子集中出现一次(并且仅出现一次),则创建匹配。

在此步骤之后,调用图(包含有关函数之间调用关系的信息的图)用于生成更多匹配:如果匹配已知,则检查从匹配函数调用的所有函数的子集。这些子集明显小于所有函数的集合,因此找到新的唯一匹配的概率要高得多。重复此过程,直到找不到新的匹配项。

这意味着在您成功运行 BinDiff 后,您将拥有一个成功关联的函数列表,以及两个无法关联的函数列表。


一般匹配策略

BinDiff有一个适合生成匹配的函数属性列表(见下文)。它从全局级别开始,考虑二进制的所有函数并计算每个函数的第一个属性。有几种可能的结果:

  1. 属性在两个二进制文件中都是唯一的。功能匹配。
  2. 一个属性在两个二进制文件中出现多次 - 匹配不明确。BinDiff继续进行“向下钻取”步骤,只考虑该属性的等效函数集。向下钻取意味着尝试下一个最佳属性,直到我们用完算法、唯一匹配函数或由于属性不匹配其任何函数而导致集合消失。
  3. 一个属性在另一个二进制文件中没有匹配项。该函数保留在未匹配集合中。

在初始全局匹配步骤之后,考虑每个新匹配的父级(调用者)和子级(被调用者)。 BinDiff尝试通过对每个函数执行如上所述的“向下钻取”步骤来匹配父子集合中的函数。最后BinDiff对所有新匹配的函数执行基本块匹配,并匹配从匹配的基本块调用的函数函数:调用引用匹配)。这结束了单个属性的全局匹配。使用下一个最佳属性在剩余的不匹配函数上重新启动整个过程。


功能匹配

函数属性以两种方式之一使用。每个函数或每个边缘规范化。如果源和目标函数属性匹配,边匹配会尝试匹配边(表示调用图中的调用或流图中的跳转)。因此,边缘匹配是更强的标准,通常会产生更好的匹配。然而,由于图中每个顶点可能有很多边(这对于调用图尤其如此,其中边的数量通常随着顶点的数量呈线性增长)边匹配可能非常慢。如果您确实遇到某些二进制文件的性能问题,您应该首先尝试禁用基于边缘匹配的算法。还,

函数匹配算法按匹配质量粗略排序:

功能:哈希匹配

根据原始原始函数字节的散列匹配函数。因此,由该算法匹配的两个函数在字节级别上应该是相同的。

比赛质量:非常好

算法性能:非常好

功能:名称哈希匹配

根据函数名称的散列匹配函数。只 考虑真实姓名,不使用反汇编程序自动生成的名称。这是可以匹配导入函数的少数算法之一,即在二进制文件中没有实际主体的函数。错误匹配的可能性很小。

比赛质量:非常好

算法性能:非常好

功能:边流图MD索引

根据源函数和目标函数的 MD 索引匹配调用图边。因此,两个结构相同的函数之间的调用是匹配的。

比赛质量:非常好

算法性能:中等

功能:边调用图MD索引

根据调用图 MD 索引匹配调用图边。这意味着导致该特定调用的调用图在两个二进制文件中在结构上是相同的。匹配质量取决于导致此边缘的调用堆栈的深度:越深,错误匹配的可能性就越小。

比赛质量:好

算法性能:中等

功能:MD索引匹配(流程图MD索引,自顶向下), 功能:MD索引匹配(流程图MD索引,自下而上)

使用 MD 索引根据函数的结构匹配函数。由于 MD 索引将拓扑图排序作为其输入之一,因此我们可以通过将图顶点排序为来自入口点(自上而下)的调用或来自出口点的调用者(自下而上)的级别来对其进行参数化。

比赛质量:好

算法性能:非常好

功能:素数签名匹配

根据其指令素积匹配功能。每个助记符都被分配了一个唯一的小质数。对于函数的所有指令,这些素数相乘。这产生了结构不变、指令顺序无关的产品,随后将用作匹配属性。

比赛质量:好

算法性能:非常好

功能:MD索引匹配(callGraph MD索引,自顶向下), 功能:MD索引匹配(callGraph MD索引,自下而上)

根据函数在调用图中的位置匹配函数。从程序入口点(自上而下)或其出口(自下而上)来看,通向该函数的调用图在结构上必须相同。

比赛质量:好

算法性能:非常好

功能:边缘接近MD索引

根据函数的本地调用图邻域匹配函数。从所讨论的函数中可以看出,调用和被调用者仅遵循两层深度。

比赛质量:中等

算法性能:差

功能:放宽MD索引匹配

根据函数的宽松 MD 索引匹配函数。MD 指数是在不考虑拓扑顺序的情况下计算的。这意味着只考虑函数局部邻域中的入边和出边。

比赛质量:中等

算法性能:中等

功能:地址序列

根据函数的入口点地址按顺序匹配函数。这是一个特殊的匹配步骤,在向下钻取期间特别有用。由于如果没有进一步约束,它将不分青红皂白地匹配所有函数,因此有两个额外的要求:首先,根据松弛的 MD 索引和流图 MD 索引,所讨论的函数必须已经是等价的。其次,两个二进制文件中的两组等效函数必须具有相同的大小。

比赛质量:差

算法性能:非常好

功能:字符串引用

根据函数引用的字符串数据匹配函数。从相关函数中引用的所有字符串都被放入一个组合哈希中,如果至少引用了一个字符串,该哈希随后将用作匹配属性。这是一个很好的匹配错误处理代码的算法,它通常只有很少的结构(因此不会被更强的算法匹配)但有很多对错误消息字符串的引用。

比赛质量:中等

算法性能:非常好

功能:循环计数匹配

根据循环数匹配函数。仅当至少存在一个循环时才应用。

比赛质量:差

算法性能:非常好

函数:调用序列匹配(精确), 函数:调用序列匹配(拓扑), 函数:调用序列匹配(序列)

仅用于具有匹配父项(调用方)的函数的特殊算法。调用点的调用点被确定为一个元组:拓扑基本块级别、基本块中的指令号、地址。如果基本块级别和指令号匹配(精确),如果仅基本块级别匹配(拓扑)或简单地按调用站点地址(序列)排序,则子函数(被调用方)匹配。这通常会产生非常弱的匹配,但如果父函数匹配正确,这可能是一个很好的策略。在这种情况下,它不太可能在两个二进制文件中以相同的顺序调用函数。

比赛质量:很差

算法性能:良好


基本块匹配

流图级别的基本块匹配在算法上与函数匹配非常相似。全局属性匹配之后是向下钻取并尝试在匹配的基本块的父/子的减少集合中进行匹配。

基本块匹配算法按匹配质量粗略排序:

basicBlock:边素积

如果源和目标基本块指令素积匹配,则流程图边缘匹配。因此,两个基本块都包含相同的指令,可能排序不同。

比赛质量:非常好

basicBlock:哈希匹配(最少 4 条指令)

基本块根据其原始字节的二进制散列进行匹配。仅用于具有至少 4 条指令的基本块。

比赛质量:非常好

basicBlock:素数匹配(最少 4 条指令)

基本块根据其指令素积进行匹配。仅用于具有至少 4 条指令的基本块。

比赛质量:非常好

basicBlock:调用引用匹配

如果基本块至少调用了一个函数,并且所有调用的函数都已匹配,则匹配基本块。

比赛质量:非常好

basicBlock:字符串引用匹配

如果基本块至少引用了一个字符串,并且该字符串在两个二进制文件中相同,则匹配基本块。

比赛质量:非常好

basicBlock:边缘MD索引(自上而下), basicBlock:MD索引匹配(自上而下), basicBlock:边缘MD索引(自下而上), basicBlock:MD索引匹配(自下而上), basicBlock:宽松MD索引匹配

基本块根据它们在流程图中的位置进行匹配。

比赛质量:好

basicBlock:素数匹配(最少 0 条指令)

像前面的素数匹配步骤一样工作,但取消了最小指令数约束。

比赛质量:中等

basicBlock:边缘 Lengauer Tarjan 占优势

匹配使用 Lengauer-Tarjan 算法确定的循环的后边缘。

比赛质量:中等

basicBlock:循环入口匹配

匹配作为循环锚点的基本块,即后边缘的目标。

匹配质量:低

basicBlock:自循环匹配

匹配具有自循环的基本块。

匹配质量:低

basicBlock:入口点匹配, basicBlock:出口点匹配

匹配入口/出口点基本块。入口点由函数唯一标识,通常入度为 0。出口点是出度为 0 的顶点。

匹配质量:低

basicBlock:指令数匹配, basicBlock:跳转序列匹配

仅适用于基于其 MD 索引在结构上等效的基本块的特殊匹配步骤。基本块根据它们的指令数量匹配或简单地按地址排序。

匹配质量:非常低

basicBlock:传播(大小==1)

不得已的特殊匹配步骤。匹配基本块的单个未匹配的父/子匹配 - 不考虑它们的内容。

匹配质量:非常低


置信度/相似度

BinDiff显示的置信度值是平均算法置信度(匹配质量),用于查找由 sigmoid 压缩函数加权的特定匹配项。这些值不是简单地平均的,因为在其他方面完美匹配的函数/二进制文件中很少有单个弱匹配不应该过多地降低置信度。类似地,即使是少数强匹配也不会“拯救”主要由地址序列和类似弱算法匹配的二进制对。

函数的相似度值是考虑以下因素的加权和:

  1. 权重 ~25%:匹配的流图边占总边的配额

  2. 权重 ~15%:匹配的基本块占基本块总数的配额

  3. 权重 ~10%:匹配指令占总指令的配额

  4. 权重~50%:流程图MD指标差异

最终的相似度值乘以置信度 - 如果由弱算法产生,即使看起来很好的匹配也不值得信赖。

整个二进制的相似度值是考虑到以下因素的加权和:

  1. 权重 ~35%:匹配的流图边占总边的配额

  2. 权重 ~25%:匹配的基本块占基本块总数的配额

  3. 权重 ~10%:匹配功能占总功能的配额

  4. 权重 ~10%:匹配指令占总指令的配额

  5. 权重 ~20%:调用图 MD 索引的差异

再次,乘以信心。计数时只考虑非库函数。这是为了避免夸大二进制文件的相似性,这些二进制文件只是使用相同的运行时库,但在其他方面完全不同。
 类似资料: