首页
/ Ghidra BSim 教程:用命令行批量构建 PostgreSQL 对象文件并以 Headless 方式分析入库

Ghidra BSim 教程:用命令行批量构建 PostgreSQL 对象文件并以 Headless 方式分析入库

2026-09-04 17:52:38作者:鲍丁臣Ursa

本文基于 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

逐步解读:

  1. cd <ghidra_install_dir>/Ghidra/Features/BSim:进入 BSim 功能模块目录,即仓库中的 Ghidra/Features/BSim,构建脚本位于其 support/make-postgres.sh
  2. export CFLAGS="-O2 -g":指定优化级别 -O2 并保留调试符号 -g。这对 BSim 语料很关键:优化等级会影响反编译结果的形态,统一 CFLAGS 可保证教程二进制具有一致性。
  3. ./support/make-postgres.sh:构建 PostgreSQL(详见第 3 节脚本内部流程)。
  4. mkdir ~/postgres_object_files:在用户主目录创建语料收集目录。
  5. 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/
  6. 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_64mac_arm_64linux_x86_64linux_arm_64;macOS 分支会设置 MACOSX_DEPLOYMENT_TARGET=10.5ARCHFLAGS,并把 Homebrew(/usr/local/opt/homebrew)的 include/lib 目录追加进 configure 选项;不支持的平台直接报错退出——这就是"必须在 Linux/macOS 上构建"限制的来源。
  • 构建与安装L108-L131):源码解压到 build/postgresql-15.18,执行 make distclean./configure --prefix=<build/os>/<平台>/postgresqlmake install,并额外安装 contrib/pg_prewarm 组件。
  • lshvector 插件构建L133-L150):将 src/lshvectorsrc/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 用户的操作流程是:

  1. 在 Linux(或 Linux 虚拟机/容器)中完成第 2 节全部构建与收割步骤;
  2. ~/postgres_object_files 目录以及 strip 后的 postgres 可执行文件传输到 Windows 机器;
  3. 在 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

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
983
503
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384