マスタリングGhidra

―基礎から学ぶリバースエンジニアリング完全マニュアル

[cover photo]
TOPICS
Security
発行年月日
PRINT LENGTH
668
ISBN
978-4-87311-992-2
原書
The Ghidra Book: The Definitive Guide
FORMAT
Print PDF EPUB
Ebook
5,280円
Ebookを購入する
Print
5,280円

本書は、NSA(米国家安全保障局)が公開したソフトウェアリバースエンジニアリングツール「Ghidra」の総合的な解説書です。ソフトウェア・ハードウェア製品の構造を分析し、動作やソースコードなどの技術情報を調査し明らかにするリバースエンジニアリングの基礎からGhidraの高度なテクニックまで紹介し、リバースエンジニアリングの初心者から経験豊富な実務者まで学ぶことができます。内容は大きく5部に分かれ、第I部はディスアセンブル、リバースエンジニアリング、およびGhidraプロジェクトについて、第II部はGhidraの基本的な使い方、第III部はGhidraをカスタマイズして自動化する方法、第IV部は特定のGhidraモジュールのより詳細な説明、第V部はリバースエンジニアが遭遇する可能性のある状況にGhidraをどのように適用できるかを紹介しています。

正誤表

ここで紹介する正誤表には、書籍発行後に気づいた誤植や更新された情報を掲載しています。以下のリストに記載の年月は、正誤表を作成し、増刷書籍を印刷した月です。お手持ちの書籍では、すでに修正が施されている場合がありますので、書籍最終ページの奥付でお手持ちの書籍の刷版、刷り年月日をご確認の上、ご利用ください。

第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