re-ghidra について
re-ghidraは、リバースエンジニア向けのGhidra静的解析ワークフローです。GUI操作とヘッドレス処理に対応し、スクリプト、逆コンパイル、型復元に加え、結果の検証と元サンプルの保全も扱います。
主な機能
- 01GUIでの移動、クロスリファレンス、逆コンパイル
- 02ヘッドレス取り込みと一括解析
- 03ラベル付けやバイト操作のスクリプト
- 04型と構造体の復元
- 05逆コンパイル結果の出力と検証
活用シーン
- 01PE、ELF、Mach-Oサンプルの一括解析
- 02関数呼び出しと参照関係の追跡
- 03ラベル付けや復号ループのエミュレーション
- 04関数境界と逆コンパイル結果の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dslsdzc/ rev-skills --skill re-ghidraインストール後、Claude Code で/re-ghidraを入力して読み込まれたか確認します。
同梱ファイルreferences/commands.mdreferences/gotchas.md
詳細
Ghidra リバースエンジニアリングワークフロー
使用する場合/使用しない場合
- 使用する:逆コンパイルと詳細な静的解析が必要な場合;ヘッドレスでの一括処理;スクリプトによる自動ラベル付け/復号ループ;PE/ELF/Mach-O をすべてサポート
- 使用しない:メモリが 4GB 未満の場合(起動時から動作が重いため、[[re-radare2]] に切り替え);素早い初期調査だけが必要な場合([[re-triage]] を使用)
- 使用しない:IDA のワークフローがすでにあり、対象が明確な場合(
RE_DECOMPILERセッション変数に従って選択)
ツールの準備
[[re-analyze/platform-tips]] を参照してください。Ghidra は静的解析の主力です(サンドボックス不要)。メモリの少ない環境では、各プラットフォームの経験に応じて [[re-radare2]] に切り替えてください。ヘッドレスでの一括処理はリモート環境に適しています。
Ghidra(公式インストール、Java 21 が必要)
- ダウンロード:GitHub の
NationalSecurityAgency/ghidrareleases からダウンロードし、解凍すれば使用できます(インストール不要) - JDK 21(Ghidra 11.3+ で必要):
- Linux:
apt install openjdk-21-jdk/dnf install java-21-openjdk/pacman -S jdk21-openjdk - macOS:
brew install openjdk@21またはbrew install --cask temurin - Windows:
choco install temurin21(または Oracle JDK 21)
- Linux:
- 起動:
./ghidraRun(GUI)/./support/analyzeHeadless(ヘッドレス) - 確認:
java -version(21+ が必要);./support/analyzeHeadless -helpで正常に出力されること - バージョン:現在のメインラインは 12.x(確認済みの基準バージョンは 12.1.4)です。インストール時は公式 Releases の Latest を基準にしてください。公式リリースの実行には JDK 21 のみが必要です。Ghidra 自体をソースからビルドするには JDK 25 + Gradle 9.1+ が必要です。11.x → 12.x ではスクリプト API に互換性を損なう変更があるため、スクリプトを作成する際は対象バージョンの javadoc を確認してください。詳細は [[gotchas]] を参照してください。
ghidra-bridge(Python によるリモート制御)
- 全プラットフォーム:
pip install ghidra-bridge - 前提条件:Ghidra GUI の Script Manager で
ghidra_bridge_server.pyを実行します - 確認:
python3 -c "import ghidra_bridge; print(ghidra_bridge.__version__)"
操作手順
-
analyzeHeadless によるヘッドレスインポート+解析:
$GHIDRA/support/analyzeHeadless /tmp/proj sample_proj \ -import ./sample.bin -deleteProject -log /tmp/ghidra.logプロジェクトを作成するだけで対話操作を行わない場合は
-overwriteを追加します。複数のサンプルを一括処理するにはループで呼び出します。ログは-logで確認します。解析完了の目安は、例外がなく、プロジェクトを再度インポートできることです。-processモード(インポート済みプロジェクト内のファイルに対してスクリプト/解析を再実行する場合に使用します。-importとの併用はできません):$GHIDRA/support/analyzeHeadless /tmp/proj sample_proj \ -process -postScript MyScript.java -scriptPath /tmp/scripts- シンボル/文字列/単一関数の逆コンパイルだけを行う場合は
-noanalysisを追加します(自動解析をスキップし、数秒で完了します)。読み取り専用で再確認する場合は-readOnlyを追加します。すべてのパラメーターの一覧は [[commands]] を参照してください。
-
GUI:ナビゲーション/クロスリファレンス/逆コンパイル:
File > Import File→ サンプルを選択 →Analyze(左下の進捗表示が完了するまで待ちます)- 移動:
Go To(G)にアドレスを入力します。エントリーポイントは Program Trees でentryと表示されます - クロスリファレンス:関数/変数にカーソルを置いて
Rを押します(References ウィンドウ)。または右クリック > References > Show References To を選択します - 逆コンパイル:Listing で
Ctrl+Eを押します(Decompiler ウィンドウ。既定のショートカットはバージョン/keymap によって異なる場合があるため、Help > Key Bindings を確認してください)。または右クリック > Decompile Function を選択します。逆コンパイルビューからコピーできます - 関数グラフ:関数上で
Fを押すと、分岐/ループ構造を確認できます(Function Graph)。Decompiler と連動してナビゲーションできます - アンダースコア付きアドレスの違い:Listing には VA(ImageBase を含む)が表示されます。スクリプトでは、一般的に
getAddressFactory().getDefaultAddressSpace().getAddress("0x401000")を使用します
-
名前変更+型伝播によるラベル付け:
- 関数名の変更:Listing で
Lを押します。変数名の変更:Decompiler でLを押します - 型の設定:変数を右クリック > Set Data Type(
y)を選択します。例:char *、DWORD、int (*)(int) - 構造体の定義:Data Type Manager > 新しい Structure を作成します。Decompiler で参照すると、型伝播によって逆コンパイルの品質が自動的に向上します
- 既知のライブラリ関数にラベルを付ける:右クリック > Set Data Type +
f(Function signature)を選択すると、後続の呼び出し箇所で引数の意味を把握しやすくなります
- 関数名の変更:Listing で
-
Python スクリプト(自動ラベル付け、復号ループのシミュレーション):
# @category Analysis — 放 GhidraScripts 目录,Script Manager 中 Run from ghidra.program.model.listing import CodeUnit fm = currentProgram.getFunctionManager() for f in fm.getFunctions(True): body = f.getBody() if body.getNumAddresses() > 10000: print("large:", f.getName(), hex(body.getMaxAddress().getOffset()))復号ループ:XOR ループを特定した後、スクリプトでパッチを適用するか、直接計算します。
from ghidra.program.model.mem import * fm = currentProgram.getFunctionManager() f = fm.getFunctionAt(currentAddress) # 示例: 从 0x403000 起 0x100 字节异或 0x55 addr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress("0x403000") for i in range(0x100): b = getByte(addr.add(i)) ^ 0x55 setByte(addr.add(i), b)- バイトを書き換える前にコピーを作成してください:
setByteは現在の Program に直接書き込みます(保存すると元のファイルが変更されます)。悪意のあるサンプルを分析する場合は、必ず事前に Program をコピーする(File > Save Asで別名保存する)か、一時コピーに対して操作してください。証拠保全の連鎖を損なうため、元のサンプルに直接パッチを適用することは禁止です。 ヘッドレスでの一括処理:analyzeHeadless ... -postScript MyScript.java -scriptPath <dir>
- バイトを書き換える前にコピーを作成してください:
-
逆コンパイルした C のエクスポート:
File > Export Program→ 形式でC/C++を選択し、逆コンパイルツリー全体をエクスポートします- または Decompiler ウィンドウで関数ごとに
Copyしてノートに貼り付けます - エクスポートされるのは逆コンパイル結果であり、元のソースコードが復元されるわけではありません:変数名/型の推定は誤っている可能性があります(名前を変更すると改善します)。元の実装を示すものではありません。閲覧の補助としてのみ使用し、重要なロジックは必ず逆アセンブル結果/Listing と照合して検証してください。
- エクスポート後の確認:C では、シンボルのない関数名がコメント(関数アドレス)として保持されます。元の Listing と照合してください。
関数分析のコンテキストチェックリスト
各関数を分析する前に、情報を収集してください([[re-analyze/analysis-contract]] のコンテキストチェックリストを参照):xrefs(その関数を参照する関数/その関数が参照する関数)、対象関数が参照する文字列、caller/callee のシグネチャ、名前付きシンボルテーブル、復元済みの struct。一度にすべてそろえてから分析し、xrefs を何度も確認するのを避けてください。各関数につき、追加の証拠を能動的に求めるツール呼び出しは 8 回以内にしてください。
単一関数の詳細分析の順序
[[re-analyze/analysis-contract]] の「単一関数の詳細分析の順序」に従って、5 つのステップ(types → constants → vtables → identity → decompilation)を進めてください(ステップを飛ばしたり、先に逆コンパイルしてから逆算したりしてはいけません)。Ghidra での対応する操作:型には Type Manager / Apply Function Signature を使用します。仮想関数テーブルには vtable 分析を使用します。シンボル/定数の証拠は、readelf / strings / objdump でエクスポートして補助情報として利用できます。
分野横断の連携
-
[[re-address-space]]:Ghidra のベースアドレスと実行時アドレスの換算(load bias)
-
[[re-binary-core]]:ワークフローの第 5 ステップで既定の逆コンパイラー
-
[[re-malware]]:悪意のあるサンプルの詳細分析(難読化スクリプトによるラベル付け)
-
[[re-ctf]]:リバースエンジニアリング問題の主力
-
[[re-firmware]]:ファームウェア ELF コンポーネントの逆コンパイル
-
[[re-mobile]]:App の .so ライブラリ分析
-
[[re-format-pe]] / [[re-format-elf]] / [[re-format-macho]] と組み合わせて構造を読み取ります。メモリの少ない環境では [[re-radare2]] を使用してください
常见坑与陷阱
-
自动分析漏掉混淆代码:花指令/乱序代码段可能未被反汇编——手动选中段按
C(code)强制标记,必要时修复函数边界(右键 > Create Function) -
Java 版本不匹配启动失败:报
UnsupportedClassVersionError→ 确认java -version为 21+,JAVA_HOME指向正确 JDK -
内存 <4GB 卡顿:分析大二进制内存耗尽 → 换 [[re-radare2]] 或减小分析范围(
-analysisTimeoutPerFile) -
headless 默认分析选项与 GUI 有差异(缺少部分可选项)→ 用
-postScript显式执行分析脚本保证一致 -
大文件自动分析卡死:现象——导入大二进制后自动分析长时间不结束/界面卡死;原因——大文件卡死诱因=间接调用爆炸/大型 C++ RTTI/混淆控制流/大量数据段;对策——先降低自动分析范围(限制/关闭间接调用与 RTTI 分析选项),优先定位入口/字符串/交叉引用再逐步展开,见 [[re-analyze/platform-tips]] 静态优先原则
-
函数边界异常 → 检查反编译假象:现象——反编译视图里函数被错误拆分/合并、多出假参数或栈变量错乱、函数体看着像垃圾数据,照此分析得出荒谬逻辑;原因——手写汇编、混淆代码、尾调用(tail call 使相邻函数被错误合并)、无 frame pointer(不用 rbp/ebp 使帧推断失真)会让 decompiler 的边界与帧推断出错;对策——先核对 Listing 汇编与真实字节,按
C/Create Function 手工修正边界,尾调用与无 frame pointer 的函数以汇编语义为准、不完全相信反编译输出(见 [[re-binary-core]] 分析方法论 R4) -
内置脚本解释器是 Jython 2.7,不是 Python 3:现象——脚本一跑就报
SyntaxError(f-string/海象运算符)或ImportError(找不到 pip 安装的三方库);原因——Ghidra 内置 Jython 2.7,是 Python 2 语法与标准库,不支持 Python 3 语法,也无法 import pip 装的包;对策——脚本按 Python 2 兼容语法写(不用 f-string、用xrange),需要现代 Python 能力(numpy 等)时改用 ghidra-bridge 让外部 Python 3 解释器驱动分析(见工具准备) -
脚本/扩展选型失当 → 自动化维护成本失控:现象——一次性批处理逻辑越写越复杂、每次手动触发很烦,或需要常驻自动化却反复手动点脚本;原因——Script(脚本:轻量单文件、手动触发、适合一次性/简单重复任务)与 Extension(扩展:可注册菜单/面板/事件监听、随工程加载自动执行、ZIP 打包团队分发)的边界没分清;对策——简单重复任务用脚本即用即走;需要 UI 集成、外部服务接入、加载时自动执行或团队标准化分发时才做扩展
-
脚本 API 跨版本不兼容:现象——headless 脚本编译失败(skipping 且报
getPermissions()/getExecute()类方法不存在);原因——Ghidra 版本间 MemoryBlock 等 API 变更(12.x 为isExecute(),不同版本方法名不同);对策——写脚本前先查当前版本 javadoc(小验证脚本),编译失败先怀疑 API 差异而非业务逻辑 -
全量分析太慢就 -noanalysis:只做符号表/字符串/单函数反编译时,
analyzeHeadless -noanalysis导入后脚本可直接用——符号(含 JNI 导出)与字符串扫描不依赖 auto-analysis,秒级完成 -
命令速查(headless 参数族 / GUI 快捷键族 / 脚本 API 族)见 [[commands]];版本差异、无头批处理与脚本 API 的更多坑见 [[gotchas]]