关于 ghidra-rpc
ghidra-rpc 是用于调用 Ghidra 逆向分析能力的 CLI 技能,通过守护进程提供操作接口。它涵盖二进制分析、反编译、搜索和程序检查,命令以 JSON 输出。
主要功能
- 01启动、停止和检查守护进程
- 02加载并分析二进制文件
- 03列出函数、导入项和符号
- 04反编译函数并检查 P-code
- 05搜索字节、字符串和反编译代码
- 06读取内存并反汇编指令
适用场景
- 01分析已导入的可执行文件
- 02在反编译函数中搜索代码模式
- 03检查交叉引用和函数结构
- 04读取或修改二进制内存
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cellebrite-labs/ ghidra-rpc --skill ghidra-rpc安装后在 Claude Code 中输入/ghidra-rpc确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CLAUDE.md.gitignoreREADME.mdCHANGELOG.mdAGENTS.md.github/workflows/integration.ymltests.yml.pi/prompts/process-feedback.mddocs/install.mdquickstart.mdtroubleshooting.mdinternals.mddocs/flows/android-apk.mdbinary-audit.mdvulnerability-research.mdpatch-analysis.mdghidra_rpc/__init__.pycli.pydaemon.pyclient.pyghidra_rpc/server/__init__.pylauncher.pymain.pycontext.py_gui_launcher.pyghidra_rpc/server/tools/analysis.py__init__.pybookmarks.pydisassembly.pycfg.py详细介绍
Ghidra RPC
一个 CLI 守护进程,通过 Unix 域套接字提供 Ghidra 逆向工程功能。
你可以通过 bash 工具运行 ghidra-rpc 命令与之交互——每条命令
都会将 JSON 输出到 stdout。
运行命令
所有 ghidra-rpc 命令都必须在 ghidra-rpc skill 目录中通过 uv run 运行,
该目录包含此 SKILL.md 文件:
cd <skill-dir> && uv run ghidra-rpc <command> ...
前置条件检查
使用任何命令前,请先确认环境已正确配置:
- 守护进程是否正在运行? 运行
uv run ghidra-rpc status --project <path>。如果未运行, 用户需要在单独的终端中启动它:uv run ghidra-rpc start --project /path/to/project.gpr(会阻塞,需由用户手动操作)。--headless标志可跳过 GUI。若要以非阻塞方式或自动 启动,请使用start --detach --headless或restart --headless。这两条命令都接受--timeout SECS(默认值:无头模式为 60 s,GUI 模式为 180 s),并将守护进程输出记录到/tmp/ghidra-rpc-<hash>.log(Windows 上为%LOCALAPPDATA%\ghidra-rpc\ghidra-rpc-<hash>.log)。 - GUI 模式:确认当前打开的是正确项目。 守护进程会将
--project路径 直接传递给 GhidraRun,以便 Ghidra 立即打开指定项目。在 GUI 模式下运行start --detach后,在执行任何分析命令前,请确认已加载正确的项目:
请将返回的二进制文件名称与预期进行核对。如果名称不匹配 (或响应中出现uv run ghidra-rpc list-project-programs --project /path/to/project.gprwarning字段),请停止并让用户在 Ghidra 的 Project 窗口中打开正确的 项目,然后再继续。 - GUI 模式:在 CodeBrowser 中打开二进制文件。 在 GUI 模式下,守护进程会通过正在运行的 CodeBrowser 工具
查找程序。如果二进制文件位于项目中,但当前未在 CodeBrowser 中打开,
list-binaries将返回空结果,所有命令都会因 “Binary not found”而失败。使用list-project-programs查看项目中存储的内容, 然后在 Ghidra 的 Project 窗口中双击该程序以将其打开。 - 是否已设置
GHIDRA_INSTALL_DIR? 如果未设置,守护进程会明确报错。
守护进程启动后,以下所有命令都可以自动运行。如果守护进程意外退出, 命令会尝试根据已保存的会话自动重启它。
命令参考
每条命令都接受 --project <path>(或读取 GHIDRA_RPC_PROJECT 环境变量)。
所有输出均为 JSON。退出代码 0 = 成功,1 = 错误。
项目管理
| 命令 | 说明 | 示例 |
|---|---|---|
ghidra-rpc start --project <gpr> [--headless] [--detach] [--ghidra-install-dir DIR] | 启动守护进程(默认阻塞;--detach 会将其置于后台运行) | ghidra-rpc start -p /tmp/re.gpr --headless --detach |
ghidra-rpc stop --project <gpr> | 停止守护进程 | ghidra-rpc stop -p /tmp/re.gpr |
ghidra-rpc status --project <gpr> | 检查守护进程是否正在运行 | ghidra-rpc status -p /tmp/re.gpr |
status 输出:{running, socket, mode, mode_source, project, binaries}。守护进程运行时,binaries 是已加载二进制文件列表;停止时为 null(一次性健康检查,无需再次调用 list-binaries)。mode_source 在守护进程运行时为
"running";仅从已保存的会话获取模式(守护进程已停止)时为 "session";如果不存在会话,则为 null。
| ghidra-rpc restart --project <gpr> [--headless] [--timeout SECS] [--ghidra-install-dir DIR] | 在后台重启守护进程(使用 --headless 覆盖模式) | ghidra-rpc restart -p /tmp/re.gpr --headless |
| ghidra-rpc list-binaries --project <gpr> | 列出守护进程中已加载的二进制文件 | ghidra-rpc list-binaries -p /tmp/re.gpr |
| ghidra-rpc list-project-programs --project <gpr> | 列出项目仓库中存储的所有程序(读取项目文件夹,而非 CodeBrowser 的实时状态;如果活动的 Ghidra 项目不匹配,则返回 warning) | ghidra-rpc list-project-programs -p /tmp/re.gpr |
| ghidra-rpc save [binary] --project <gpr> | 将程序保存到磁盘(每次写入后也会自动保存) | ghidra-rpc save -p /tmp/re.gpr |
加载与分析
| 命令 | 说明 | 示例 |
|---|---|---|
ghidra-rpc load <path> -p <gpr> [--no-analyze] [--analysis-timeout SECS] | 导入并分析二进制文件 | ghidra-rpc load /usr/bin/target -p /tmp/re.gpr |
ghidra-rpc metadata <binary> -p <gpr> | 二进制文件元数据(架构、位数、格式) | ghidra-rpc metadata target -p /tmp/re.gpr |
load 标志:
--no-analyze- 完全跳过自动分析(速度快;适用于只需要列表,或打算稍后通过 Ghidra GUI 运行分析的情况)。--analysis-timeout SECS- 在指定的实际运行时间限额后中止自动分析(尽力而为);保存二进制文件时会包含限额内已完成的分析结果。
列表
| 命令 | 说明 | 输出结构 |
|---|---|---|
ghidra-rpc functions <binary> [--offset N] [--limit N] [--address-min ADDR] [--address-max ADDR] [--with-body] | 列出函数(分页);--address-min/max 用于服务端范围筛选;--with-body 会添加函数体范围字段 | {functions: [{name, address, signature[, body_min, body_max, body_size]}], count, total, offset} |
ghidra-rpc imports <binary> | 列出导入项 | {imports: [{name, address, library}], count} |
ghidra-rpc exports <binary> | 列出导出项 | {exports: [{name, address}], count} |
ghidra-rpc relocations <binary> [--address ADDR] [--limit N] | 列出重定位表条目 | {relocations: [{address, type, symbol, bytes, status}], count, total} |
ghidra-rpc list-calling-conventions <binary> | 列出该架构有效的调用约定名称 | {conventions: [str], default, count} |
反编译
| 命令 | 说明 | 输出结构 |
|---|---|---|
ghidra-rpc decompile <binary> <func> [--timeout SECS] | 反编译为伪 C(默认 120 s) | {name, address, signature, c_code} |
ghidra-rpc basic-blocks <binary> <func> [--limit N] | 获取函数的基本块(CFG) | {name, address, blocks:[{start,end,size,instructions,successors,predecessors}], num_blocks, edges} |
ghidra-rpc pcode <binary> <func> [--high] [--timeout SECS] [--limit N] | 获取 P-code(Ghidra IR);原始形式或高阶 SSA 形式(--high) | {name, address, mode, ops:[{address,seq,opcode,output,inputs}], count, truncated} |
ghidra-rpc search-decompiled <binary> <regex> [--class NAME] [--case-sensitive] [--limit N] [--max-scan N] [--timeout SECS] [--socket-timeout SECS] | 一次调用即可在多个函数的反编译 C 代码中进行正则搜索(避免逐个函数执行 decompile 再 grep) | {matches:[{function,address,matching_lines:[{line,text}]}], count, functions_searched, functions_total, truncated} |
<func> 可以是函数名或十六进制地址(例如 main 或 0x401000)。如果函数名有歧义,
错误消息会列出匹配项,方便你改用地址。
search-decompiled 对 multidex Android 项目尤其有用:在这类项目中,针对某个方法使用 xrefs-to
只能看到同一 DEX 程序中的调用方(参见 Android APK/DEX
部分)——可以用它替代 symbols+decompile+grep 循环,例如 search-decompiled app.apk targetF1 --class com::example::Foo。未指定 --class 时,--max-scan(默认 5000)会限制反编译的函数数量,避免对包含 5 万多个函数的二进制文件进行无休止的搜索;如果扩大扫描范围,请同时调高
--socket-timeout(默认 1800s)。
搜索
| 命令 | 说明 | 输出结构 |
|---|---|---|
ghidra-rpc find-bytes <binary> <pattern> [--limit N] [--address ADDR] | 搜索带通配符的字节模式(例如 "55 8b ?? 83 ec") | {pattern, matches: [{address, context_hex}], count, truncated} |
ghidra-rpc strings <binary> <query> [--limit N] | 搜索字符串(子串) | {strings: [{address, value, type}], count} |
ghidra-rpc symbols <binary> <query> [--limit N] [--offset N] | 搜索符号 | {symbols: [{name, address, type}], count, total} |
匹配前,symbols 会将普通空格和下划线视为等价字符,因此直接从 strings 输出中粘贴查询内容(使用实际空格)也能找到对应标签,即使 Ghidra 会自动根据字符串内容生成标签,将每个空格替换为 _(其他所有字符,包括非 ASCII/CJK 文本,均保持不变)。
交叉引用
| 命令 | 说明 | 输出结构 |
|---|---|---|
ghidra-rpc xrefs-to <binary> <target> [--limit N] [--all-binaries] | 谁引用了此项? | {xrefs: [{from_address, from_function, type}], count} |
ghidra-rpc xrefs-from <binary> <target> [--limit N] [--no-stack] | 此项引用了什么?(--no-stack 会隐藏 Stack[-0x...] 条目) | {xrefs: [{to_address, to_function, type}], count} |
Ghidra 的引用管理器按二进制文件区分:如果调用方和目标位于两个不同的已加载二进制文件中,单个二进制文件的 xrefs-to 查询就无法看到该调用(这种情况最常见于 multidex Android 项目:一个 classesN.dex 中的方法被另一个 DEX 调用;但这并非 DEX 特有——守护进程中加载了多个二进制文件的任何项目都会遇到此情况)。传入 --all-binaries 还会搜索当前加载的其他所有二进制文件,查找名称相同的完全限定符号,并合并其中找到的实际调用方;每个合并条目都包含一个 binary 字段,方便你确认其来源。
导航(仅 GUI 模式)
| 命令 | 说明 | 输出结构 |
|---|---|---|
ghidra-rpc goto <binary> <target> [function|address] | 在 GUI 中导航 | {address, success} |
内存与反汇编
| 命令 | 描述 | 输出结构 |
|---|---|---|
ghidra-rpc memory-map <binary> | 列出所有内存段(名称、地址范围、大小、rwx 标志、类型) | {segments: [{name, start, end, size, read, write, execute, initialized, type, source_name}], count} |
ghidra-rpc write-bytes <binary> <address> <hex> | 将原始字节写入指定地址;不会自动重新反汇编 | {address, length, hex, verified} |
ghidra-rpc read-bytes <binary> <address> <length> | 读取原始字节;LENGTH 接受十进制或 0x 十六进制 | {address, length, hex, hexdump} |
ghidra-rpc read-pointers <binary> <address> <count> [--pointer-size N] | 读取 COUNT 个指针,并将每个指针解析为其符号(虚函数表、导入表/跳转表、RTTI 数组) | {address, count, pointer_size, endian, pointers:[{index, offset, slot_address, value, target_address, target_name, target_kind}]} |
ghidra-rpc list-vtable <binary> <address> [--count N] [--pointer-size N] | 将 C++ 虚函数表的槽位导出为已解析的方法;ADDRESS 可以是符号名称。不指定 --count 时,会在遇到下一个 vftable 符号/第一个非函数指针时停止(参见 stopped_reason) | {vtable_address, symbol, count, pointer_size, stopped_reason, slots:[{index, offset, slot_address, target_address, target_name, target_kind}]} |
ghidra-rpc disassemble <binary> <address> [--count N] [--with-instructions] | 反汇编 N 条指令(默认 20 条);返回 listing 文本,其中已包含地址/字节/助记符/操作数/注释;仅在需要机器可解析的数组时传入 --with-instructions(输出量约为 4 倍);如果起始地址没有指令,则会返回 warning 字段 | {address, count, listing[, instructions][, warning]} |
ghidra-rpc assemble <binary> <address> <instr> [<instr> ...] | 在指定地址汇编指令文本(Ghidra SLEIGH 汇编器) | {address, bytes_written, hex, instructions:[{address,bytes,mnemonic,operands,length}]} |
修改
| 命令 | 描述 | 输出格式 |
|---|---|---|
ghidra-rpc create-function <binary> <address> [--name NAME] | 在指定地址创建函数(根据控制流自动检测函数体) | {name, address, size, body} |
ghidra-rpc delete-function <binary> <target> | 移除函数定义(字节不变;该地址恢复为未定义状态) | {address, name, deleted} |
ghidra-rpc rename-function <binary> <target> <new_name> [--namespace NS] | 重命名函数;--namespace 可将函数移入命名空间 | {address, old_name, new_name, verified[, old_namespace, new_namespace]} |
ghidra-rpc rename-symbol <binary> <address> <new_name> [--create] | 重命名符号;如果不存在符号,--create 会新建标签 | {address, old_name, new_name, created, verified} |
ghidra-rpc create-label <binary> <address> <name> | 在任意地址新建或重命名标签(插入或更新) | {address, name, old_name, action, created, verified} |
ghidra-rpc set-comment <binary> <address> --comment <text> [--type TYPE] | 设置注释(注释文本使用 --comment,与 set-bookmark 一致) | {address, comment_type, comment, verified} |
ghidra-rpc batch-rename <binary> --json |--json-file FILE [--mode function|label] | 在一个事务中重命名 40 个以上的函数或标签;逐项报告错误 | {results:[{ok, index, address, old_name, new_name}], count, ok_count, error_count} |
ghidra-rpc batch-set-comment <binary> --json |--json-file FILE | 在一个事务中为多个地址设置注释 | {results:[{ok, index, address, comment_type, comment}], count, ok_count, error_count} |
ghidra-rpc set-signature <binary> <target> <signature> | 设置函数签名 | {address, old_signature, new_signature, verified} |
ghidra-rpc set-data-type <binary> <address> <type> | 在列表中定义数据类型 | {address, data_type, length, value} |
ghidra-rpc retype-variable <binary> <func> <variable> <type> [--timeout SECS] | 更改反编译器变量的类型 | {function, variable, old_type, new_type, verified} |
ghidra-rpc rename-variable <binary> <func> <variable> <new_name> [--timeout SECS] | 重命名反编译器变量 | {function, variable, new_name, verified} |
ghidra-rpc batch-edit-variable <binary> <func> --json |--json-file FILE [--timeout SECS] | 在同一份反编译器快照中重命名和/或更改多个局部变量的类型,避免连续执行单项编辑时自动名称重新编号导致的问题。每项操作格式:{variable|storage, new_name?, data_type?}(按名称或存储字符串指定;必须至少提供 new_name 或 data_type) | {function, results:[{ok, index, variable, storage, old_name, new_name, old_type, new_type, verified}], count, ok_count, error_count, verified_count} |
ghidra-rpc set-calling-convention <binary> <target> <convention> | 更改函数的调用约定 | {address, name, old_convention, new_convention, verified} |
ghidra-rpc set-thunk <binary> <thunk> <target> | 将函数标记为 thunk(转发包装器) | {thunk_address, thunk_name, target_address, target_name, verified} |
ghidra-rpc set-flow-override <binary> <address> <override> | 覆盖指令流类型(NONE/BRANCH/CALL/CALL_RETURN/RETURN) | {address, override, old_override, verified} |
ghidra-rpc get-processor-context <binary> <address> [--register REG] | 检查 ISA 上下文寄存器值(例如 ARM 上的 TMode) | {address, registers:{name:value}} |
ghidra-rpc set-processor-context <binary> <address> <register> <value> [--end ADDR] | 在指定范围内设置 ISA 上下文寄存器,可修正 ARM Thumb 模式误分类 | {address, end, register, value, verified} |
ghidra-rpc create-namespace <binary> <name> [--parent NS] | 创建或查找命名空间 | {name, path, id, created} |
ghidra-rpc list-namespaces <binary> [--limit N] | 列出所有命名空间及其符号数量 | {namespaces:[{name,path,id,type,symbol_count}], count} |
注释类型:plate、pre、post、eol(默认)、repeatable。
签名输入会自动进行清理:去除末尾分号、修剪空白,并从字符串中提取内联调用约定(__thiscall、__fastcall、
__stdcall、__cdecl、__vectorcall、__pascal),再通过正确的 Ghidra API 应用。因此,你可以直接粘贴 C 原型
(例如,void __thiscall Foo::Bar(int x); 无需手动清理即可使用)。
set-data-type、retype-variable 和结构体字段类型支持以下类型表达式:
- 内置类型:
byte、char、int、uint、short、long、float、double、void、string、unicode - 指针:
char *、void *、int ** - 数组:
char[11]、int[4] - 按名称或路径引用程序数据类型管理器中的任意类型:
MyStruct、/POSIX/size_t
操作顺序——先设置签名和类型,再命名局部变量。 set-signature、set-data-type、retype-variable 和
rename-variable 中的每个命令都会重新运行反编译器,导致其余自动命名的局部变量重新编号(uVar1、dVar2,等等)。因此,连续进行单变量编辑并不可靠:重命名 dVar1 后,原来的 dVar2 现在可能变成了 dVar1。先完成所有签名和 this 类型设置,再命名局部变量——或者更好的做法是,使用
batch-edit-variable 在一次调用中基于同一个反编译器快照应用所有重命名和类型更改(它还允许你使用稳定的
storage 字符串而非易变的自动名称来指定变量)。
书签
| 命令 | 描述 | 输出格式 |
|---|---|---|
ghidra-rpc set-bookmark <binary> <address> [--type TYPE] [--category CAT] [--comment TEXT] | 在某个地址创建或更新书签 | {address, type, category, comment, action} |
ghidra-rpc list-bookmarks <binary> [--type TYPE] [--category CAT] [--address ADDR] [--limit N] | 列出书签(全部、按类型或类别筛选,或列出指定地址处的书签) | {bookmarks: [{address, type, category, comment}], count, total} |
ghidra-rpc remove-bookmark <binary> <address> [--type TYPE] [--category CAT] | 删除某个地址处的书签 | {address, type, removed} |
书签类型:Note(默认)、Warning、Error、Info、Analysis。
--category 是不区分大小写的子字符串筛选条件。对于经过大量自动分析的二进制文件
(大型原生程序,尤其是 DEX/Dalvik 文件——函数数量达到 5 万以上很常见),Ghidra
会生成大量 Analysis 类型的书签(常见类别为 Address Table),可能会淹没少量自定义书签;与其翻阅未经筛选的列表,不如用 --category 过滤掉这些书签(或用 --type 仅查看自定义类型,例如 Note)。
书签可在 Ghidra GUI 的书签窗口中查看。可用它们持久标记有趣的位置、跟踪分析进度,或标出 供人工审查的发现。
函数标签
| 命令 | 描述 | 输出格式 |
|---|---|---|
ghidra-rpc tag-function <binary> <target> --tag TAG | 为函数添加标签以进行分类 | {address, name, tag, all_tags} |
ghidra-rpc untag-function <binary> <target> --tag TAG | 移除函数标签 | {address, name, tag, removed, all_tags} |
ghidra-rpc list-tags <binary> | 列出所有已定义的标签及其使用次数 | {tags:[{name,count}], count} |
ghidra-rpc functions-by-tag <binary> --tag TAG [--limit N] | 列出具有指定标签的函数 | {tag, functions:[{name,address,signature}], count, total} |
标签是字符串标记(例如 crypto、vuln-sink、analyzed、needs-review),
可在 Ghidra 的函数标签窗口中查看。可用它们对函数进行分类
并跟踪分析进度。
数据类型编写
| 命令 | 描述 | 输出结构 |
|---|---|---|
ghidra-rpc create-struct <binary> <name> TYPE FIELD [TYPE FIELD ...] [--if-not-exists|--or-replace] | 创建具名结构体;--if-not-exists 具有幂等性,--or-replace 会重建结构体 | {name, path, size, fields:[...], already_existed} |
ghidra-rpc create-struct <binary> <name> --field OFFSET TYPE NAME [--field ...] | 创建一个字段位于指定字节偏移处的结构体(OFFSET 为十进制或 0x 十六进制);字段之间的空隙会自动填充未定义字节(无需手动添加填充字段)。不允许字段重叠。 | {name, path, size, fields:[...], already_existed} |
ghidra-rpc create-union <binary> <name> TYPE FIELD [TYPE FIELD ...] [--if-not-exists|--or-replace] | 创建具名联合体;所有字段的偏移均为 0 | {name, path, size, fields:[...], already_existed} |
ghidra-rpc modify-struct <binary> <struct_name> --field-offset N|--field-name NAME [--new-type TYPE] [--new-name NAME] | 更改结构体字段的类型、名称或注释 | {name, path, size, fields:[...], modified_field:{...}} |
ghidra-rpc clear-data-range <binary> <start> <end> | 将包含首尾字节的范围重置为未定义 | {start, end, cleared} |
ghidra-rpc apply-data-type-range <binary> <start> <end> <type> [--clear] | 在包含首尾字节的范围内重复应用类型;--clear 会在应用类型前以原子方式清除该区域 | {start, end, data_type, type_size, applied_count, cleared} |
ghidra-rpc list-labels <binary> <address> [--end ADDR] [--limit N] | 列出指定地址或范围内的符号,包括各位置的数据类型 | {labels:[{address,name,type,source,is_primary,data_type,data_length}], count, total} |
ghidra-rpc create-enum <binary> <name> NAME VAL [NAME VAL ...] [--size 1|2|4|8] [--if-not-exists|--or-replace] | 在 DTM 中创建具名枚举 | {name, path, size, values:[{name,value}], already_existed} |
ghidra-rpc modify-enum <binary> <name> [--add NAME:VAL ...] [--remove NAME ...] | 添加或移除现有枚举中的单个条目 | {name, path, size, values:[{name,value}]} |
ghidra-rpc set-equate <binary> <addr> <equate_name> <value> [--operand-index N] [--enum-path PATH] | 将具名标量常量附加到指令操作数;若找到枚举,则自动关联 | {address, operand_index, equate_name, value, enum_linked, verified} |
ghidra-rpc list-equates <binary> [address] [--limit N] | 列出程序中的所有等式,或仅列出在指定地址应用的等式 | {equates:[{name,value[,operand_index,address]}], count, total} |
ghidra-rpc list-data-types <binary> [--category CAT] [--query SUBSTR] [--limit N] | 列出 DTM 中的类型;类别:struct、enum、union、typedef、pointer、array、all | {data_types:[{name,path,category,size}], count, total} |
版本跟踪与差异比较
| 命令 | 描述 | 输出格式 |
|---|---|---|
ghidra-rpc version-track <old> <new> [--changed-only] [--limit N] [--min-similarity F] | 匹配两个版本之间的函数,查找变更内容。结果按源函数去重。 | {matched:[{source_name,destination_name,similarity,confidence,correlator}], unmatched_source, unmatched_destination, summary:{source_functions_total, changed_functions, identical_functions, ...}} |
ghidra-rpc function-diff <bin1> <func1> <bin2> <func2> [--mode decompile|disassembly] | 比较两个版本中函数的统一差异;将自动生成的名称(FUN_*、DAT_*、local_*、param_*)标准化以抑制重定位噪声 | {is_identical, diff, raw_code1, raw_code2, func1_address, func2_address} |
ghidra-rpc match-function <bin1> <func> <bin2> [--threshold F] | 使用 BSim 和关联器,在另一个二进制文件中查找函数的最佳匹配项 | {source:{name,address}, candidates:[{name,address,similarity,confidence,correlator}], count} |
ghidra-rpc decompile-all <binary> [--limit N] [--offset N] [--timeout SECS] [--socket-timeout SECS] | 批量反编译所有函数;用于导出和外部差异比较工具 | {functions:[{name,address,signature,c_code}], count, total, offset, errors} |
decompile-all 的默认 --socket-timeout(1800s)假设批量扫描所需时间可能远超单个函数的 --timeout;对于包含数万个函数的二进制文件(例如大型 DEX/APK 程序),请进一步调高此值。
完整的补丁差异工作流请参阅 docs/flows/patch-analysis.md。
错误处理
错误响应如下所示:
{"id": "...", "ok": false, "error": "FunctionNotFound", "message": "Function 'foo' not found."}
常见错误:
- DaemonNotRunning:守护进程尚未启动。请告知用户运行
ghidra-rpc start。 - ValueError:参数有误(名称有歧义、地址无效)。错误消息通常会说明如何处理,例如使用更具体的名称或地址。
- RuntimeError:Ghidra 级别的错误。对于无头模式下仅限 GUI 的命令,错误会明确说明。
所有 CLI 输出均为 JSON,包括用法错误。 格式错误的调用(未知选项、无效的 --type 选项、未知子命令、缺少必需参数)也会通过 stdout 返回 {"ok": false, "error": "...", "message": "..."},并以非零退出码结束,而不会输出纯文本的 Click 用法字符串。脚本调用方始终可以无条件对 stdout 使用 json.loads(),无需专门处理参数错误。
写入操作与持久化
写入操作(rename、create-label、create-function、delete-function、set-comment、batch-rename、batch-set-comment、set-signature、set-data-type、retype-variable、rename-variable、batch-edit-variable、set-calling-convention、set-thunk、set-flow-override、set-processor-context、create-struct、create-union、modify-struct、create-enum、modify-enum、set-equate、set-bookmark、clear-data-range、apply-data-type-range、write-bytes、assemble、tag-function、untag-function、create-namespace) 在内部使用 Ghidra 事务。每次写入都会在事务提交后自动保存到磁盘上的项目数据库,因此更改在守护进程重启后仍会保留,并且重新在 Ghidra GUI 中打开项目时也能看到。
每个写入响应都包含一个 verified 布尔值,用于确认提交后是否成功读回了更改。
你也可以随时显式保存:
ghidra-rpc save # saves all loaded programs
ghidra-rpc save <binary> # saves one program
正常关闭时(执行 stop 或按 Ctrl+C),所有程序都会自动保存。
补丁/差异分析快速入门
# 1. Load both versions
ghidra-rpc load /path/to/binary_v1 -p project.gpr
ghidra-rpc load /path/to/binary_v2 -p project.gpr
# 2. Find changed functions (summary counts all changes; matched list is filtered)
ghidra-rpc version-track binary_v1 binary_v2 --changed-only
# 3. Diff a specific changed function
ghidra-rpc function-diff binary_v1 <func> binary_v2 <func>
完整工作流——关联器详情、未匹配项分析、批量反编译:
请阅读 docs/flows/patch-analysis.md。
Android APK / DEX 分析
Ghidra 内置了 APK 和 DEX 支持(Dalvik 处理器 + FileFormats 加载器),无需安装扩展。直接 load .dex 或 .apk,常用命令(decompile、functions、strings、xrefs-* 等)即可在 Dalvik 程序上运行,并反编译为类似 Java 的伪代码。请注意 多 DEX 限制:load app.apk 只会导入主 classes.dex。
如需了解完整工作流,包括多 DEX 提取、带类限定符的 :: 符号和存在歧义的方法、DEX 字符串与 xrefs-to 的注意事项、混淆应用,以及清单 / .so 提取,请阅读 docs/flows/android-apk.md。
典型工作流
- 用户启动守护进程:
cd <skill-dir> && uv run ghidra-rpc start --project /path/to/project.gpr --headless自动化 / 非阻塞启动:uv run ghidra-rpc start --project /path/to/project.gpr --headless --detach - 加载二进制文件:
uv run ghidra-rpc load /path/to/binary -p /path/to/project.gpr响应中包含short_name(可在后续所有命令中用作别名)。 (添加--no-analyze可跳过分析,添加--analysis-timeout SECS可限制分析时间) - 获取概览:
metadata、functions、imports、exports - 调查:对感兴趣的函数运行
decompile,用xrefs-to跟踪调用方 - 添加注释:用
rename-function、set-comment记录发现 - 搜索:用
strings查找硬编码值,用symbols查找特定模式
FAQ / 常见注意事项
create-label 会正确替换 DEFAULT(自动分析)符号:
create-label 会创建一个 USER_DEFINED 标签,并将其设为该地址的主符号。如果该地址已存在 DEFAULT 符号(例如 DAT_00418138),该符号会降为次要符号。随后反编译器会使用新名称。rename-symbol 会就地重命名,但要求符号已存在;无论地址上是否已有符号,添加注释时都优先使用 create-label。
为没有现有符号的地址添加注释(rename-symbol 失败并提示 "No symbol found"):
rename-symbol 要求该地址已有符号。自动分析只会在检测到数据的位置添加 DAT_ 符号;数组内部或密集的结构体区域中,许多地址没有符号。请改用 create-label——如果没有现有符号,它会创建新的 USER_DEFINED 标签;如果已有符号,则会将其重命名:
ghidra-rpc create-label <binary> 0x0040e4ac topPtrErrorMsg
也可以为 rename-symbol 添加 --create,以实现相同的插入或更新行为。
定义结构体并将其应用到内存区域: 以下是将结构体应用到重复数据表的完整工作流:
# 1. Create the struct type in the DTM (--if-not-exists makes the call idempotent)
ghidra-rpc create-struct binary ErrorEntry int errorNumber "char *" ptrErrorMsg --if-not-exists
# 2. Stamp the struct across the range with --clear to atomically clear + apply
# (23 × 8-byte ErrorEntry structs, both endpoints inclusive)
ghidra-rpc apply-data-type-range binary 0x0040e4a8 0x0040e55f ErrorEntry --clear
执行后,地址 0x0040e4a8、0x0040e4b0 等处的类型均为 ErrorEntry。
如果不使用 --clear,apply-data-type-range 会跳过与现有数据冲突的位置,并在 errors 列表中报告。若要更精细地控制清除区域,请先使用 clear-data-range。
查找地址或范围内有哪些标签:
# Single address
ghidra-rpc list-labels binary 0x0040e4a8
# Range
ghidra-rpc list-labels binary 0x0040e4a8 --end 0x0040e55f --limit 50
在 load 后使用二进制文件名:
load 会同时返回完整键(binary,带哈希后缀)和 short_name(原始文件名)。后续所有命令都使用 short_name——它有效是因为命令会按子字符串匹配二进制文件名:
# Load response: {"binary": "/WinHelloCPP.exe-85cbcc", "short_name": "WinHelloCPP.exe", ...}
ghidra-rpc decompile WinHelloCPP.exe main # short_name works
ghidra-rpc decompile WinHelloCPP main # even without extension, if unambiguous
如果两个二进制文件的主文件名相同,请使用完整键来区分。
签名末尾的分号:Ghidra 的解析器会拒绝以 ; 结尾的 C 原型。ghidra-rpc 会自动去掉末尾分号,因此可以直接粘贴原文。
list-binaries 为空,但我已加载二进制文件:在 GUI 模式下,二进制文件必须在 CodeBrowser 中打开。使用 list-project-programs 查看项目仓库中存储的内容,然后在 CodeBrowser 的 Project 窗口中打开它。
守护进程日志文件:在后台启动时(start --detach 或 restart),日志会写入 /tmp/ghidra-rpc-<hash>.log,与守护进程端点位于同一目录且文件名主体相同;因此在 Windows 上,路径为 %LOCALAPPDATA%\ghidra-rpc\ghidra-rpc-<hash>.log。如果守护进程启动失败或无法响应,请先检查该文件:
tail -50 /tmp/ghidra-rpc-*.log
在所有平台上,超时错误消息都会显示准确的日志路径。
后台运行后找不到 GHIDRA_INSTALL_DIR:守护进程化时(nohup、cron、systemd 单元等)环境变量可能会丢失。按优先顺序,可采用以下解决方法:
- 向
start或restart传入--ghidra-install-dir /path/to/ghidra——该值会保存在会话文件中,并在后续每次重启时自动传递。 - 在 shell 配置文件(
~/.bashrc、~/.zshrc)中导出GHIDRA_INSTALL_DIR,使其在登录会话间保留。 - 在设置了该环境变量的同一终端中使用
start --detach --headless。
会话文件位置:默认情况下,会话文件(.ghidra-rpc-<hash>.json)会写入 .gpr 项目文件所在目录,使所有状态都集中在一处。若要使用自定义目录(例如共享位置或 RAM 磁盘),请设置 GHIDRA_RPC_STATE_DIR:
export GHIDRA_RPC_STATE_DIR=/tmp/ghidra-sessions
更改未在 Ghidra GUI 中显示:请确保打开的是项目副本(例如 Project 窗口中的 basic_code-501243),而不是通过 File → Open 打开的原始二进制文件。此外,请确保没有在同一项目上运行两个独立的 Ghidra 实例(这会导致锁冲突)。ghidra-rpc 所做的更改会自动保存到磁盘,并会在下次通过 GUI 打开程序时显示。
没有先前会话时使用 restart:传入 --headless,这样 restart 就能创建新的无头会话,而无需先执行 start。
某些函数反编译超时:某些函数会触发开销较大的反编译分析路径,即使汇编很简单也会超时。对于难以处理的函数,请使用 decompile --timeout 300(或更高值)。默认超时时间为 120 s(从 60 s 增加,以处理大型固件函数)。retype-variable 和 rename-variable 命令也接受 --timeout,因为它们会触发内部反编译过程。
decompile 返回错误指令警告——使用 pcode --high 作为备用方案:
当 decompile 输出类似 "Bad instruction data" 的内容,或无法解码函数体(在被自动分析错误分类为数据的区域中,ARM Thumb 代码常见此问题)时,请改用 pcode --high:
ghidra-rpc pcode binary 0x03288102 --high
P-code 引擎会根据函数对象的上下文重新解码字节,而不是依据列表级反汇编器,因此它经常能在 decompile 失败时成功。高级 P-code 还会显示所有 CALL / CALLIND / BRANCHIND 目标和数据流,因此即使无法有效反编译,也可用于追踪参数。请使用 set-processor-context 修复根本原因(见下文)。
disassemble 从错误的地址开始(B2 警告):
如果在没有指令的地址处调用 disassemble(例如地址位于指令中间或尚未定义),响应现在会包含一个 warning 字段,说明反汇编从下一个可用指令开始。如果列表看起来有误,请检查 JSON 响应中的 warning。
ARM Thumb 误分类——使用 set-processor-context 修复(F1/F5):
当 ARM 自动分析将 Thumb 代码分类为数据时,列表反汇编器会将其解码为 32 位 ARM(TMode=0),从而产生无效结果。完整的恢复工作流:
# 1. Diagnose: check TMode at the affected address
ghidra-rpc get-processor-context binary 0x03288100 --register TMode
# Expected: {"TMode": 0} ← this is the problem
# 2. Clear the bad data/code classification
ghidra-rpc clear-data-range binary 0x03288100 0x032883ff
# 3. Set Thumb mode for the range
ghidra-rpc set-processor-context binary 0x03288100 TMode 1 --end 0x032883ff
# 4. Verify disassembly now shows Thumb-2 instructions
ghidra-rpc disassemble binary 0x03288100 --count 20
# 5. Re-create the function
ghidra-rpc create-function binary 0x03288100
如果由于该地址仍存在错误的存根而导致 create-function 失败,请先使用 delete-function 将其删除。
错误存根阻止重新创建——使用 delete-function(F2):
如果 create-function 0x03288103(奇数地址错误)留下了存根,而现在 create-function 0x03288102(正确地址)因 "already exists at overlapping address" 而失败,请先删除错误存根:
ghidra-rpc delete-function binary 0x03288103
ghidra-rpc create-function binary 0x03288102
批量重命名 / 注释 40 多个函数,无需往返开销(F7):
使用 batch-rename 和 batch-set-comment,通过一次服务往返和一次 Ghidra 事务应用多条注释:
# Rename functions from a JSON file
ghidra-rpc batch-rename binary --json-file renames.json
# Or inline
ghidra-rpc batch-rename binary --json \
'[{"target":"sub_401234","new_name":"init_uart"},{"target":"0x400200","new_name":"isr_handler"}]'
# Label-mode (symbol/label rename by address)
ghidra-rpc batch-rename binary --mode label --json \
'[{"address":"0x0333afcc","new_name":"g_debugStr"}]'
# Batch comments
ghidra-rpc batch-set-comment binary --json \
'[{"address":"0x03288102","comment":"Thumb ISR entry","comment_type":"plate"}]'
所有成功的项目都会在一个事务中提交;失败的项目会在 results[].ok=false 中逐项报告,不会回滚成功的项目。
并发写操作会串行化:守护进程会在内部串行处理所有命令处理程序调用,以避免 Ghidra 事务冲突。你无需在外部串行化写命令——并行写入会自动排队。这比并发执行稍慢,但能避免静默的部分失败。
报告 Bug 和缺失功能
使用 ghidra-rpc 时,你可能会遇到 Bug、错误或缺失的功能。请报告这些问题——真实使用情况有助于持续改进。
在遇到问题的分析会话结束时,请保存一份简短报告:
cat > /tmp/ghidra-rpc-issues-$(date +%Y%m%d-%H%M%S).md << 'EOF'
## ghidra-rpc Issue Report
**Date:** $(date)
**Binary:** <name of binary analysed>
### Bugs encountered
### Missing features
### Suggestions
EOF
然后告知用户:
“我已将 ghidra-rpc 问题报告保存到
/tmp/ghidra-rpc-issues-<timestamp>.md。 如果你想提交报告,请运行:cat /tmp/ghidra-rpc-issues-*.md”
报告会写入 /tmp,因此只保留在本机,重启后就会丢失——它绝不会被自动发送到任何地方。在 Windows 上,请改为写入 %TEMP%;上面的代码片段使用 bash,请根据你实际使用的 shell 进行调整。
更多文档
有关特定工作流的详细指南:
- 安装与设置:阅读
docs/install.md - 快速入门教程:阅读
docs/quickstart.md - 故障排除:阅读
docs/troubleshooting.md - 二进制审计工作流:阅读
docs/flows/binary-audit.md - 漏洞研究:阅读
docs/flows/vulnerability-research.md - 补丁 / 差异分析:阅读
docs/flows/patch-analysis.md - Android APK / DEX 分析:阅读
docs/flows/android-apk.md