本書は、NSA(米国家安全保障局)が公開したソフトウェアリバースエンジニアリングツール「Ghidra」の総合的な解説書です。ソフトウェア・ハードウェア製品の構造を分析し、動作やソースコードなどの技術情報を調査し明らかにするリバースエンジニアリングの基礎からGhidraの高度なテクニックまで紹介し、リバースエンジニアリングの初心者から経験豊富な実務者まで学ぶことができます。内容は大きく5部に分かれ、第I部はディスアセンブル、リバースエンジニアリング、およびGhidraプロジェクトについて、第II部はGhidraの基本的な使い方、第III部はGhidraをカスタマイズして自動化する方法、第IV部は特定のGhidraモジュールのより詳細な説明、第V部はリバースエンジニアが遭遇する可能性のある状況にGhidraをどのように適用できるかを紹介しています。
マスタリングGhidra
―基礎から学ぶリバースエンジニアリング完全マニュアル
Chris Eagle、Kara Nance 著、石川 朝久 監訳、中島 将太、小竹 泰一、原 弘明 訳
- TOPICS
- Security
- 発行年月日
- 2022年05月
- PRINT LENGTH
- 668
- ISBN
- 978-4-87311-992-2
- 原書
- The Ghidra Book: The Definitive Guide
- FORMAT
- Print PDF EPUB
正誤表
ここで紹介する正誤表には、書籍発行後に気づいた誤植や更新された情報を掲載しています。以下のリストに記載の年月は、正誤表を作成し、増刷書籍を印刷した月です。お手持ちの書籍では、すでに修正が施されている場合がありますので、書籍最終ページの奥付でお手持ちの書籍の刷版、刷り年月日をご確認の上、ご利用ください。
第1刷正誤表
※2022年12月更新
■P.189 「8.4.7 有用なリファレンス」に注釈を追加
詳細は、“Reversing Microsoft Visual C++ Part II: Classes, Methods and RTTI”(http://www.openrce.org/articles/full_view/23)と“Reversing C++”(https://www.blackhat.com/presentations/bh-dc-07/Sabanal_Yason/Paper/bh-dc-07-Sabanal_Yason-WP.pdf)を参照。
■P. 332 「次のx86コードは、DEFCONのCapture the Flagで使用されたバイナリのスニペットです。」の後のコード抜け
【正】
08049ede MOV dword ptr [EBP + local_8],0x0
LAB_08049ee5
08049ee5 CMP dword ptr [EBP + local_8],0x3c1
08049eec JA LAB_08049f0d
08049eee MOV EDX,dword ptr [EBP + local_8]
08049ef1 ADD EDX,DAT_0804b880
08049ef7 MOV EAX,dword ptr [EBP + local_8]
08049efa ADD EAX,DAT_0804b880
08049eff MOV AL,byte ptr [EAX]=>DAT_0804b880
08049f01 XOR EAX,0x4b
08049f04 MO byte ptr [EDX],AL=>DAT_0804b880
08049f06 LEA EAX=>local_8,[EBP + -0x4]
08049f09 INC dword ptr [EAX]=>local_8
08049f0b JMP LAB_08049ee5
目次
目 次 謝辞 訳者まえがき はじめに 第I部 リバースエンジニアリング入門 1章 ディスアセンブル入門 1.1 ディスアセンブルの原理 1.2 ディスアセンブルとは 1.3 なぜディスアセンブルが必要なのか 1.3.1 マルウェア解析 1.3.2 脆弱性の分析 1.3.3 ソフトウェアの相互運用性 1.3.4 コンパイラの検証 1.3.5 デバッグ時の表示 1.4 どのようにディスアセンブルするか 1.4.1 ディスアセンブルアルゴリズムの基礎 1.4.2 線形掃引ディスアセンブル 1.4.3 再帰下降ディスアセンブル 1.5 まとめ 2章 リバースエンジニアリングツール 2.1 ファイルの識別 2.1.1 file 2.1.2 PE Tools 2.1.3 PEiD 2.2 ファイルの概要把握 2.2.1 nm 2.2.2 ldd 2.2.3 objdump 2.2.4 otool 2.2.5 dumpbin 2.2.6 c++filt 2.3 ファイルの詳細分析 2.3.1 strings 2.3.2 ディスアセンブラ 2.4 まとめ 3章 Ghidraとの邂逅 3.1 ライセンス 3.2 対応 OS 3.3 公式ドキュメント 3.4 ダウンロード 3.5 インストール方法 3.5.1 ディレクトリ構成 3.5.2 起動方法 3.6 まとめ 第II部 Ghidraの基本的な使い方 4章 Ghidra入門 4.1 Ghidraを起動する 4.2 新しいプロジェクトの作成 4.2.1 ファイルの読み込み 4.2.2 Raw Binaryローダを使う 4.3 Ghidraによるファイル解析 4.3.1 Auto Analysis結果 4.4 初期解析時の Ghidraの挙動 4.4.1 作業内容の保存と終了 4.5 Ghidraを使うためのヒントとコツ 4.6 まとめ 5章 Ghidraによるデータ表示 5.1 CodeBrowser 5.2 CodeBrowserの各種ウィンドウ 5.2.1 Listingウィンドウ 5.2.2 Function Graphビュー 5.2.3 Program Treesウィンドウ 5.2.4 Symbol Treeウィンドウ 5.2.5 Data Type Managerウィンドウ 5.2.6 Consoleウィンドウ 5.2.7 Decompilerウィンドウ 5.3 その他のウィンドウ 5.3.1 Bytesウィンドウ 5.3.2 Defined Dataウィンドウ 5.3.3 Defined Stringsウィンドウ 5.3.4 Symbol Tableウィンドウと Symbol Referencesウィンドウ 5.3.5 Memory Mapウィンドウ 5.3.6 Function Call Graphウィンドウ 5.4 まとめ 6章 Ghidraによるディスアセンブルの理解 6.1 ディスアセンブル結果の調査 6.1.1 シンボルとラベル 6.1.2 ナビゲーション 6.1.3 Go To 6.1.4 ナビゲーションの履歴 6.2 スタックフレーム 6.2.1 関数呼び出しの仕組み 6.2.2 様々な呼び出し規約 6.2.3 その他の考慮事項 6.2.4 ローカル変数のレイアウト 6.2.5 スタックフレームの例 6.3 Ghidraでのスタックの表示 6.3.1 スタックフレームの解析 6.3.2 Listingビューでのスタックフレーム 6.3.3 デコンパイラを用いたスタックフレームの解析 6.3.4 オペランドでのローカル変数 6.3.5 Stack Frame Editor 6.4 検索 6.4.1 Search Program Text 6.4.2 Search Memory 6.5 まとめ 7章 ディスアセンブル結果の操作 7.1 名前とラベルの操作 7.1.1 引数名とローカル変数名の変更 7.1.2 ラベル名の変更 7.1.3 新しいラベル 7.1.4 ラベルの編集 7.1.5 ラベルの削除 7.1.6 ラベルによるナビゲーション 7.2 コメント 7.2.1 EOLコメント 7.2.2 プレコメントとポストコメント 7.2.3 プレートコメント 7.2.4 リピータブルコメント 7.2.5 引数とローカル変数へのコメント 7.2.6 アノテーション 7.3 基本的なコードの変換 7.3.1 コード表示設定の変更 7.3.2 オペランドのフォーマット 7.3.3 関数に対する操作 7.3.4 データからコードへの変換 7.4 基本的なデータの変換 7.4.1 データ型の変換 7.4.2 文字列の検索 7.4.3 配列の定義 7.5 まとめ 8章 データの型と構造 8.1 データを理解する 8.2 データ構造を理解する 8.2.1 配列のメンバへの参照 8.2.2 構造体メンバへの参照 8.3 構造体を Ghidraで作成する 8.3.1 新しい構造体の作成 8.3.2 構造体のメンバの編集 8.3.3 構造体のレイアウトの適用 8.4 C++で書かれたプログラムのリバースエンジニアリング 8.4.1 thisポインタ 8.4.2 仮想関数と Vftable 8.4.3 オブジェクトのライフサイクル 8.4.4 名前マングリング 8.4.5 ランタイムの認識 8.4.6 継承関係 8.4.7 有用なリファレンス 8.5 まとめ 9章 相互参照 9.1 参照の基礎 9.1.1 相互参照(後方参照) 9.1.2 参照の例 9.2 Reference Managementウィンドウ 9.2.1 Xrefsウィンドウ 9.3 まとめ 10章 グラフ 10.1 基本ブロック 10.2 Function Graph 10.3 Function Call Graph 10.4 Tree 10.5 まとめ 第III部 Ghidraを使いこなす方法 11章 コラボレーションSRE 11.1 チームワーク 11.2 Ghidra Serverのセットアップ 11.3 共有プロジェクト 11.3.1 共有プロジェクトの作成 11.3.2 プロジェクト管理 11.4 Projectウィンドウのメニュー 11.4.1 Fileメニュー 11.4.2 Editメニュー 11.4.3 Projectメニュー 11.5 プロジェクトとリポジトリ 11.5.1 バージョン管理 11.5.2 シナリオ例 11.6 まとめ 12章 Ghidraのカスタマイズ 12.1 CodeBrowser 12.1.1 ウィンドウの再配置 12.1.2 ツールオプションの編集 12.1.3 ツールの編集 12.1.4 ツールのカスタム設定 12.1.5 CodeBrowserのレイアウトを保存する 12.2 Ghidra Projectウィンドウ 12.3 ツール 12.4 ワークスペース 12.5 まとめ 13章 Ghidraの機能拡張 13.1 ファイルのインポート 13.2 アナライザ(Analyzer) 13.3 単語モデル 13.4 データタイプ 13.4.1 新規データ型アーカイブの作成 13.5 Function ID 13.6 Function IDプラグイン 13.6.1 Function IDプラグインの例:UPX 13.6.2 Function IDプラグインの例:静的ライブラリのプロファイリング 13.7 まとめ 14章 スクリプティングの基礎 14.1 Script Manager 14.1.1 Script Managerウィンドウ 14.2 スクリプトの開発 14.2.1 Javaスクリプトを書く(JavaScriptではありません!) 14.2.2 スクリプト編集例:正規表現を用いた検索 14.2.3 Pythonスクリプト 14.2.4 他言語のサポート 14.3 Ghidra API 14.3.1 Addressインタフェース 14.3.2 Symbolインタフェース 14.3.3 Referenceインタフェース 14.3.4 GhidraScriptクラス 14.3.5 Programクラス 14.3.6 Functionインタフェース 14.3.7 Instructionインタフェース 14.4 Ghidraスクリプトの作成例 14.4.1 例1:関数を列挙する 14.4.2 例2:命令を列挙する 14.4.3 例3:相互参照の列挙 14.4.4 例4:関数の呼び出し元を探す 14.4.5 例5:アセンブリ命令を模倣する 14.5 まとめ 15章 EclipseとGhidraDevプラグイン 15.1 Eclipse 15.1.1 Eclipseの統合 15.1.2 Eclipseを始めよう 15.1.3 Eclipseでスクリプトを編集する 15.2 GhidraDevメニュー 15.2.1 [GhidraDev] > [New]サブメニュー 15.2.2 Package Explorerを使う 15.3 例:Ghidraアナライザ・モジュール・プロジェクト 15.3.1 ステップ1:解決すべき課題を定義する 15.3.2 ステップ2:Eclipseでモジュールを作成する 15.3.3 ステップ3:アナライザを作成する 15.3.4 ステップ4:Eclipseを使ってアナライザをテストする 15.3.5 ステップ5:アナライザを Ghidraにインストールする 15.3.6 ステップ6:インストールしたアナライザをテストする 15.4 まとめ 16章 ヘッドレス・モード 16.1 実行してみよう 16.1.1 ステップ1:Ghidraを立ち上げる 16.1.2 ステップ2と3:新規 Ghidraプロジェクトを指定したパスに作成する 16.1.3 ステップ4:ファイルをプロジェクトにインポートする 16.1.4 ステップ5と6:ファイルを自動解析し、保存して終了する 16.1.5 オプションと引数 16.2 Ghidraスクリプトの作成 16.2.1 HeadlessSimpleROP 16.2.2 FidDb作成の自動化 16.3 まとめ 第IV部 さらなる深みへ 17章 Ghidraローダ 17.1 未知のファイル解析 17.2 Windows PEファイルの手動ロード 17.3 例1:シンプルなシェルコードローダモジュール 17.3.1 ステップ0:一歩引いてみる 17.3.2 ステップ1:問題の定義 17.3.3 ステップ2:Eclipseモジュールの作成 17.3.4 ステップ3:ローダの構築 17.3.5 ステップ4:Ghidraにローダを追加する 17.3.6 ステップ5:Ghidra内でローダをテストする 17.4 例2:シンプルなシェルコードソースローダ 17.4.1 更新1:インポータへの応答を変更する 17.4.2 更新2:ソースコードからシェルコードを探す 17.4.3 更新3:シェルコードをバイト値に変換する 17.4.4 更新4:変換されたバイト配列をロードする 17.4.5 結果 17.5 例3:シンプルな ELFシェルコードローダ 17.5.1 ハウスキーピング 17.5.2 ELFヘッダフォーマット 17.5.3 サポートされているロード仕様を探す 17.5.4 ファイルの内容を Ghidraに読み込む 17.5.5 データバイトフォーマットとエントリポイントの追加 17.5.6 言語定義ファイル 17.5.7 opinionファイル 17.5.8 結果 17.6 まとめ 18章 Ghidraプロセッサ 18.1 Ghidraプロセッサモジュールを理解する 18.1.1 Eclipseのプロセッサモジュール 18.1.2 SLEIGH 18.1.3 プロセッサマニュアル 18.2 Ghidraプロセッサモジュールの変更 18.2.1 問題提起 18.2.2 例1:プロセッサモジュールへの命令の追加 18.2.3 例2:プロセッサモジュール内の命令の修正 18.2.4 例3:プロセッサモジュールへのレジスタの追加 18.3 まとめ 19章 Ghidraデコンパイラ 19.1 デコンパイラ解析 19.1.1 Analysisオプション 19.2 Decompilerウィンドウ 19.2.1 例1:Decompilerウィンドウの編集 19.2.2 例2:リターンしない関数 19.2.3 例3:構造体の自動作成 19.3 まとめ 20章 コンパイラのバリエーション 20.1 ハイレベルな構成要素 20.1.1 switch文 20.1.2 例:gccと Microsoft C/C++コンパイラの比較 20.2 コンパイラのビルドオプション 20.2.1 例1:モジュロ演算子 20.2.2 例2:三項演算子 20.2.3 例3:関数のインライン化 20.3 コンパイラ固有のC++実装 20.3.1 関数のオーバーロード 20.3.2 RTTIの実装 20.3.3 main関数の位置 20.4 まとめ 第V部 実世界のアプリケーションへの応用 21章 難読化されたコードの解析 21.1 アンチリバースエンジニアリング 21.1.1 難読化 21.1.2 アンチ静的解析技術 21.1.3 インポート関数の難読化 21.1.4 アンチ動的解析技術 21.2 Ghidraによるバイナリの静的難読化解除 21.2.1 スクリプトを利用した難読化解除 21.2.2 エミュレータベースの難読化解除 21.2.3 ステップ1:問題の定義 21.2.4 ステップ2:Eclipseスクリプトプロジェクトの作成 21.2.5 ステップ3:エミュレータのビルド 21.2.6 ステップ4:Ghidraにスクリプトを追加する 21.2.7 ステップ5:Ghidraを使ったスクリプトのテスト 21.3 まとめ 22章 バイナリのパッチ 22.1 パッチの計画 22.2 変更するものを見つける 22.2.1 メモリの検索 22.2.2 直接参照の検索 22.2.3 命令パターンの検索 22.2.4 特定の動作を見つける 22.3 パッチの適用 22.3.1 基本的な変更方法 22.3.2 簡単でない変更 22.4 ファイルのエクスポート 22.4.1 Ghidraのエクスポートフォーマット 22.4.2 Binaryエクスポートフォーマット 22.4.3 スクリプト支援エクスポート 22.5 例:バイナリのパッチ 22.6 まとめ 23章 バイナリ差分とバージョントラッキング 23.1 バイナリ差分 23.1.1 Program Diffツール 23.2 関数の比較 23.2.1 Function Comparisonウィンドウ 23.2.2 例:暗号化ルーチンの比較 23.3 Version Trackingツール 23.3.1 Version Trackingの概念 23.4 まとめ 付録A IDAユーザ向けのGhidra A.1 基礎編 A.1.1 データベース作成 A.2 基本的なウィンドウとナビゲーション A.2.1 Listingウィンドウ A.2.2 Graphウィンドウ A.2.3 Decompilerウィンドウ A.2.4 Symbol Treeウィンドウ A.2.5 Data Type Managerウィンドウ A.3 スクリプト A.4 まとめ 付録B デバッガ B.1 デバッグオプション B.2 各ウィンドウ B.2.1 Targetウィンドウ B.2.2 Consoleウィンドウ B.2.3 Objectsウィンドウ B.2.4 Interpreterウィンドウ B.2.5 Threadsウィンドウ B.2.6 Registersウィンドウ B.2.7 Dynamic Listingウィンドウ B.2.8 Stackウィンドウ B.2.9 Breakpointsウィンドウ B.2.10 Regionsウィンドウ B.2.11 Timeウィンドウ B.2.12 Modulesウィンドウ B.2.13 Static Mappingsウィンドウ B.2.14 Watchesウィンドウ B.2.15 Memviewウィンドウ B.3 デバッガの使用方法 B.4 おわりに 索引 コラム目次 x86アセンブリ構文:AT&T記法 VS Intel記法 Windows Subsystem for Linux バイナリ内のシンボルの削除 バイナリの難読化 ツールを使う際の注意事項 なぜ stringsは変わったのか? Auto Analysisによる警告 ツールバー・ホットキー・ボタンについて 内側に表示されるウィンドウと外側に表示されるウィンドウ 私のウィンドウはどこにあるの? お気に入りのバーは? Listingウィンドウの設定 Satelliteビュー ツール間の接続 グラフのカスタマイズ プログラム内を自由に移動するには 誰が関数を呼び出したのか? ラベル名を変更してみよう スタック上のデータは本当に消えるのか? レジスタによる引数の指定 Searchウィンドウの名前を変えることによる作業効率化 各種操作の取り消し方 禁止された名前 どのような名前をつけるべきか FUN_接頭辞 バグか機能か 下部の3つのボタン C言語が本当に期待すること シンボルを削られたバイナリ コメントによるシンボル情報の更新 共用体の役割 コンストラクタとは? new演算子とは? オーバーロードされた関数の発見 XREFの表示形式 余計な XREF? 基本ブロックとは グラフ表示を調整する Interaction Thresholdについて 「Graph is stale」メッセージについて Function Graphの操作 thunk関数について Ghidra Serverのカスタムインストール プロジェクトリポジトリ Ghidra Serverにおける管理者の種類 Ghidra Serverをプライベート用として使う バージョン管理と Version Tracking バージョン管理におけるコメント ファイルが乗っ取られた!助けて! ファイル読み込み時の言語とコンパイラの指定について Ghidraにおける Python 危険な関数 またそのスクリプトを作るの? ROPガジェットとは何か?なぜ特定する必要があるのか? スラッシュかバックスラッシュか? ワイルドカード! シェルコードとは何か?なぜ気にするのか? Eclipseでモジュールをテストする Ghidraの拡張に貢献しているのはどんな人ですか? Ghidraの SLEIGHエディタ P-CODE:どこまで低レイヤーになる? サンドボックス環境 プロセスのトレース CRACKME, CRACK YOURSELF