AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Ghidra Core

skill-cristallin2006-ghidra-skill-for-dsh-ghidra-core · by Cristallin2006

Ghidra headless 执行底座(execution engine)——rpc_driver/ghidra-rpc 命令、daemon 起停、doctor 环境自检、脚本清单。当需要实际运行任何 Ghidra 命令(import/decompile/disassemble/rename/patch/version-track)、环境排障、或其他逆向 skill 里的操作不知道具体命令时加载。不含分析方法论。动手前必须先用 skill 工具加载本 skill 全文并遵守其流程;一切观察/结论用 ledger.py 落账。

— No reviews yet
0 installs
1 views
0.0% view→install

Install

$ agentstack add skill-cristallin2006-ghidra-skill-for-dsh-ghidra-core

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-cristallin2006-ghidra-skill-for-dsh-ghidra-core)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● today

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Ghidra Core? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Ghidra Core(执行底座)

唯一的代码与命令知识层。场景 skill(re-triage / ghidra-static / vuln-audit)只含方法论,具体命令一律回本文件查。

  • 场景路由:未知样本分诊 → ~/.dsh/skills/re-triage;脱壳与验证 → ~/.dsh/skills/re-unpack;静态深挖/patch/交付 → ~/.dsh/skills/ghidra-static;漏洞模式排查 → ~/.dsh/skills/vuln-audit
  • 本 skill 内容:§0 环境 / §1 十四条铁律 / §2 快速上手(含长任务、GUI、doctor)/ §4 legacy 裸命令 / §5 能力清单(三层)/ §7 移植坑 / §8 能力边界
  • engine 内部补丁细节不在本文件:见 engine/VENDOR.md

0. 环境(本机已配好)

> WSL/Linux 部署的路径映射(当 uname 是 Linux 时,本节常量按下表替换;脚本内部已自动按平台分支,此处供人工/排障参考): > - GHIDRA_HOME = /opt/ghidra,JDK = /usr/lib/jvm/java-21-openjdk-amd64(apt openjdk-21) > - 引擎 venv = ~/ghidra-rpc-venv(bin/python,无 .exe),legacy venv = ~/pyghidra-venv > - re-tools venv = ~/re-tools-venv,unpacker venv = ~/unpacker-venv,pwn venv = ~/re-pwn-venv > - 工具目录 = ~/tools/(goresym、jadx、pyinstxtractor);系统工具(file/upx/gdb/tshark/pycdc…)全在 PATH,直接裸名调用 > - junction 在 Linux 是 symlink ~/dsh-ghidra-workspace,语义相同 > - win_gui_drive.py、pywin32、Android SDK/emulator 为 Windows-only,Linux 下不可用

  • GHIDRA_HOME = C:\t001s\ghidra_12.1.3_PUBLIC_20260817\ghidra_12.1.3_PUBLIC(含 support/ 的内层目录)
  • 执行引擎:ghidra-rpc 常驻 daemon(vendor 在 engine/ghidra-rpc/,上游 Cellebrite Labs 0.2.0 + dsh 补丁,见 engine/VENDOR.md)。统一入口 scripts/rpc_driver.py;GUI 用 scripts/launch_gui.py(见 §2「GUI」节)
  • JDK 21+(本机 C:\Java,Java 25),且必须是 JDK 而非 JRE——PyGhidra 通过 JPype 起 JVM
  • Python 环境 ×2:
  • 引擎 venv:$HOME/Desktop/src/ghidra-bridge/ghidra-rpc-venv(Python 3.12;ghidra-rpc 0.2.0 editable 安装自 engine/ghidra-rpc/,pyghidra 3.1.0 + JPype1 1.5.2)——引擎代码改动即时生效
  • legacy venv:$HOME/Desktop/src/ghidra-bridge/pyghidra-venv(Python 3.10,pyghidra 3.1.0)——仅供 driver.py 后路使用
  • 工作区:~/.dsh/ghidra-workspace/(projects/ legacy 项目缓存、projects-rpc/ daemon 项目、out/ 产物、logs/ 日志)
  • 传给 Ghidra 的路径必须走 junction ~/dsh-ghidra-workspace:Ghidra 的 ProjectLocator 拒绝任何以 . 开头的路径元素(~/.dsh/... 会 abort)。上游 ghidra-rpc 会 resolve() 掉 junction——已打补丁(engine/VENDOR.md 补丁 2),junction 路径全程可用

为什么不是 Jython / analyzeHeadless(重要:原设计其实没错)

Jython 扩展本身是装好的,就在 %APPDATA%\ghidra\ghidra_12.1.3_PUBLIC\Extensions\Jython(内含 jython-2.7.4\Lib)。用 GUI(ghidraRun.bat,不重定向 APPDATA)跑,原本的 @runtime Jython 脚本是能用的。

真正的坑是 APPDATA 重定向:为了满足 DSH 的文件沙箱(只允许写工作区),driver 把 APPDATA/LOCALAPPDATA/USERPROFILE/TMP 指到工作区内的 settings 目录。Ghidra 于是去 \ghidra\ghidra_12.1.3_PUBLIC\Extensions\ 找扩展——那里没有 Jython,于是报:

ghidra.app.script.JythonStubScriptProvider$JythonStubException:
  In order to use Jython based scripts, you must install the Jython Ghidra Extension,
  or (recommended) port your script to PyGhidra or Java.

一句话:不是 skill 的脚本有问题,是重定向把一个已装好的扩展藏起来了。两个可选解法:

  • 想用 Jython:在被重定向的 settings 目录下建 junction 指到真实扩展

mklink /J \...\Extensions\Jython %APPDATA%\ghidra\ghidra_12.1.3_PUBLIC\Extensions\Jython (实测可行;但 PyGhidra 流程下仍不建议回退,见下)

  • 继续用 PyGhidra(当前选择):不依赖扩展、脚本是真正的 Python 3、错误信息更清楚。代价是要过下面的启动/API 关口。

另外注意:PyGhidra 启动器下 analyzeHeadless 完全不可用——把 .py 交给它会得到 Ghidra was not started with PyGhidra. Python is not available。所以一旦选 PyGhidra,就必须整条链走 driver.py。

上游 19 个 + 本 skill 早期的 triage_scan/decompile_all 共 21 个脚本已全部移植为 @runtime PyGhidra 并统一由 driver.py 启动(原 run-headless.sh 入口已废弃并删除,见 §2),此后又新增 4 个。2026-09-15 起执行引擎迁移为 ghidra-rpc 常驻 daemon,这 25 个脚本冻结为 legacy 备查(见 §5 第 3 层),driver.py 保留为 daemon 挂掉时的后路。

1. 十四条铁律(先读这个再动手)

  1. 开工先 ensure;批量场景用批量工具:daemon 温热后单次命令 ~0.2s,"一个函数一次调用"不再是罪。但全量反编译/全文搜索仍优先 decompile-all / search-decompiled 这类服务端批量工具——别 for 循环 1000 次单条 decompile(每条都要序列化过锁)。
  2. 导入分析一次做足:rpc_driver.py ensure 的 load 只做一次全量分析;之后所有查询/写操作都打在同一个已分析程序上,不会重跑分析。
  3. 大输出落文件:所有脚本约定首个参数 @绝对路径 = 完整结果写该文件(JSON/文本),stdout 只留状态行。agent 用 Read 读文件,不要从 stdout 抠大输出。
  4. Triage 硬门:未记录 imports(DLL/SYS 还要 exports)+ 语言/壳判定之前,MUST NOT 进入深挖或动态分析。导入表只有 kernel32/ntdll 且极少 → 高度怀疑 LoadLibrary+GetProcAddress 动态加载,禁止宣称"无网络/无文件能力"。
  5. 确认即标注:搞清一个函数立即 rename-function 改成语义名 + set-comment --type plate 写 plate comment(地址/作用/依据)。结论必须带地址和可复现命令。daemon 写操作即刻生效并自动存盘。
  6. 时间盒:静态深挖 ~15 分钟无关键路径 → 转动态(Frida/GDB/Qiling/angr,选型见 ghidra-static references/ctf-patterns.md §6);同一路径失败 2 次 → 换工具,禁止空转。量化判据(什么算"卡住"):同一假设上连续 3 次工具调用没有产出新观测(新地址/新常量/新结构),即判定卡住——不许靠"再试一次"拖延,立即按铁律 7 的菜单升级;给同一思路"换措辞重试"(改脚本变量名/换种写法跑同一模型)计入失败次数,不重置计数。拟合/接线类推断熔断(chal session:wiring→wiring2→fitwiring 连错 5 次):手写拟合/接线求解脚本连错 2 次 → 强制升级 z3/SMT 求解或 emulate_blob/emulate-function 仿真取数,禁止写第 3 个手写拟合脚本;升级前先查依赖图——存在可剥离递推/可逆算子时优先手工剥离(Reverse-chal:掩码二阶递推逐层反解成功,z3 60s 超时反而没用上);hooks 层 gate_churn.py 会在脚本堆积(目录近 24h ≥8 个 .py)且台账零 stuck 时机械阻断。探索运行熔断(f862c151 session:97 次 heredoc 探索、128 个手写结构变体盲搜,gdb/framemap/modeldiff/emulate 全程 0 次):heredoc/python -c/stdin 管道这类不落盘的探索运行不过 churn 闸门(载体盲区),由 hooks 层 gate_explore.py 计数封堵——30 分钟 ≥25 次且台账零 stuck → 机械阻断;脚本体与窗内 ≥2 次历史高度相似(换措辞重试的指纹)且台账无新条目 → 阻断并直指 model_diff.py 分歧指纹分类。ARX/模乘类密文升级阶梯(禁止跳档):① gdb 断轮体读帧槽位真值(先 frame_map.py 定位槽位)→ ② model_diff.py 分歧指纹分类 → ③ emulate-function/p-code 插桩取语句级真值 → ④ 把已有 trace 当方程组解接线(数据够时差的是"解"不是"枚举")→ ⑤ angr 殿后且须先论证对本密文可行(16 轮 × 68 次 mod-65537 乘 + 192 次查表的规模必爆)——未走完前四档就调 angr 会被 gate_explore.py 机械阻断。Cython/CPython 扩展前置:triage 报 python_ext=true 时,建模轮函数之前必须先跑 const_scan.py --binary(§12 元数据常量重建)+ frame_map.py(栈帧槽位)并落账,否则深挖被机械阻断。
  7. 死循环断路器(机械触发,不靠自觉):循环签名 = 第二次回到同一字节区域/同一假设继续分析。执行载体是 scripts/ledger.py:每个区域级观察 MUST 走 ledger.py observe 落账——同一区域第二次 observe 时脚本拒绝入账(exit 2),除非 --delta 回答"这次观测和上次差在哪";答不出 = 断路器触发,按脚本打印的菜单升级:换工具 / 转动态 / 问用户,并用 ledger.py stuck 留痕——禁止换第 3 种方式重试同一路径。字节只能通过工具解读(反汇编、反编译、脚本输出);肉眼/裸 hex 仅用于验证工具输出,脚本对同一区域只放行 2 次,第 3 次直接拒绝。packed/加密字节在信息论上是噪声,内容级死磕一律禁止——先脱壳(re-unpack)或仿真(emulate-function)。断路器的盲区自查:observe 熔断只统计同 binary 同 region——给同一思路"换措辞重试"(36 个脚本各写各的 region/文件名)一次都响不了(DEFCON26 复盘 R3)。外部信号:work 目录脚本数 ÷ 台账条目数 > 5 = 记账死掉/同路径重试,用 ledger.py status --workdir 机械统计,命中立即 stuck + 审视。定时器(chal 复盘 E4):单样本目录下每 ~20 分钟主动跑一次 status --workdir——本次 churn 12 倍于红线而没人去跑;注意比值 >5 只触发一次记账(落 observe/stuck),是否停手由当时的 delta 决定,不由比值决定;阈值 5 仅在单样本目录有意义,多文件/协议/多阶段题型天然"脚本多、样本少",只当记账提醒。非地址型题目(协议/算法/多方件)没有自然 binary 键:用题目名当 binary 键、conclude --locus proto:/channel:/region: 前缀落账。

铁律 6 管时间(多久没进展就换路),铁律 7 管循环签名(ledger.py 机械拦截原地打转)——先命中哪条执行哪条。台账 = /out/.ledger.jsonl(机器真相,append-only)+ 每次入账自动重建的 .ledger.md(人读视图):权威结论写入即锁定(同 id 覆盖必须 --overturn+新证据)、先查后析(ledger.py query)、推翻留痕——机制细节见 references/evidence-ledger.md。

  1. 读数纪律(第一嫌疑人是读数,不是程序):关键常量(密文/密钥/换表/魔数)的唯一权威读数 = scripts/read_views.py 三视图(hexdump + 带字节数的 fromhex-ready hex + cstr),读到立即 ledger.py conclude 锁定(注明地址+长度+工具);禁止从终端手工转录 hex(可信度最低的通道不能承载最关键的事实)。反编译器/IDA 的字符串与 hex 渲染只是视图——会把 0x01/0x0E 渲染成 1/E 吞掉前导 0——凡要引用渲染文本,先 read_views.py --expect-hex "" 与真实字节对照。观测矛盾(伪码声明长度 vs 实测处理长度、同一事实两次读出不同值、strcmp 对任何输入都不等)→ 先怀疑读数:任何"这段逻辑是坏的/反的"的结论,必须先排除读数错误才允许提出;同一事实第二次读出不同结果 = 熔断信号,立即停止推断、用 read_views 建立权威读数。求逆之前先正向验证:拿到疑似密钥/密文后,先用已知输入把完整流水线正向跑一遍(oracle.py / emulate-function)确认模型能复现已知输出,再求逆——直接求逆错了也不知道错在哪。字段/读数冲突时,在宣称"题目设计有矛盾"之前,必须先排除"该值是多字段复合函数"(如 tsval ^ payload ^ seq 片段)这一可能——同键冲突恰恰证明单字段不是明文。
  2. 缓冲区归属(字节是谁的):从 MOV [EBP+disp], imm 序列重建栈上字符串时,必须按 disp 区间归属变量,禁止按指令出现顺序拼接——相邻变量的写入区间相接(end_A + 1 == start_B)时极易把别人的字节拼进自己的常量(encode 复盘 E1:28 字节密文被读成 49 字符)。拼接结果 MUST read_views.py --expect-len 与该变量声明长度核对。任何常量长度不符合其用途(hex 必须偶数、base64 必须 4 的倍数、XOR/RC4 密文必须等于明文长度)→ 以「读数可疑」中止,禁止进入求逆。机械门 = scripts/crypto_sanity.py:求逆前 MUST 过 check,求逆后 MUST 过 check-result——49 字符的 base64、28≠21 的密文、不可打印的反推结果都会被它 exit 2 拦下。候选合法性 = 方程校验信号(92a0a107 临门一脚):反演候选全部不可打印 / 尾部不符合填充格式(PKCS#7 等),且原程序对非 ASCII 输入直接崩溃时,判定本轮方程错了(常量或比对对象选错),禁止在同一方程上加补丁续命、禁止归因「还有未建模的编码分支」继续探测——先核对方程两边各是什么(trace 里输入构造用的常量与输出比对的常量未必是同一个)。check-result 的不可打印判定就是这条的机械触发器。
  3. 验证独立性(同源验证 = 没验证):用自己 patch 的进程、自己写的 harness、自己算的偏移来验证自己对程序的理解,三者一致不构成任何证据(encode 复盘 E2/E3)。① 被 patch 过的运行态只能用于探索控制流,禁止用于验证数据模型——验证数据模型要求进程未修改(或修改点与测量点无数据依赖)+ 至少一个独立来源(静态常量/第二输入/已知明文)交叉印证;被迫在 patch 后测量的结论必须 conclude --independent no 标注。② 自建 harness(投喂/读数脚本)在支撑结论前必须用已知答案的输入自检;自检失败或结果不稳定 → 该 harness 全部输出作废;「偶发命中」必须复跑 ≥100 次确认可复现才算发现。凡「由观测反推中间量」的脚本(白化/搬运公式、角色字反推、偏移表)无已知答案自检 ⇒ 其输出标 ⚠UNVERIFIED 且不得用于否定模型——「模型像坏的」时第一嫌疑人永远是 harness 自己:差异呈现规律(如低半字全对、高半字共用一个常数)是"接口/搬运写错"的典型指纹,不是"程序少了运算"。③ ledger.py conclude 强制标注 --source/--independent(self-script 必须给 --harness 路径),无独立来源的结论在 render 里标 ⚠UNVERIFIED,禁止原样交付。④ 否定性结论门槛更高:说「不可满足/程序是坏的」之前,必须先用已知输入正向复现成功(铁律 8),且结论必须能指认一个「如果它错了,结论就崩」的外部事实——指认不出就不许交付。「这是诱饵/假 check/作者逻辑坏了」同属否定性结论:判某分支为假之前,必须先做判定性实验——钉随机源为不同值看输出是否变(判 mask vs target)、读校验涉及的状态量(dir()/__dict__/hook 目标函数)并用已知输入拟合其表达式;实验做不了就不许判。混淆实验不算判定性实验(f862c151 诱饵门事故:stub _p3 返回 _var2 得到 "yes" 是人为满足第一道门,推不出"真门是 _var2";真指纹是 _p3 输出被 os.urandom 掩码 ⇒ _p3(...)==_var2 恒不可满足——恒不可满足的"判定条件"本身就是诱饵签名)。「工具不可用/装不上」同属否定性结论(chal 复盘 §8.3):下此结论前必须换第二种方式复核(离线 pip 缓存 / 系统包 / 独立可执行 / 另一包管理器)——检查器自身也会假阴性(tag 重建错、缺 --target),"不可用"的结论被信了之后,整条工具升级路线都会被误关。细则见 re-dynamic §4。⑤ flag 类结论的唯一合法 VERIFIED 证据 = 未修改的原程序/平台接受候选输入(chal session 循环论证事故:把自写探针 [ord(c) for c in _var1] == _var3 当程序判定,交付错 flag 并标 --independent yes——探针里 _var1 就是输入本身,恒真)。自写探针/等价式只能支撑 --kind finding;flag/答案类结论必须 conclude --kind flag --program-accept "投喂命令 + 原程序成功响应原文"(缺证据 exit 2,且禁止 --source self-script),远程题则为平台接受回执。⑥ 自检强度分级 + 闭合锚定(f862c151/92a0a107 双会话临门一脚:用恒真的右逆自检确认了一个错的方程):L1 fwd(inv(B))==B 恒真——任何逆函数实现都构造性满足,零信息量,禁止落账为「已验证」;L2 inv(fwd(X_known))==X_known 左逆锚定——能抓常量/分支/接线错,手握 ground truth(如 'A'*L 采的 trace,反演结果前 L 字节必须是 0x41)必须拿它当锚,一行 assert 的事;L3 未修改原程序接受候选 = 唯一终审(⑤)。宣布「模型/反演已闭合」的结论必须 conclude --kind model --anchor "L2 断言+实测输出"(缺证据 exit 2)。只验变换不验方程 = 没验。
  4. 手写解析器必须双源验证(工具缺失 ≠ 自造轮子的许可证):自行实现的格式/字节码解析器(opcode 表、结构体偏移、指令解码、文件格式 parser),在据此下任何结论前,MUST 与第二个独立实现逐条比对至少一次——官方实现优先(SDK 自带工具),其次成熟第三方库;比对不上就装工具,装不了就标 ⚠UNVERIFIED(铁律 10③)禁止交付。「输出看起来合理」不构成正确性证据——表偏移类错误恰恰只产生语法合法、语义自洽、看似合理的输出(五题复盘:DEX opcode 表在 0x2d 多塞一个条目,if-lt 被读成 if-ne,标准 ROT13 显示成残废实现,差点自信交付)。已知的静默偏移陷阱(手写同类代码前先当自检清单过一遍):scripts/pe_info.py 的 PE32 ImageBase(PE32 在 opt+28,opt+24 是 BaseOfData;PE32+ 才在 opt+24)与 PE32+ 导入 thunk 宽度(8 字节 QWORD——按 4 字节读会撞上全零高半部,把导入列表静默截断成「每 DLL 1 个函数」)、AXML 字符串池偏移、DEX opcode 表条目数。配套纪律:oracle 必须成对(证明「正确输入被接受」之外,必须给出「近似错值被拒绝」的负对照,否则无法排除「凡输入皆通过」);解空间可枚举时穷举优先于公式(穷举同时产出答案与唯一性证明)。
  5. 异常即约束:观测到的不一致(重复键冲突、伪码长度 vs 实测、同一事实两次读数不同)必须 ledger.py anomaly --consequence "..." 转成可检验假设落账,禁止降级为"噪声/歧义待枚举";台账自身两条结论互相矛盾同样是异常(f862c151:_var2 32 项 ⇒ flag 17–32 字节 与 len(_p3res)==48 ⇒ flag 33–48 字节并存却 0 条 anomaly——自相矛盾正是诱饵的指纹);存在 open anomaly 时 stuck 必须 --ack 引用或先 resolve --waive;工具缺失导致的客观不可查走 waive,不许硬卡。待检验的模型/推断(不止观测到的不一致)落 ledger.py hypothesis --text --if-true --if-false --test——"不一致必须转成可检验假设"的假设对象就是它,open 在 render 单列置顶,关闭(confirmed/killed)必须 --evidence(与 resolve 反向门同构,缺证据 exit 2),客观不可检验走 --status waived --waive "理由"(豁免理由强制入账,render 单列可见)。写下就必须有下文:stop_check 收尾时机械检查 open hypothesis,带着未闭环假设交卷直接 deny(92a0a107 临门一脚:H1 精确写出真因却没跑,恢复轮把最后 3 分钟花在写报告上)。关闭异常的机械门(反向门,比正向门更重要):resolve --note 必须同时给 --evidence(复核命令/地址/读数),否则 exit 2——叙述性机制解释不是证据,不许用它解除约束;waive 通道豁免 --evidence(豁免理由强制入账),但 waived 在 status/render 里与 resolved 单独可见。
  6. 轴必须交叉(限枚举类解码/搜索任务):仅适用于候选空间可枚举的解码/搜索任务(隐信道解码、爆破类)——开跑前先出轴矩阵+候选预算(候选数 = Σ C(字段数,k) × 算子数 × 顺序源 × 打包 × 后变换),且轴矩阵+预算必须 ledger.py plan --axes --budget 落账,禁止只写在聊天里(复盘实证:不落账的轴矩阵永远不会被执行);预算算得出却仍剪轴必须写明理由;任一轴恒为 identity/常量 = 未覆盖,不得声称"试过"。与铁律 6 时间盒联动:预算 > 时间盒承受能力时升级方法(找 oracle/换数学洞察)而不是硬跑。不适用于需要数学洞察的密码题——那里穷举是最后手段。 模型内拟合搜索预算门(chal 复盘 G2):在自己写的模型(Python 拟合脚本)里做 >1e5 次候选搜索前,先自证输入数据(铁律 10②——"用错的观测数据做对的搜索"是最大时间黑洞,本次 10^7 组搜索全部建立错数据上),再找可分离未知量或检查点把搜索变求解;都不行 → 换观测手段(机器级取数/打桩/仿真);该题型不存在观测手段时退回纯推断 + ⚠UNVERIFIED,不停手。正当爆破(弱 KDF/口令/小密钥空间异或)不归此门——走 hashcat/GPU 等专用工具。
  7. 判定性实验优先于继续读数:任一关键量(参数角色 / 通道归属 / 某因子是否参与计算)在 30 分钟或 3 次工具调用内未被扰动实验确认(钉住可疑因子为常量看输出是否变、翻转一个输入看哪路输出动),必须停止读码转做打桩实验,并按 --source runtime-oracle 落账。参数角色不得仅由调用约定/寄存器推断——"第 N 参数按惯例是输出缓冲区"是假设不是读数(DEFCON26 复盘:FUN_13d74 第一参数实为文件缓冲区,被读成输出,错模型持有数小时;推翻它只需一次几分钟的打桩实验)。瓶颈不是算力是"到证伪的距离":最高杠杆的两个动作是 oracle 打桩隔离单因子(oracle_family.py)与模型差分校验(model_diff.py),关键量存疑时先用它们,不要继续读码。

2. 快速上手(3 行)

RD="$HOME/.dsh/skills/ghidra-core/scripts/rpc_driver.py"

# 1) 开工:daemon 没起就起、二进制没 load 就 load(幂等),含全量分析
python "$RD" ensure /path/to/binary

# 2) 一键分诊 → @out 落盘;之后所有命令直接跟二进制路径,key 自动映射
python "$RD" "@$HOME/.dsh/ghidra-workspace/out/app.triage.json" triage /path/to/binary
python "$RD" decompile /path/to/binary main
python "$RD" xrefs-to /path/to/binary check_flag

# 3) 写操作(重命名/注释/patch)即刻生效并自动存盘,无需 exec-w
python "$RD" rename-function /path/to/binary FUN_00401000 check_flag

rpc_driver.py 做的事:项目映射(~/dsh-ghidra-workspace/projects-rpc/dsh_.gpr,junction 路径)、binary key 自动替换(不用记 /name-hash6 后缀)、--project 注入、@out 落盘、环境变量自给(GHIDRAINSTALLDIR/JAVA_HOME/LOCALAPPDATA 重定向/USERNAME=dsh)。 子命令:ensure|status|stop (ensure 支持 --timeout N 秒,等待期间每 12s 向 stderr 打心跳,大二进制首载不再像死掉)+ 其余全部透传给 ghidra-rpc CLI(decompile/functions/strings/disassemble/assemble/write-bytes/triage/exec-code/export-binary/emulate-function/version-track…,全量见 ghidra-rpc --help)。 二进制比对:version-track / function-diff 会自动把 B 也 load 进 A 的项目(VT 要求同项目)。

长任务(后台执行)

daemon 常驻后日常命令都是亚秒级,真正的长任务只剩 load(大文件导入+分析)和 version-track(全函数关联)——这类用 dsh Bash 工具的 run_in_background 跑,靠 @out 落盘拿结果:

# 后台跑 version-track(大样本对),结果落 @out 文件
python "$RD" "@$HOME/.dsh/ghidra-workspace/out/vt.json" version-track old.exe new.exe --changed-only
# → 拿到 task_id 后继续干别的;完成通知到达后 Read 该 json

判断完成的信号是 @out 文件出现且 JSON 有效;stdout 摘要行只有几行,不要从前台输出抠大结果。

本地计算型长任务(爆破/拟合/搜索,timeout ≥300s)必须走 scripts/guarded_run.py(chal session 事故:nohup timeout 1200 python3 bf.py > log & ——python 块缓冲 + 到点 SIGTERM,20 分钟计算日志 0 字节):

python3 "$SK/guarded_run.py" --timeout 1200 --log out/job.log -- python3 -u bf.py

逐行 tee 落盘(每行 flush,杀掉也有)、静默 30s 心跳、到点先 terminate 宽限 5s 再 kill、结束打印 rc/耗时/log 路径;超时退出码 124 对齐 timeout(1)。hooks 层 gate_longrun.py 会拦下裸 timeout ≥300s + python 脚本 的命令。

GUI(launch_gui.py)

python "$SK/launch_gui.py"                      # 裸启动 Ghidra GUI
python "$SK/launch_gui.py" --open /path/to/bin  # 打开该二进制的 dsh_ 项目
python "$SK/launch_gui.py" --project dsh_ # 按项目名打开

detached 启动,脚本立即返回 PID,GUI 输出进 logs/gui-launch.log;关闭用 taskkill //PID //F 或 GUI 内退出。GUI 以 USERNAME=dsh 启动(与 headless 创建的项目的属主一致,不会 NotOwnerException),settings 用真实用户目录。

何时该去 GUI:交互式 CFG/函数图深挖、人工比对多个函数、type archive(FIDB)制作、plugin 类交互工具(GOOMBA 等)。headless 已覆盖的事别去 GUI:导出 patched 二进制(export_binary.py)、patch(patch_bytes.py)、批量反编译、分诊。

环境自检(doctor.py)

python "$SK/doctor.py"          # 全绿 exit 0;任一 fail exit 1

输出分两块:

  • Ghidra 核心 8 项(决定 exit code,fail 即 exit 1):安装与两个启动器、JAVA_HOME/java 版本、pyghidra-venv、ghidra-rpc-venv、ghidra-rpc 包(editable 自 engine/)、工作区可写 + junction 解析、现有项目清单、daemon 起停冒烟(--quick 可跳过这项慢的)
  • toolchain 三层(独立成节,不进 exit code):Tier A 轻量高频(checksec/GoReSym/pyinstxtractor/frida/z3/rust-demangler/upx/unpacker,缺失=warn 按 hint 补装);Tier B 按需重装(angr/qiling/speakeasy/unipacker/ghidriff/SiMBA/strings/readelf);Tier C GUI/手工(dnSpyEx/de4dot/DIE/x64dbg/GOOMBA/golang-loader)

任何 skill 的路由表提到外部工具时,可用性以 doctor 的 toolchain 节为准——那是唯一真相源。换机器/升级 Ghidra/排查"怎么又起不来"时先跑它。

外来旧项目:从别处拷来的项目若 project.prp 的 OWNER 不是 dsh,headless open_project 首次打开会自动改写属主;GUI 则要求属主一致,手动把 OWNER VALUE="..." 改成 dsh 即可。

4. 裸命令模板(legacy 排障专用;日常用 rpc_driver.py)

daemon 整体不可用时的后路是 driver.py(pyghidra-venv,每次调用一个冷启动 JVM):

PY="$HOME/Desktop/src/ghidra-bridge/pyghidra-venv/Scripts/python.exe"
GH="C:/t001s/ghidra_12.1.3_PUBLIC_20260817/ghidra_12.1.3_PUBLIC"
WS="$HOME/dsh-ghidra-workspace"   # junction → ~/.dsh/ghidra-workspace;Ghidra 拒绝含 . 的路径元素,必须用 junction

export GHIDRA_INSTALL_DIR="$GH"
export JAVA_HOME="C:/Java"

# 首次:导入 + 全量分析 + 分诊(项目名 dsh_)
"$PY" -m pyghidra --project-path "$WS/projects" --project-name dsh_ \
  "C:/abs/path/binary.exe" "$SK/triage_scan.p

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Cristallin2006](https://github.com/Cristallin2006)
- **Source:** [Cristallin2006/ghidra-skill-for-dsh](https://github.com/Cristallin2006/ghidra-skill-for-dsh)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.