Ghidra BSim 命令行实战:用 bsim 工具生成、提交与管理 BSim 签名数据库
本文以 Ghidra 官方教程文档 BSim Databases from the Command Line 为主体,完整讲解分布包 support 目录中 bsim 命令行工具的核心工作流:从 Ghidra 项目中生成 BSim 签名文件(generatesigs)、将签名提交入库(commitsigs)、创建数据库(createdatabase),以及可执行文件分类与函数标签的管理(addexecategory / addfunctiontag)。读完并结合 BSimLaunchable.java 源码,你能掌握 BSim 离线入库的完整操作细节、URL 格式规范和每个子命令的可用选项边界。
bsim 工具定位:一条命令覆盖所有数据库后端
bsim 是位于 Ghidra 分发(distribution)support 目录下的命令行工具,用于创建、填充和管理 BSim 数据库。它对所有 BSim 数据库后端(H2 文件库、PostgreSQL、Elasticsearch)通用。
两个基本使用事实:
bsim不带参数运行时,会打印详细的用法说明(usage message);- 它通过子命令(subcommand)工作,每个子命令有各自受限的选项集合——源码 BSimLaunchable.java 中通过
ALLOWED_OPTION_MAP为每个命令显式声明了允许选项,不合法的选项组合会直接抛出IllegalArgumentException,这也是命令行拼错时报错的直接来源。
从源码的 COMMAND_SET 看,bsim 实际提供的子命令远多于教程示例,完整清单为:
| 子命令 | 作用 |
|---|---|
createdatabase / dropdatabase |
创建 / 删除数据库(删除支持 --force 跳过确认) |
setmetadata / getmetadata |
修改 / 查看数据库全局 name、owner、description 元数据 |
addexecategory / addfunctiontag |
登记新的可执行文件分类 / 函数标签 |
dropindex / rebuildindex / prewarm |
索引管理(PostgreSQL 场景,H2 不支持) |
generatesigs / commitsigs |
生成签名 XML 文件 / 将签名文件提交入库 |
generateupdates / commitupdates |
仅更新元数据(名称、标签、分类等,不动签名)/ 提交更新 |
listexes / getexecount / delete |
列出可执行文件记录 / 计数 / 删除某可执行文件的全部记录 |
listfuncs / dumpsigs |
列出某可执行文件的函数记录 / 导出签名 XML |
两类 URL:ghidra 项目地址与 BSim 数据库地址
BSim 命令行围绕两种 URL 展开,官方帮助文档 CommandLineReference.html 对格式有严格约定:
本地 Ghidra 项目 URL(ghidra: 协议)
ghidra:[/<directory_path>]/<project_name>[?/<folder_path>]
- 本地项目的 URL 只有一个正斜杠(即
ghidra:/...,不是ghidra://)——这是教程特别强调的易错点; - 目录路径必须是包含
*.gpr定位文件的绝对路径,项目名不含.gpr/.rep后缀;Windows 下路径需带盘符(如ghidra:/C:/mydir/myproject?/folderA/folderB)。
BSim 数据库 URL
| 后端 | URL 格式 |
|---|---|
| H2 文件库 | file:[/<directory_path>]/<dbname>(指向 *.mv.db 文件,但不含扩展名) |
| PostgreSQL | postgresql://[<username>@]<hostname>[:<port>]/<dbname> |
| Elasticsearch | https://[<username>@]<hostname>[:<port>]/<dbname>(elastic:// 等价) |
同样注意:本地 file: URL 协议后只有单个正斜杠(file:/...)。
生成签名文件:generatesigs
BSim 入库的第一步,是从 Ghidra 项目中的二进制生成签名文件。签名文件是 XML 文件,包含 BSim 服务器所需的函数签名(BSim signature)与元数据。
前置条件:先退出 Ghidra
教程给出了明确的“Important”警告,执行后续步骤前最简做法是先退出 Ghidra,原因有二:
- H2 后端数据库同一时间只能被一个进程访问;
- 如果你已在 Ghidra 中打开了
postgres_object_files项目,签名生成会失败——非共享(local)项目在打开期间处于锁定状态,锁会阻止签名生成进程访问该项目。
操作步骤
在 shell 中执行(Windows 下请相应调整):
cd <ghidra_install_dir>/support
mkdir ~/bsim_sigs
./bsim generatesigs ghidra:/<ghidra_project_dir>/postgres_object_files ~/bsim_sigs --bsim file:/<database_dir>/example
参数逐项解析:
ghidra:/<ghidra_project_dir>/postgres_object_files:持有已分析二进制的本地项目 URL(再次注意只有一个正斜杠);~/bsim_sigs:签名 XML 文件的输出目录;--bsim file:/<database_dir>/example:BSim 数据库 URL。该命令不会向数据库写入任何签名,但会向数据库查询其配置(如 LSH 权重等模板设置)。
源码视角:generatesigs 的三种形态
从 BSimLaunchable.java 的 processSigAndUpdateOptions 与 doGenerateSigs 方法可以看到,generatesigs 的选项约束比教程示例更丰富:
- 必须且只能提供
--bsim <bsimURL>与--config <template>之一(二者同时出现会报错):--bsim:从已有数据库读取配置;--config:在没有数据库的情况下,用建库模板(如medium_nosize)直接生成签名文件;
- 若不指定输出目录,则隐含启用 commit——签名直接写入数据库(使用临时 XML 目录);此时
--overwrite不允许出现; --commit仅在同时给出 XML 目录和--bsim时有效,表示生成后顺带提交入库;--overwrite仅在给出 XML 目录时允许,用于覆盖同名冲突的签名文件。
即官方帮助中列出的三种合法形态:
bsim generatesigs <ghidraURL> </xmldirectory> --config|-c <config_template> [--overwrite]
bsim generatesigs <ghidraURL> </xmldirectory> --bsim|-b <bsimURL> [--commit] [--overwrite]
bsim generatesigs <ghidraURL> --bsim|-b <bsimURL>
提交签名文件:commitsigs
签名生成完毕后,用以下命令将其提交到 BSim 数据库(仍在 support 目录中):
./bsim commitsigs file:/<database_dir>/example ~/bsim_sigs
签名成功入库后,重新启动 Ghidra 即可在 BSim 客户端中查询。源码层面,doCommitSigs 会先校验目录存在且确实是目录(checkDirectory),再调用 BulkSignatures.sendXmlToQueryServer 完成入库。commitsigs 支持两个选项:
--md5 <hash>:仅提交指定 MD5 可执行文件相关的签名;--override <ghidraURL>:覆盖签名 XML 中在生成阶段记录的 Ghidra 仓库/项目 URL——这在项目迁移、目录变化后很有用。
创建数据库:createdatabase 与模板 medium_nosize
教程的练习流程复用了已有的 example 数据库,但如果没有通过 CreateH2BSimDatabaseScript.java 创建过它,完全可以用命令行替代:
./bsim createdatabase file:/<database_dir>/example medium_nosize
这里 medium_nosize 是数据库模板,两个词各有含义:
- "medium"(对比 "large"):影响 LSH 向量索引的规模(medium 面向约千万级函数向量,large 面向亿级),对 H2 数据库无实际意义;
- "nosize":4 字节及以上的 varnode 尺寸差异不纳入 BSim 特征向量——这是允许 32 位与 64 位代码互相匹配的必要设置。
仓库中可以直接读到模板的真实内容,medium_nosize.xml:
<dbconfig>
<info>
<name>Medium No Size</name>
<owner>Example Owner</owner>
<description>A medium sized (~10 million functions) database tuned for executables with different address/register sizes</description>
...
<settings>0x4d</settings>
</info>
<k>17</k>
<L>146</L>
<weightsfile>lshweights_nosize.xml</weightsfile>
</dbconfig>
其中的 <k>/<L> 是 LSH 索引参数,weightsfile 指向特征权重文件(nosize 模板对应 lshweights_nosize.xml,即尺寸特征被降权的权重集)。Ghidra/Features/BSim/data 目录下还内置了其他标准模板:large_32.xml、medium_32.xml、medium_64.xml、medium_cpool.xml、medium_nosize.xml。
另外两点值得注意:
createdatabase同样适用于 PostgreSQL 或 Elasticsearch 服务器(前提是服务器已配置并运行),即该命令跨后端通用;- 从源码看,
createdatabase还支持--name/--owner/--description设置数据库元数据,以及--nocallgraph关闭函数间调用关系(call relationships)的存储,默认为存储。
可执行文件分类与函数标签:addexecategory 与 addfunctiontag
BSim 数据库可以记录两类用户自定义元数据,用作查询时的过滤元素:
- Executable Categories(可执行文件分类):记录在可执行文件级别,例如把查询限定在分类为
OPEN_SOURCE的可执行文件范围内; - Function Tags(函数标签):记录在函数级别,例如只搜索被标记为
COMPRESSION_FUNCTIONS的函数。
实现机制上,BSim 的 executable categories 基于 Ghidra 的 program properties,function tags 对应 Ghidra 的函数标签。属性和标签在 Ghidra 中都有独立于 BSim 的用途,因此要让 BSim 记录某个分类或标签,必须显式声明。
声明一个新的可执行文件分类:
./bsim addexecategory file:/<database_dir>/example ORIGIN
(可选的 --date 选项表示该分类承载日期/时间信息。)声明函数标签的语法为 ./bsim addfunctiontag <bsimURL> <tag_name>。
对应地,给程序设置分类值使用的是 Ghidra 脚本 SetExecutableCategoryScript.java。阅读该脚本源码可以看到它的全部实现:通过 Options opts = currentProgram.getOptions(Program.PROGRAM_INFO) 取得程序属性选项,再调用 opts.setString(name, value) 写入一对属性名/值——这正是教程所说“BSim 分类经由 program properties 实现”的源码印证。脚本运行时弹出输入框要求填写 Property Name 与 Property Value,二者均不允许为空。
一个重要的时序语义:addexecategory / addfunctiontag 只影响之后的入库命令,已经入库的可执行文件/函数不受影响;如需补录旧数据,需要用 generateupdates / commitupdates 命令重新生成并更新元数据(签名本身不变)。
选项速查:从源码提取的命令-选项矩阵
BSimLaunchable 源码为每个子命令声明了白名单选项,整理如下(- 表示该命令无额外选项):
| 子命令 | 允许的选项 |
|---|---|
createdatabase |
--name -n、--owner -o、--description -d、--nocallgraph |
dropdatabase |
--force |
setmetadata |
--name、--owner、--description |
getmetadata |
- |
addexecategory |
--date |
addfunctiontag |
- |
generatesigs / generateupdates |
--config -c、--bsim -b(二选一)、--overwrite、--commit |
commitsigs |
--override、--md5 -m |
commitupdates / dropindex / rebuildindex / prewarm |
- |
delete / dumpsigs / listfuncs / listexes / getexecount |
--md5、--name、--arch -a、--compiler、--limit -l(listexes)、--sortcol -s(listexes)、--includelibs、--printselfsig / --callgraph / --printjustexe / --maxfunc(listfuncs) |
补充规则(均来自源码与官方帮助):
- 需要定位具体可执行文件的命令(
delete、listfuncs、dumpsigs、listexes、getexecount)必须提供--md5或--name之一;使用--md5时不允许再附加--name/--arch/--compiler; - 需要取值的选项可用
--option value或--option=value两种写法; - 全局选项
--user-u(以某用户身份连接)与--cert(PKI 认证证书路径)适用于所有命令; - 常用短选项映射:
-a→--arch、-b→--bsim、-c→--config、-d→--description、-l→--limit、-m→--md5、-n→--name、-o→--owner、-s→--sortcol、-u→--user; listexes默认最多列出 20 条(--limit 0表示不限制);listfuncs默认上限 1000 个函数。
小结与延伸
至此,BSim 离线入库的完整命令行链路为:(可选)createdatabase 建库 → generatesigs 从 Ghidra 项目生成签名 XML → commitsigs 提交入库 → (可选)addexecategory/addfunctiontag 登记过滤维度。其中 H2 后端的单进程访问限制与本地项目锁,是实操中最容易踩的两个坑。
教程的下一章 Evaluating Matches and Applying Information 将讲解签名入库后如何在 Ghidra 中查询与比对匹配结果;BSim 的整体原理(行为相似度、余弦相似度、LSH 索引)与三种数据库后端的取舍,可参考 BSimTutorial_Intro.md;更完整的命令参考则以 Ghidra 帮助页 Command-Line Utility Reference 为准。
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