mcpField
G
ghidra-rpc

ghidra-rpc

github.com/cellebrite-labs安全39342 次安装今天更新
代码仓库

关于 ghidra-rpc

ghidra-rpc 是用于调用 Ghidra 逆向分析能力的 CLI 技能,通过守护进程提供操作接口。它涵盖二进制分析、反编译、搜索和程序检查,命令以 JSON 输出。

主要功能

  1. 01启动、停止和检查守护进程
  2. 02加载并分析二进制文件
  3. 03列出函数、导入项和符号
  4. 04反编译函数并检查 P-code
  5. 05搜索字节、字符串和反编译代码
  6. 06读取内存并反汇编指令

适用场景

  1. 01分析已导入的可执行文件
  2. 02在反编译函数中搜索代码模式
  3. 03检查交叉引用和函数结构
  4. 04读取或修改二进制内存

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cellebrite-labs/ghidra-rpc --skill ghidra-rpc

安装后在 Claude Code 中输入/ghidra-rpc确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CLAUDE.md
.gitignore
README.md
CHANGELOG.md
AGENTS.md
.github/workflows/
integration.yml
tests.yml
.pi/prompts/
process-feedback.md
docs/
install.md
quickstart.md
troubleshooting.md
internals.md
docs/flows/
android-apk.md
binary-audit.md
vulnerability-research.md
patch-analysis.md
ghidra_rpc/
__init__.py
cli.py
daemon.py
client.py
ghidra_rpc/server/
__init__.py
launcher.py
main.py
context.py
_gui_launcher.py
ghidra_rpc/server/tools/
analysis.py
__init__.py
bookmarks.py
disassembly.py
cfg.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> ...

前置条件检查

使用任何命令前,请先确认环境已正确配置:

  1. 守护进程是否正在运行? 运行 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)。
  2. GUI 模式:确认当前打开的是正确项目。 守护进程会将 --project 路径 直接传递给 GhidraRun,以便 Ghidra 立即打开指定项目。在 GUI 模式下运行 start --detach 后,在执行任何分析命令前,请确认已加载正确的项目:
    uv run ghidra-rpc list-project-programs --project /path/to/project.gpr
    
    请将返回的二进制文件名称与预期进行核对。如果名称不匹配 (或响应中出现 warning 字段),请停止并让用户在 Ghidra 的 Project 窗口中打开正确的 项目,然后再继续。
  3. GUI 模式:在 CodeBrowser 中打开二进制文件。 在 GUI 模式下,守护进程会通过正在运行的 CodeBrowser 工具 查找程序。如果二进制文件位于项目中,但当前未在 CodeBrowser 中打开,list-binaries 将返回空结果,所有命令都会因 “Binary not found”而失败。使用 list-project-programs 查看项目中存储的内容, 然后在 Ghidra 的 Project 窗口中双击该程序以将其打开。
  4. 是否已设置 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。

典型工作流

  1. 用户启动守护进程: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
  2. 加载二进制文件:uv run ghidra-rpc load /path/to/binary -p /path/to/project.gpr 响应中包含 short_name(可在后续所有命令中用作别名)。 (添加 --no-analyze 可跳过分析,添加 --analysis-timeout SECS 可限制分析时间)
  3. 获取概览:metadata、functions、imports、exports
  4. 调查:对感兴趣的函数运行 decompile,用 xrefs-to 跟踪调用方
  5. 添加注释:用 rename-function、set-comment 记录发现
  6. 搜索:用 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 单元等)环境变量可能会丢失。按优先顺序,可采用以下解决方法:

  1. 向 start 或 restart 传入 --ghidra-install-dir /path/to/ghidra——该值会保存在会话文件中,并在后续每次重启时自动传递。
  2. 在 shell 配置文件(~/.bashrc、~/.zshrc)中导出 GHIDRA_INSTALL_DIR,使其在登录会话间保留。
  3. 在设置了该环境变量的同一终端中使用 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

评论

支持 Markdown