Ghidra BSim Overview Query 实战:函数匹配数、Self-Significance 与 Vector Hash 判重
本文基于 Ghidra BSim(行为相似性)教程中的 Overview Queries 章节展开,讲解如何使用 BSim Overview Query 统计可执行文件中每个函数在 BSim 数据库中的匹配数量,并结合结果表中的 Hit Count、Self Significance 和可选的 Vector Hash 列完成三个典型实战练习:识别高重复度函数、基于命中数筛选发起精准搜索、以及用向量哈希判定两个函数是否拥有相同的 BSim 签名。读完后你可以独立完成从执行 Overview 查询、解读结果表到发起后续相似函数搜索的完整工作流。
Overview Query 是什么
Overview Query(概览查询) 会向 BSim 数据库查询:当前可执行文件中的每个函数各有多少个匹配项(match count)。它只返回每个函数的匹配数量,不返回具体的匹配函数本身。与普通的相似函数搜索(Search Functions)相比,Overview Query 有以下特性:
- 可以设置 Similarity(相似度) 与 Confidence(置信度) 阈值;
- 没有 “Matches per Function(每个函数最大匹配数)” 上限;
- 不能 施加 BSim 过滤器(filter)。
发起方式:在 Ghidra 的 Code Browser 中执行菜单操作 BSim -> Perform Overview...。
源码视角:Overview 任务如何构造
Perform Overview... 菜单项由 BSimSearchPlugin.java 注册:
new ActionBuilder("BSim Overview", getName()).menuPath("BSim", "Perform Overview...")
.helpLocation(new HelpLocation(getName(), "BSim_Overview_Dialog"))
.enabledWhen(c -> currentProgram != null)
.onAction(c -> showOverviewDialog())
.buildAndInstall(tool);
点击后弹出 BSim Overview 对话框,选择一个已配置的 BSim 服务器与数据库,随后插件会创建一个后台 OverviewTask。从 OverviewTask 的构造与执行逻辑 可以看到它与文档描述完全对应:
overviewInfo = new SFOverviewInfo(functions);
overviewInfo.setSimilarityThreshold(settings.getSimilarity());
overviewInfo.setSignificanceThreshold(settings.getConfidence());
...
queryService.overviewSimilarFunctions(overviewInfo, this, monitor);
对比同一文件中的 SearchTask(普通搜索),可以发现 Overview 路径不调用 setMaximumResults(...),也没有复制 BSimFilterSet 过滤器——这正是“无每函数匹配数上限、无过滤器”这一行为限制的实现依据。
另外,被统计的对象是当前程序中全部非 stub 函数。插件通过 getOverviewFunctions() 用 functionManager.getFunctionsNoStubs(true) 遍历得到,因此结果表的行数通常等于程序中的非 stub 函数数。
结果表:列含义与源码实现
Overview 结果在独立的 “BSim Function Overview” 窗口中展示(窗口分组为 bsim.overview,见 BSimOverviewProvider.java),默认列由表模型 BSimOverviewModel 定义:
| 列名 | 说明 | 源码取值 |
|---|---|---|
| Address | 函数入口地址,支持点击导航 | BSimOverviewModel.getAddress() |
| Function Name | 函数名 | FuncNameColumn |
| Hit Count | 该函数在数据库中的匹配数量 | simvec.getTotalCount() |
| Self Significance | 以该函数为查询时可能得到的最高显著性得分 | vectorFactory.getSelfSignificance(...) |
| Vector Hash | 特征向量的唯一哈希(默认隐藏的可选列) | lshVector.calcUniqueHash(),按 %016X 十六进制显示 |
几个关键点来自 BSimOverviewRowObject 的构造逻辑:
Hit Count取自数据库返回的SimilarityVectorResult.getTotalCount();- 源码注释明确说明
selfsignif是 “Maximum significance score a query with this function could return”(以该函数作为查询时,查询结果所能达到的最大显著性分数)。换句话说,一个函数的 Self Significance 就是它“自我匹配”的天花板:如果连它自己都只能得到较低的显著性得分,那么用它去查询时所有结果的 Confidence 都不会太高; Vector Hash列在 列描述符 中通过addHiddenColumn(new VectorHashColumn())注册为隐藏列,因此教程中要求“在 Overview 表中启用 Vector Hash 列”——即通过 Ghidra 表格的列选择器把它勾选出来。
下面是 Overview 查询结果窗口的示意:
练习一:Hit Count 与 Self-Significance 的关系
目标:用默认阈值对 postgres 可执行文件执行 Overview 查询,观察命中数与自显著性之间的负相关。
操作步骤:
- 以默认查询阈值对
postgres执行 Overview 查询(BSim -> Perform Overview...),结果如上图所示。 - 点击表头,按 Hit Count 列升序 排序。通常命中数(Hit Count)最大的那些函数,其 Self Significance 会很低。请对照上表验证这一点。
- 思考题:命中数最高的那些函数为什么会有这么多匹配?
- 参考答案:它们全都是 PostgreSQL 的错误报告函数(error-reporting functions)。这些函数的函数体非常相似,因此具有完全相同的 BSim 签名——数据库中每出现一份这样的函数副本,就为所有这些副本各贡献一次命中。
这一现象正是“高命中 ⇒ 低 Self Significance”直觉的典型例证:当某个函数的签名与大量几乎相同的函数共享时,它作为查询向量时的显著性得分上限就会被摊薄。理解这一规律后,Overview 表就成了一个“噪声探测器”——命中数极高的行往往对应模板化/重复生成的代码,直接拿它们去查询价值有限。
练习二:利用命中数筛选后发起搜索
Overview 表虽然只给数量,但 Hit Count 列可以直接用作排除策略:把命中数过多的“噪声函数”排除在查询范围之外,只对命中数低(即更独特、更可能匹配到有意义目标)的函数发起真正的相似函数搜索。
操作步骤:
- 在 Overview 表中,选中所有 Hit Count ≤ 2 的函数行(可用表格过滤或多选)。
- 在选区上右键,执行 Search Selected Functions 操作;按 Confidence 降序 排序查询结果,验证
demangler_gnu_v2_41位于列表靠后的位置。
这一步对应的工具栏/右键动作在 BSimOverviewProvider.createActions() 中定义:
new ActionBuilder("Overview BSim Search From Dialog", getOwner())
.popupMenuPath("Search Selected Functions...")
...
.onAction(c -> initialBSimSearch(true))
.buildAndInstallLocal(this);
new ActionBuilder("Overview BSim Search", getOwner())
.popupMenuPath("Search Selected Functions")
...
.onAction(c -> initialBSimSearch(false))
.buildAndInstallLocal(this);
两个动作的区别在于是否弹出查询对话框:不带 ... 的 “Search Selected Functions” 直接使用上次使用的服务器与设置(initialBSimSearch(false))立即执行;带 ... 的变体先打开 BSim 搜索对话框以便修改阈值与过滤器。实现上,选区被转换为函数入口地址列表后交给 plugin.doBSimSearch(program, selectedFunctionAddresses, showDialog),走的是与主菜单 “Search Functions...” 相同的 SearchTask 通道——此时 setMaximumResults 和过滤器都会正常生效,这正是练习二相对 Overview 查询多出约束能力的原因。
练习三:用 Vector Hash 判定“签名相同”
假设 Overview 表中 foo 与 bar 的 Hit Count 相同,存在两种可能:
foo与bar的特征向量不同,只是碰巧匹配数量相同;foo与bar拥有同一个特征向量(即完全相同的 BSim 签名)。
为了区分这两种情况,可以启用可选列 Vector Hash:
- 在 Overview 表中通过列选择器启用 Vector Hash 列;
- 找到两个 Vector Hash 相同的函数;
- 选中这两行,点击 BSim Overview 工具栏的 Make Selection 图标
(Icons.MAKE_SELECTION_ICON),把选区转移到 Listing 视图; - 在 Listing 中右键执行 Function -> Compare Function(s);
- 在弹出的函数比较窗口中,验证这两个函数确实应当拥有相同的 BSim 签名。
源码中,“两行哈希相同 ⇔ 特征向量相同” 这一语义由 BSimOverviewRowObject 的构造 保证:哈希直接对函数签名记录中的 LSH 向量调用 calcUniqueHash() 计算,是对向量内容的唯一性摘要。因此 Vector Hash 相等是判定“同签名”的快速充分依据,而工具栏的 Make Selection 动作(makeSelection())通过 GoToService 跳转到首个选中地址并广播 ProgramSelectionPluginEvent,让 Listing 获得同样的函数选择,从而无缝衔接 Compare Function 操作。
实操前提与小结
执行以上练习需要满足的前提:
- 已启用 BSim 功能并配置好服务器(BSim -> Manage Servers),数据库中已摄入相关可执行文件(如
postgres、含demangler_gnu_v2_41的库等),具体摄入流程参见教程其他章节(如 Creating Database From GUI、Enabling); - Overview 插件同一时间只允许一个 BSim 查询在后台运行(
checkBusy()会提示 “Only one BSim query permitted at a time!”)。
小结:Overview Query 是 BSim 工作流中“先普查、后精查”的第一步——它用 Hit Count + Self Significance 快速标出重复度极高、查询价值低的函数;练习二展示了如何把这种统计信息转化为查询范围过滤;练习三则利用 Vector Hash 这一隐藏列完成签名级判重。掌握了这三点后,你可以进一步学习带过滤器与每函数匹配上限的常规查询。下一节:Queries and Filters。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
