Ghidra BSim 过滤机制详解:服务器端与客户端过滤器的工作原理与实战演练
本篇技术指南聚焦 Ghidra BSim(二进制相似性匹配)功能的过滤器体系:讲解 BSim Search 对话框中 Filters 下拉提供的服务器端过滤器如何生成查询条件、结果表格上 Filter Results 客户端过滤器如何即时裁剪展示,并结合 BSim 模块源码逐一解析每种过滤器类型对应的 SQL/Elasticsearch 子句生成逻辑。读完本篇,你可以准确运用各类过滤器缩小相似函数搜索结果的范围、看懂过滤器在查询协议中的落地形式,并完成教程配套的过滤实操演练。
一、两级过滤器:服务器端与客户端
BSim 查询可以施加多种过滤器,涉及名称、架构、编译器、入库日期、用户自定义可执行文件类别(executable categories)及其他属性。过滤器分为两个层级,二者作用域完全不同:
- 服务器端过滤器(Server-side):作用于 BSim 服务器返回给 Ghidra 的查询结果本身。在 BSim Search 对话框的 Filters 下拉中施加,会直接改变查询协议中携带的过滤条件。要"撤销"一个服务器端过滤器,只能重新发起一次不带该过滤器的 BSim 查询——它不是对已有结果的事后裁剪。
- 客户端过滤器(Client-side):作用于 BSim Search 结果表格的展示,可以随时添加、随时移除,对应结果窗口工具栏上的 Filter Results 按钮。
源码中这两级 UI 分别落在两处:
- 结果表格的 Search Info(查看已施加的服务器端过滤器)与 Filter Results(打开客户端过滤面板)两个工具栏动作,定义在 BSimSearchResultsProvider.java 的
createActions()中,分别使用信息图标(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-21 或 09/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),外加数据库中声明的用户自定义函数标签 |
值得注意的两个动态行为:
- 日期过滤器的列名可被覆盖。
generateBsimFilters()中,若info.dateColumnName非空,则用它构造定制日期过滤器;否则回退到默认的 "Ingest Date" 列。 - 类别与标签过滤器完全由数据库元数据驱动。数据库信息中声明了哪些
execats(可执行文件类别)与functionTags(函数标签),下拉里就出现多少对应的 matches/does-not-match 过滤器;用户标签的位标志从RESERVED_BITS之后开始按位递增分配。
多值取值与 OR/AND 组合语义
每个 FilterWidget 的值编辑器可返回一个字符串列表——多数过滤器允许同一类型填多个值,最终组合方式由 BSimFilterType.orMultipleEntries() 决定(L188-L202 的 buildSQLCombinedClause()):
- 默认(
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.java 的 gatherSQLEffect() 生成 exetable.name_exec != '...'(值经 Utils.escapeLiteral 转义),其 gatherElasticEffect() 生成 "must_not": { "term": { "name_exec": "..." } };而正向版本 ExecutableNameBSimFilterType.java 则分别生成 exetable.name_exec = '...' 与 "term" 匹配。二者都无需 ID 解析(generateIDSQLResolution 返回 null),因为可执行文件名本身就是可直接比较的字符串列。
在对话框一侧,所有过滤器行最终由 BSimFilterSet.java 的 getBSimFilter() 收敛:遍历每条 FilterEntry(类型 + 取值列表),把每个取值调用 bsimFilter.addAtom(filterType, value.trim()) 打包为协议层的 BSimFilter,随查询请求发往 BSim 服务器。过滤器还可通过 xmlval 完成 XML 序列化(saveXml()),从而随查询设置一起保存与还原。
四、教程演练:用名称过滤器排除干扰可执行文件
以下演练完整继承自 BSim 教程 BSimTutorial_Filters.md,其前提是先阅读 BSim 启用指南 启用了 BSim 扩展,并已建立包含 postgres 与 demangler_gnu_v2_41 等可执行文件的测试库(仓库中 demangler_gnu_v2_41 的源码位于 GPL/DMG/src/demangler_gnu_v2_41/,是 GNU demangler 移植模块的一部分):
- 选中
postgres中的全部函数,打开 BSim Search 对话框; - 在 Filters 下拉中施加一个 Executable name does not equal 过滤器,排除名称填
demangler_gnu_v2_41; - 执行查询,验证匹配结果的可执行文件列表中不再出现
demangler_gnu_v2_41——因为该条件在服务器端就把该文件的函数向量排除出了结果集; - 点击结果工具栏的 Search Info 按钮(信息图标),查看本次查询实际携带的服务器端过滤器,核对其内容与第 2 步一致;
- 点击 Filter Results 按钮(过滤图标),对结果表格施加客户端过滤器,随意尝试添加与移除,体会其与服务器端过滤器"可即时撤销"的差异。
对比两级的行为差异:第 5 步的客户端过滤器只隐藏表格行,查询结果集并未改变;而第 2 步的服务器端过滤器一旦执行,若需恢复 demangler_gnu_v2_41 的结果,必须回到 Search 对话框移除该过滤行后重新查询。
五、相关章节与源码索引
继续深入可参考同一教程系列的相邻章节:BSim 基础查询、查询概述、可执行文件结果,以及本篇的下一节 脚本与可视化。涉及 BSim 功能启用与数据库构建,另见 通过 GUI 创建数据库 与 BSim 命令行。
本篇引用的关键源码文件(均在 BSim 特性模块下):
- BSimFilterType.java —— 过滤器类型抽象基类、基础清单与动态生成;
- ExecutableNameBSimFilterType.java、NotExecutableNameBSimFilterType.java —— 名称匹配/排除过滤器的 SQL 与 Elastic 子句生成;
- BSimFilterPanel.java、FilterWidget.java、BSimFilterSet.java —— Search 对话框中过滤器编辑区的 UI 与状态管理;
- BSimSearchResultsProvider.java —— 结果窗口的 Search Info / Filter Results 动作定义。
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 StartedRust0624
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
