首页
/ Ghidra BSim 命令行实战:用 bsim 工具生成、提交与管理 BSim 签名数据库

Ghidra BSim 命令行实战:用 bsim 工具生成、提交与管理 BSim 签名数据库

2026-09-04 15:09:29作者:董灵辛Dennis

本文以 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.javaprocessSigAndUpdateOptionsdoGenerateSigs 方法可以看到,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.xmlmedium_32.xmlmedium_64.xmlmedium_cpool.xmlmedium_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)

补充规则(均来自源码与官方帮助):

  • 需要定位具体可执行文件的命令(deletelistfuncsdumpsigslistexesgetexecount)必须提供 --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 为准。

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