Ghidra BSim 教程:用命令行批量构建 PostgreSQL 对象文件并以 Headless 方式分析入库
本文基于 Ghidra 官方 BSim 教程中的 Ghidra Analysis from the Command Line 一节展开。BSim(Behavioral Similarity,行为相似度)用于在大规模二进制集合中搜索"相似但不完全相同"的函数,而使用前必须先用一批真实二进制填充 BSim 数据库。本文介绍如何用 BSim 自带的 make-postgres.sh 脚本构建 PostgreSQL 并收割所需的对象文件,再用 Ghidra 的 Headless Analyzer(analyzeHeadless)批量导入分析,为后续 BSim 查询准备好数据源。读完后你能独立完成"准备样例二进制 → 批量导入分析 → 产出 Ghidra 项目"这一完整流水线。
1. 背景:为什么需要一批二进制,为什么选 PostgreSQL
BSim 的工作方式为二进制中的每个函数生成一个"特征向量"(feature vector):向量由 Ghidra 反编译器产生,每个特征对应一小段数据流/控制流,且经过归一化处理——常量值、寄存器名、数据类型等属性被刻意剔除,因此不同编译器、不同架构、源码小幅改动产生的等价代码往往得到相同或极相近的向量(详见 BSimTutorial_Intro.md)。向量的相似度比较基于余弦相似度,大规模库还会用局部敏感哈希(LSH)索引加速检索。
要让 BSim 查询有意义,数据库里得有足够多的函数向量。官方教程需要"一组一致的样例二进制",但不想向 Ghidra 发行版里塞几十上百个可执行文件。BSim 插件本身带有一个构建 PostgreSQL 后端的脚本,而该构建过程天然会产生数百个目标文件(*.o),正好可以"顺手收割"这些文件作为教程的二进制语料。
原文档中有两条重要说明,务必理解:
- 教程本身不使用 PostgreSQL。构建 PostgreSQL 只是为了拿到它编译出的目标文件;教程后续继续用 H2 作为 BSim 数据库后端,不运行任何 PostgreSQL 代码;
- 这些文件必须在 Linux 或 macOS 上构建。Windows 用户可以在 Linux 虚拟机中完成构建,然后把产物拷贝到 Windows 机器继续(见第 4 节)。
2. 构建 PostgreSQL 并收割对象文件
在 shell 中依次执行以下命令(<ghidra_install_dir> 为 Ghidra 安装目录):
cd <ghidra_install_dir>/Ghidra/Features/BSim
export CFLAGS="-O2 -g"
./support/make-postgres.sh
mkdir ~/postgres_object_files
cd build
find . -name p*o -size +100000c -size -700000c -exec cp {} ~/postgres_object_files/ \;
cd os/linux_x86_64/postgresql/bin
strip -s postgres
逐步解读:
cd <ghidra_install_dir>/Ghidra/Features/BSim:进入 BSim 功能模块目录,即仓库中的 Ghidra/Features/BSim,构建脚本位于其 support/make-postgres.sh。export CFLAGS="-O2 -g":指定优化级别-O2并保留调试符号-g。这对 BSim 语料很关键:优化等级会影响反编译结果的形态,统一 CFLAGS 可保证教程二进制具有一致性。./support/make-postgres.sh:构建 PostgreSQL(详见第 3 节脚本内部流程)。mkdir ~/postgres_object_files:在用户主目录创建语料收集目录。cd build && find . -name p*o -size +100000c -size -700000c -exec cp {} ~/postgres_object_files/ \;:这条find是"收割"命令,三个条件缺一不可:-name p*o:PostgreSQL 的编译产物命名习惯使其目标文件以p开头、.o结尾(如parse_expr.o);-size +100000c -size -700000c:只保留大小在 100 KB 到 700 KB 之间的文件——过小的目标文件(初始化/桩文件)和过大的目标文件(如巨型代码生成产物)对教程演示价值不高,这个区间筛出"体量适中、函数数量可观"的样本;-exec cp ... \;:把匹配文件逐个复制到~/postgres_object_files/。
cd os/linux_x86_64/postgresql/bin && strip -s postgres:进入构建产物目录(x86_64 Linux 平台),用strip -s剥离postgres可执行文件的符号表,使其成为一个"更贴近实战"的被分析对象(无符号时可考察 BSim 对未命名函数的识别能力)。
注意:教程可能还需要安装额外的系统依赖包、或调整构建选项,PostgreSQL 才能构建成功;脚本头部注释也提示了这一点,构建报错信息通常具有自解释性,可参见 make-postgres.sh 中的注释说明。
3.1 make-postgres.sh 内部做了什么(源码级补充)
从 make-postgres.sh 的源码结构看,脚本并不"裸编译",流程如下(行号以仓库文件为准):
- 源码包定位(L49-L66):脚本固定构建
postgresql-15.18,按顺序在三个位置查找postgresql-15.18.tar.gz:开发环境的ghidra.bin仓库路径(<repo>/ghidra.bin/Ghidra/Features/BSim/)、开发依赖目录Ghidra/dependencies/BSim/、以及发行版内Ghidra/Features/BSim/support/。都找不到则打印Postgres source bundle not found并退出。因此若在发行版中运行,需先将 PostgreSQL 15.18 源码包放入上述目录之一。 - 配置选项(L51):默认
POSTGRES_CONFIG_OPTIONS="--disable-rpath --with-openssl",可在脚本顶部按需调整(例如改为不带 OpenSSL 构建)。 - 平台探测(L68-L104):通过
uname -s/uname -m区分mac_x86_64、mac_arm_64、linux_x86_64、linux_arm_64;macOS 分支会设置MACOSX_DEPLOYMENT_TARGET=10.5、ARCHFLAGS,并把 Homebrew(/usr/local或/opt/homebrew)的 include/lib 目录追加进 configure 选项;不支持的平台直接报错退出——这就是"必须在 Linux/macOS 上构建"限制的来源。 - 构建与安装(L108-L131):源码解压到
build/postgresql-15.18,执行make distclean→./configure --prefix=<build/os>/<平台>/postgresql→make install,并额外安装contrib/pg_prewarm组件。 - lshvector 插件构建(L133-L150):将
src/lshvector与src/lshvector/c的源码拷入build/lshvector,用make -f Makefile.lshvector install PG_CONFIG=<安装目录>/bin/pg_config编译安装 BSim 的 PostgreSQL 向量索引插件。
也就是说,一次 make-postgres.sh 同时完成两件事:构建出教程需要的语料(中间产物即 build/ 下的数百个 .o 文件和最终的 postgres 可执行文件),以及构建 BSim PostgreSQL 后端所需的 lshvector 插件。构建结束后,所有产物落在 build/ 目录:对象文件散布在各源码子目录中,最终二进制位于 build/os/<平台>/postgresql/bin/postgres。
3. 用 Headless Analyzer 导入并分析语料
有了可执行文件后,用 Ghidra 的 Headless Analyzer(无头分析器)做批量分析。教程原文明确指出:Headless Analyzer 与 BSim 是两个独立组件,但它是分析"大量二进制"唯一可行的方式——GUI 方式无法高效处理上百个文件的导入与分析。
在 Linux 上执行:
cd <ghidra_install_dir>/support
./analyzeHeadless <ghidra_project_dir> postgres_object_files -import ~/postgres_object_files/*
(Windows 上改用 analyzeHeadless.bat 并相应调整路径。)
这条命令的效果:在 <ghidra_project_dir> 目录下创建(或打开)一个名为 postgres_object_files 的本地 Ghidra 项目,将 ~/postgres_object_files/ 中全部对象文件通配导入,并完成默认自动分析。之后 BSim 就可以基于该项目中的程序提取函数特征向量、填充 BSim 数据库。
在仓库中,该脚本对应 Ghidra/RuntimeScripts/support/analyzeHeadless(Windows 版为 analyzeHeadless.bat),完整参数文档见 analyzeHeadlessREADME.md(发行版中随附于 support/ 目录)。
3.1 与本次操作直接相关的参数要点
结合 analyzeHeadlessREADME.md,本次命令涉及及常用的参数有:
| 参数 | 说明 |
|---|---|
<project_location> <project_name> |
项目所在目录与项目名;-import 模式下若项目不存在会在新目录中创建 |
-import <file/dir>+ |
导入一个或多个文件/目录;通配符由操作系统 shell 展开后再交给 Headless Analyzer。批量导入时,以 . 开头的隐藏文件默认被忽略 |
-noanalysis |
抑制自动分析(默认分析是开启的,本教程需要默认开启) |
-processor <languageID> |
指定处理器语言,如 x86:LE:32:default;缺省时由文件头信息自动识别 |
-cspec <compilerSpecID> |
指定编译器规范(必须与 -processor 一起使用) |
-overwrite |
导入时覆盖项目中同名的已有文件(否则跳过) |
-recursive [<depth>] |
递归导入目录(本例目录为扁平结构,不需要) |
-deleteProject |
处理完成后删除本次会话新建的项目 |
-log / -scriptlog |
分析日志与脚本日志输出路径;默认分别写入用户目录下的 application.log / script.log |
几个值得注意的约束(对批量任务尤其重要):
- 项目互斥:若目标项目已在 Ghidra GUI 中打开,Headless Analyzer 可能无法运行;
- 通配符规则:
-import模式的通配符由底层 shell 展开(因此~/postgres_object_files/*依赖 shell 展开;Windows 通配符只能展开到文件,Unix 还可展开目录); - 日志排查:批量导入数百个文件后,可检查默认日志确认每个文件的导入与分析结果。
4. Windows 用户的衔接方式
由于构建步骤限定在 Linux/macOS,Windows 用户的操作流程是:
- 在 Linux(或 Linux 虚拟机/容器)中完成第 2 节全部构建与收割步骤;
- 将
~/postgres_object_files目录以及 strip 后的postgres可执行文件传输到 Windows 机器; - 在 Windows 上执行
analyzeHeadless.bat <ghidra_project_dir> postgres_object_files -import <语料目录>\*(注意 Windows 路径写法与目录分隔符)。
5. 小结与下一步
本篇完成了 BSim 教程数据准备阶段:用 make-postgres.sh 构建 PostgreSQL 15.18、用带大小过滤的 find 收割 100 KB–700 KB 区间的 p*.o 目标文件、strip 出 postgres 可执行文件,再通过 analyzeHeadless 把它们统一导入 postgres_object_files 本地项目并完成分析。这些经过分析的程序正是后续 BSim 数据库的语料来源——BSim 会对它们做反编译、提取函数特征向量并按 H2 后端建库。
教程的下一节将介绍如何从命令行使用 BSim 本体:BSimTutorial_BSim_Command_Line.md;关于 BSim 原理与三种数据库后端(PostgreSQL / Elasticsearch / H2)的选型背景,可参考 BSimTutorial_Intro.md。
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 StartedRust0622
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