首页
/ Ghidra BSim 过滤机制详解:服务器端与客户端过滤器的工作原理与实战演练

Ghidra BSim 过滤机制详解:服务器端与客户端过滤器的工作原理与实战演练

2026-09-06 20:42:07作者:傅爽业Veleda

本篇技术指南聚焦 Ghidra BSim(二进制相似性匹配)功能的过滤器体系:讲解 BSim Search 对话框中 Filters 下拉提供的服务器端过滤器如何生成查询条件、结果表格上 Filter Results 客户端过滤器如何即时裁剪展示,并结合 BSim 模块源码逐一解析每种过滤器类型对应的 SQL/Elasticsearch 子句生成逻辑。读完本篇,你可以准确运用各类过滤器缩小相似函数搜索结果的范围、看懂过滤器在查询协议中的落地形式,并完成教程配套的过滤实操演练。

BSim Search 对话框(含 Filters 过滤器区域)

一、两级过滤器:服务器端与客户端

BSim 查询可以施加多种过滤器,涉及名称、架构、编译器、入库日期、用户自定义可执行文件类别(executable categories)及其他属性。过滤器分为两个层级,二者作用域完全不同:

  • 服务器端过滤器(Server-side):作用于 BSim 服务器返回给 Ghidra 的查询结果本身。在 BSim Search 对话框的 Filters 下拉中施加,会直接改变查询协议中携带的过滤条件。要"撤销"一个服务器端过滤器,只能重新发起一次不带该过滤器的 BSim 查询——它不是对已有结果的事后裁剪。
  • 客户端过滤器(Client-side):作用于 BSim Search 结果表格的展示,可以随时添加、随时移除,对应结果窗口工具栏上的 Filter Results 按钮。

源码中这两级 UI 分别落在两处:

  • 结果表格的 Search Info(查看已施加的服务器端过滤器)与 Filter Results(打开客户端过滤面板)两个工具栏动作,定义在 BSimSearchResultsProvider.javacreateActions() 中,分别使用信息图标(Icons.INFO_ICON)和过滤图标(Icons.CONFIGURE_FILTER_ICON);
  • Search 对话框侧的过滤器编辑区由 BSimFilterPanel.java 承载:面板为每条过滤器生成一个 FilterWidget(左侧类型下拉框 + 中部值编辑器 + 右侧删除按钮),右侧提供 Add Filter 按钮追加过滤器行。getFilterSet() 只收集"非空白且值有效"的条目,hasValidFilters() 则在查询前校验所有非空白过滤器都具有合法取值。

二、服务器端过滤器类型全景

BSim Search 对话框 Filters 下拉里可选的类型并非写死在界面上,而是由 BSimFilterType.java 统一构建。buildFilterBasis()L300-L316)给出基础过滤器清单,generateBsimFilters()L324-L386)再根据目标数据库的描述信息(DatabaseInformation)动态增补。基础清单与动态增补项如下("显示名称"即下拉框中的 label,"XML 值"是过滤器序列化的类型标签,"输入提示"是值输入框中的占位示例):

过滤器(GUI 显示名) XML 值 输入提示(示例取值) 说明
Executable name equals nameequals executable name 可执行文件名精确匹配
Executable name does not equal namenotequal executable name 可执行文件名排除(教程演练即用此项)
MD5 equals / MD5 does not equal md5equals / md5notequal 32-digit hex value 按文件 MD5 精确匹配/排除
Architecture equals / does not equal archequals / archnotequal x86:LE:64:default 按架构标识匹配/排除
Compiler equals / does not equal compequals / compnotequal gcc 按编译器名匹配/排除
Path starts with pathstarts path 按文件路径前缀匹配
Calls external function namedchild external subfunction 子过滤器:要求函数调用图含指定外部函数;仅当数据库追踪了 callgraph 时才出现
Ingest Date is earlier/later than dateearlier / datelater 1974-09-2109/21/1974 按入库日期做前后界;若数据库显式声明了日期列名,则显示名替换为该列名(表中只能容纳一个日期)
<类别名> matches / does not match execatmatches / execatnomatch category value 用户自定义的可执行文件类别,类别清单来自数据库信息(execats
Function tagged as KNOWN_LIBRARY / HAS_UNIMPLEMENTED / HAS_BADDATA functiontag function tag 内置函数标签(位掩码分别为 1/2/4),外加数据库中声明的用户自定义函数标签

值得注意的两个动态行为:

  1. 日期过滤器的列名可被覆盖generateBsimFilters() 中,若 info.dateColumnName 非空,则用它构造定制日期过滤器;否则回退到默认的 "Ingest Date" 列。
  2. 类别与标签过滤器完全由数据库元数据驱动。数据库信息中声明了哪些 execats(可执行文件类别)与 functionTags(函数标签),下拉里就出现多少对应的 matches/does-not-match 过滤器;用户标签的位标志从 RESERVED_BITS 之后开始按位递增分配。

多值取值与 OR/AND 组合语义

每个 FilterWidget 的值编辑器可返回一个字符串列表——多数过滤器允许同一类型填多个值,最终组合方式由 BSimFilterType.orMultipleEntries() 决定(L188-L202buildSQLCombinedClause()):

  • 默认(orMultipleEntries() == true):同一过滤器的多个取值用 OR 连接(SQL 端为 OR,Elasticsearch 脚本端为 ||);
  • 部分"排除型"过滤器覆写为 false,例如 NotExecutableNameBSimFilterType.java:多个"不等于"值必须 AND 连接才符合"全部排除"的语义。

三、过滤器如何变成查询:SQL 与 Elasticsearch 双通道

每个过滤器类型的抽象契约定义在 BSimFilterType.java 中,核心方法有三类:

  • generateIDSQLResolution(FilterAtom) / gatherSQLEffect(...):面向 PostgreSQL 后端,把过滤器值转换为 WHERE 子句;
  • gatherElasticEffect(...):面向 Elasticsearch 后端,生成对应的查询 JSON 片段;
  • evaluate(ExecutableRecord, String):对单条可执行文件记录做本地判定,供客户端过滤使用。

以教程演练中用到的"Executable name does not equal"为例,NotExecutableNameBSimFilterType.javagatherSQLEffect() 生成 exetable.name_exec != '...'(值经 Utils.escapeLiteral 转义),其 gatherElasticEffect() 生成 "must_not": { "term": { "name_exec": "..." } };而正向版本 ExecutableNameBSimFilterType.java 则分别生成 exetable.name_exec = '...'"term" 匹配。二者都无需 ID 解析(generateIDSQLResolution 返回 null),因为可执行文件名本身就是可直接比较的字符串列。

在对话框一侧,所有过滤器行最终由 BSimFilterSet.javagetBSimFilter() 收敛:遍历每条 FilterEntry(类型 + 取值列表),把每个取值调用 bsimFilter.addAtom(filterType, value.trim()) 打包为协议层的 BSimFilter,随查询请求发往 BSim 服务器。过滤器还可通过 xmlval 完成 XML 序列化(saveXml()),从而随查询设置一起保存与还原。

四、教程演练:用名称过滤器排除干扰可执行文件

以下演练完整继承自 BSim 教程 BSimTutorial_Filters.md,其前提是先阅读 BSim 启用指南 启用了 BSim 扩展,并已建立包含 postgresdemangler_gnu_v2_41 等可执行文件的测试库(仓库中 demangler_gnu_v2_41 的源码位于 GPL/DMG/src/demangler_gnu_v2_41/,是 GNU demangler 移植模块的一部分):

  1. 选中 postgres 中的全部函数,打开 BSim Search 对话框;
  2. Filters 下拉中施加一个 Executable name does not equal 过滤器,排除名称填 demangler_gnu_v2_41
  3. 执行查询,验证匹配结果的可执行文件列表中不再出现 demangler_gnu_v2_41——因为该条件在服务器端就把该文件的函数向量排除出了结果集;
  4. 点击结果工具栏的 Search Info 按钮(信息图标),查看本次查询实际携带的服务器端过滤器,核对其内容与第 2 步一致;
  5. 点击 Filter Results 按钮(过滤图标),对结果表格施加客户端过滤器,随意尝试添加与移除,体会其与服务器端过滤器"可即时撤销"的差异。

对比两级的行为差异:第 5 步的客户端过滤器只隐藏表格行,查询结果集并未改变;而第 2 步的服务器端过滤器一旦执行,若需恢复 demangler_gnu_v2_41 的结果,必须回到 Search 对话框移除该过滤行后重新查询。

五、相关章节与源码索引

继续深入可参考同一教程系列的相邻章节:BSim 基础查询查询概述可执行文件结果,以及本篇的下一节 脚本与可视化。涉及 BSim 功能启用与数据库构建,另见 通过 GUI 创建数据库BSim 命令行

本篇引用的关键源码文件(均在 BSim 特性模块下):

登录后查看全文
热门项目推荐
相关项目推荐