今回から、リバースエンジニアリングツールである Ghidra を使っていきます。
書籍「リバースエンジニアリングツールGhidra実践ガイド (Compass Booksシリーズ)」を読みながら進めていきます。
また、書籍「マスタリングGhidra ―基礎から学ぶリバースエンジニアリング完全マニュアル」も入手しました。こちらで覚えた内容も追記していきたいと思います。
それでは、やっていきます。
参考文献
はじめに
「セキュリティ」の記事一覧です。良かったら参考にしてください。
・第2回:Ghidraで始めるリバースエンジニアリング(使い方編)
・第3回:VirtualBoxにParrotOS(OVA)をインストールする
・第4回:HTTPを題材にtcpdumpの出力を理解する
・第5回:nginx(エンジンエックス)を理解する
・第6回:Python+Flask(WSGI+Werkzeug+Jinja2)を動かしてみる
・第7回:Python+FlaskのファイルをCython化してみる
・第8回:shadowファイルを理解してパスワードを解読してみる
・第9回:安全なWebアプリケーションの作り方(徳丸本)の環境構築
・第10回:Vue.jsの2.xと3.xをVue CLIを使って動かしてみる(ビルドも行う)
・第11回:Vue.jsのソースコードを確認する(ビルド後のソースも見てみる)
・第12回:徳丸本:OWASP ZAPの自動脆弱性スキャンをやってみる
・第13回:徳丸本:セッション管理を理解してセッションID漏洩で成りすましを試す
・第14回:OWASP ZAPの自動スキャン結果の分析と対策:パストラバーサル
・第15回:OWASP ZAPの自動スキャン結果の分析と対策:クロスサイトスクリプティング(XSS)
・第16回:OWASP ZAPの自動スキャン結果の分析と対策:SQLインジェクション
・第17回:OWASP ZAPの自動スキャン結果の分析と対策:オープンリダイレクト
・第18回:OWASP ZAPの自動スキャン結果の分析と対策:リスク中すべて
・第19回:CTF初心者向けのCpawCTFをやってみた
・第20回:hashcatの使い方(GPU実行時間の見積りとパスワード付きZIPファイル)
・第21回:Scapyの環境構築とネットワークプログラミング
・第22回:CpawCTF2にチャレンジします(クリア状況は随時更新します)
・第23回:K&Rのmalloc関数とfree関数を理解する
・第24回:C言語、アセンブラでシェルを起動するプログラムを作る(ARM64)
・第25回:機械語でシェルを起動するプログラムを作る(ARM64)
・第26回:入門セキュリティコンテスト(CTFを解きながら学ぶ実践技術)を読んだ
・第27回:x86-64 ELF(Linux)のアセンブラをGDBでデバッグしながら理解する(GDBコマンド、関連ツールもまとめておく)
・第28回:入門セキュリティコンテスト(CTFを解きながら学ぶ実践技術)のPwnable問題をやってみる
・第29回:実行ファイルのセキュリティ機構を調べるツール「checksec」のまとめ
・第30回:setodaNote CTF Exhibitionにチャレンジします(クリア状況は随時更新します)
・第31回:常設CTFのksnctfにチャレンジします(クリア状況は随時更新します)
・第32回:セキュリティコンテストチャレンジブックの「Part2 pwn」を読んだ
・第33回:セキュリティコンテストチャレンジブックの「付録」を読んでx86とx64のシェルコードを作った
・第34回:TryHackMeを始めてみたけどハードルが高かった話
・第35回:picoCTFを始めてみた(Beginner picoMini 2022:全13問完了)
・第36回:picoCTF 2024:Binary Exploitationの全10問をやってみた(Hardの1問は後日やります)
・第37回:picoCTF 2024:Reverse Engineeringの全7問をやってみた(Windowsプログラムの3問は後日やります)
・第38回:picoCTF 2024:General Skillsの全10問をやってみた
・第39回:picoCTF 2024:Web Exploitationの全6問をやってみた(最後の2問は解けず)
・第40回:picoCTF 2024:Forensicsの全8問をやってみた(最後の2問は解けず)
・第41回:picoCTF 2024:Cryptographyの全5問をやってみた(最後の2問は手つかず)
・第42回:picoCTF 2023:General Skillsの全6問をやってみた
・第43回:picoCTF 2023:Reverse Engineeringの全9問をやってみた
・第44回:picoCTF 2023:Binary Exploitationの全7問をやってみた(最後の1問は後日やります)
・第45回:書籍「セキュリティコンテストのためのCTF問題集」を読んだ
・第46回:書籍「詳解セキュリティコンテスト」のReversingを読んだ
・第47回:書籍「詳解セキュリティコンテスト」のPwnableのシェルコードを読んだ
・第48回:書籍「バイナリファイル解析 実践ガイド」を読んだ
・第49回:書籍「詳解セキュリティコンテスト」Pwnableのスタックベースエクスプロイトを読んだ
・第50回:書籍「詳解セキュリティコンテスト」Pwnableの共有ライブラリと関数呼び出しを読んだ
・第51回:picoCTF 2025:General Skillsの全5問をやってみた
・第52回:picoCTF 2025:Reverse Engineeringの全7問をやってみた
・第53回:picoCTF 2025:Binary Exploitationの全6問をやってみた
・第54回:書籍「詳解セキュリティコンテスト」Pwnableの仕様に起因する脆弱性を読んだ
・第55回:システムにインストールされたものと異なるバージョンのglibcを使う方法
・第56回:書籍「詳解セキュリティコンテスト」Pwnableのヒープベースエクスプロイトを読んだ
・第57回:書籍「解題pwnable」の第1章「準備」を読んだ
・第58回:書籍「解題pwnable」の第2章「login1(スタックバッファオーバーフロー1)」を読んだ
・第59回:書籍「解題pwnable」の第3章「login2(スタックバッファオーバーフロー2)」を読んだ
・第60回:書籍「解題pwnable」の第4章「login3(スタックバッファオーバーフロー3)」を読んだ
・第61回:書籍「解題pwnable」の第5章「rot13(書式文字列攻撃)」を読んだ
・第62回:GitHubが開発した静的解析ツール(脆弱性検出ツール)のCodeQLを使ってみる
・第63回:CodeQL(静的解析ツール)で使われるクエリの選ばれ方を調べた
・第64回:CodeQL(静的解析ツール)のクエリの書き方を調べた
・第65回:CodeQL(静的解析ツール)で使われているアラートクエリの中身を調べる
・第66回:CodeQL(静的解析ツール)で使われているパスクエリの中身を調べる
・第67回:CodeQL(静的解析ツール)をVSCodeで使う方法を理解する
・第68回:CodeQL(静的解析ツール)の挙動を確認するための対象ソースコードとしてTinyhttpdを調査する
・第69回:Tinyhttpdを使用してCodeQL(静的解析ツール)のクエリの挙動を確認する
・第70回:セキュアコーディング:CERT C INT02-C 「整数変換のルールを理解する」を調べる
・第71回:CodeQL(静的解析ツール)の挙動を確認するための対象ソースコードとしてlibusbを調査する
まず、書籍「リバースエンジニアリングツールGhidra実践ガイド (Compass Booksシリーズ)」のサポートサイトは以下です。
ここからサンプルプログラムがダウンロードできます。
今回は、Ghidra の環境を構築していきます。
Ghidraのインストール
Ghidra とは、アメリカ国家安全保障局(NSA:National Security Agency)によって開発されたソフトウェアリバースエンジニアリングのツールです。
よく使われる用途としては、実行プログラム(バイナリ)をディスアセンブル(アセンブラ言語に変換すること)と、デコンパイル(アセンブラ言語から、C言語のような高級言語に変換すること)を行い、実行プログラムの解析を行うことです。他のリバースエンジニアリングツールとして、IDA や、Binary Ninja があります。これらは、無償で使うこともできますが、非常に条件が厳しいです。例えば、IDA の無償版は x86 のプログラムにしか使えません。Binary Ninja の無償版はクラウドを利用しなければならないらしいです。一方、Ghidra はオープンソースなので、全ての機能が無償で利用できるところがメリットです。
まず、以下は、Ghidra の GitHub です。
インストール方法が書かれています。Ghidra は JDK の環境を準備すれば、あとは、リリースバイナリをダウンロードして、解凍するだけでインストールは完了します。Windows、Linux のどちらも同じ方法でインストールできるので、導入は大変簡単です。
Linuxにインストール
今回は、VirtualBox の Ubuntu 22.04 に Ghidra をインストールしていきます。
まず、JDK 17 64bit をインストールします。
私は既にインストール済みですが、以下で簡単にインストールできます。
$ sudo apt install openjdk-17-jdk
続いて、Ghidra の GitHub の releases から zipファイルをダウンロードします。
ファイル名は、ghidra_11.0.3_PUBLIC_20240410.zip です。
※2024/8/30:追記
新しい gcc、g++ ビルドしたプログラムは、DWARF v5 が使われていて、Ghidra は、v11.1 から、この DWARF v5 に対応しています。ダウンロードするときは、v11.1 以降を選んだ方がいいです。
解凍します。
$ unzip ghidra_11.0.3_PUBLIC_20240410.zip
解凍したディレクトリの ghidraRun を起動します。
cd ghidra_11.0.3_PUBLIC/ ./ghidraRun
起動すると、使用許諾が出るので、問題なければ、I Agree をクリックします。

Ghidra が起動しました。

Windowsにインストール
Windows11 にインストールしていきます。
まずは、JDK をインストールします。JDK 25 が既にリリースされていますが、安定性を考えて、今回は、JDK 21 を選択します。
以下から、JDK 21.0.9 として、Windows の x64 Installer(msi でもいいと思います)をダウンロードします。
ダウンロードした exeファイルをダブルクリックします。次をクリックします。

インストール先を指定します。私はデフォルトでいいと思うので、次をクリックします。

JDK のインストールが完了しました。閉じるをクリックします。

続いて、Ghidra の GitHub の releases から zipファイルをダウンロードします。
ファイル名は、ghidra_12.0_PUBLIC_20251205.zip です。
これを解凍して、ghidraRun.bat をダブルクリックすれば、Ghidra が起動します。

インストールは以上で完了です。
プロジェクトの作成からプログラムの解析まで
プロジェクトの作成
Tip of the Day は閉じておきます。
プロジェクトを作成していきます。
File → New Project... をクリックします。

Non-Shared Project と Shared Project が選択として現れます。Shared Project は、共同で作業するためのプロジェクトで、Ghidra Server というのが必要らしく、通常は、Non-Shared Project を選びます。Nextをクリックします。

次に、プロジェクトの場所と、プロジェクト名を決めます。どちらも任意ですが、プロジェクトの場所とは、複数のプロジェクトが格納される場所なので、新しいディレクトリを作って、そこを指定してください。その下に、今回指定したプロジェクト名のディレクトリが出来ます。指定できたら、Finish をクリックします。

プロジェクトが作られました。

これからプログラムをロードするのですが、構造の分からないプログラムより、以前に作った STM32 のサンプルプログラムを使います。
daisuke20240310.hatenablog.com
プログラムのインポート
STM32 のプログラム(ELFファイル)をインポートします。
File → Import File... をクリックします。

STM32 の ELFファイルを指定すると、確認画面が出ます。
ELFファイルで、32bit の ARM と正しく認識していますので、OKをクリックします。

インポート結果のサマリが出ます。OKをクリックします。

プログラムの解析
続いて、プログラムを解析させます。
Active Project のテキストのアイコンをダブルクリックします。

すると、Code Browser が開き、解析するかどうか聞かれるので、Yes をクリックします。

解析オプションを聞かれるので、デフォルトのままでいいと思います。もしくは、Select All を選択して、Analyze をクリックします。

右下に解析状況が表示されています。解析が完了すると、ソースコードが表示されます。試しに main をクリックすると、デコンパイルされた結果が右のウィンドウに表示されます。

ちなみに、もとの main関数のソースコードは以下になります。
int main(void) { initialise_monitor_handles(); // セミホスティング機能の初期化 led_init(); // LEDの初期化 button_init(); // Buttonの初期化 systick_init(); // SysTickの初期化 // メインループ while (1) { time = g_system_time - lap_time; switch (state) { case WAINTING: waiting(); // 開始待ち break; case RUNNING: running(); // ルーレット回転中 break; case STOP_OK: stop_ok(); // 停止(成功) break; case STOP_NG: default: stop_ng(); // 停止(失敗) break; } } // ここには到達しない return 0; }
デバッグ情報が含まれている ELFファイルですが、ほぼ、Cソースコードを復元できています。
今回はここまでにします。
おわりに
今回から、Ghidra を使ったリバースエンジニアリングを始めました。
次回は、Ghidra の使い方を理解していきたいと思います。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。