はじめに
Windowsで動作するアプリ(.exe)やライブラリ(.dll)が、OSに対して「自分は何者で、どう動くべきか」を伝えるための共通規格、それがPE(Portable Executable)フォーマットです。
PEファイルは単なるデータの塊ではなく、複数の「ヘッダー」と「セクション」で構成された厳密な階層構造を持っています。
1. PEフォーマットの主要コンポーネント
PEファイルは大きく分けて以下の7つのコンポーネントで構成されます。
① DOSヘッダー (DOS Header)
ファイルの先頭に位置し、ファイル形式を定義します。
-
特徴: 先頭の2バイトが
4D 5A(アスキーコードで "MZ")であれば、それはWindowsの実行ファイルであることを示します。 - 役割: 非常に古いOS(MS-DOS)との互換性のために存在します。
② DOSスタブ (DOS Stub)
MS-DOS環境でこのファイルを実行しようとした際に動作する小さなプログラムです。
-
メッセージ: 通常、
This program cannot be run in DOS mode.という文字列が含まれており、現代のWindows上では実行に影響を与えません。
③ PEファイルヘッダー (PE File Header)
バイナリの基本情報を格納します。
-
内容:
50 45("PE") というシグネチャから始まり、マシンの種類(32bit/64bit)、セクションの数、タイムスタンプなどが定義されています。
④ イメージ・オプショナルヘッダー (Image Optional Header)
「オプショナル」という名前ですが、実行ファイルにとっては極めて重要なセクションです。
- 役割: プログラムの開始点(エントリポイント)のアドレスや、メモリ上のロードサイズなどを定義します。
⑤ データディレクトリ (Data Dictionaries)
オプショナルヘッダーの一部で、インポート(外部DLLの参照)やエクスポートなどの重要なテーブルがどこにあるかを指し示すインデックスの役割を果たします。
⑥ セクションテーブル (Section Table)
後述する各「セクション」の名前、サイズ、ファイル上の位置、メモリ上の権限(読み取り専用、実行可能など)を記述したカタログです。
⑦ セクション (Sections)
ファイルの実際のコンテンツが格納される場所です。
2. 各セクションの役割一覧
ヘッダーが「説明書」だとすれば、セクションは「中身」そのものです。代表的なセクションとその目的は以下の通りです。
| セクション名 | 役割・目的 |
|---|---|
| .text | 実行コード: CPUが実行する命令そのものと、プログラムの開始点が含まれます。 |
| .data | 初期化済みデータ: 文字列やグローバル変数などが格納されます。 |
| .rdata / .idata | インポート情報: Windows APIや利用するDLL(Dynamic Link Library)のリストです。 |
| .reloc | 再配置情報: メモリのロード位置が変わった際にアドレスを調整するための情報です。 |
| .rsrc | リソース: アイコン、画像、メニューなどの視覚的素材が含まれます。 |
| .debug | デバッグ情報: 開発時のトラブルシューティング用データです。 |
3. バイナリ(Hex Dump)で見るPE構造
実際の calc.exe(電卓)のヘキサダンプを確認すると、構造が視覚的に分かります。
-
ファイル冒頭:
4D 5A(MZヘッダー) が確認できます。 -
スタブ付近:
54 68 69 73 20 ...(This program...) という文字列が見て取れます。 -
セクション定義: ダンプの中盤には
.text,.rdata,.dataといったセクション名が刻まれており、ここから実データがどこにあるかをOSが判断します。
detect-it-easyを使って、notepad見る
EntryPoint
メモリマップ
オフセット「0001f99c」を探す
まとめ
PEフォーマットを理解することは、Windowsの内部動作やマルウェア解析、リバースエンジニアリングを学ぶ上での第一歩です。すべてのWindowsアプリケーションは、この精巧な「設計図」に基づいて動いているのです。


