RawrXD PEライター - 完全実装
概要
これは、純粋なx64 MASMアセンブリで実装され、依存関係がなく、CRTを使用しない完全なPE32+ライターおよびマシンコードエミッタです。スクラッチから実行可能なWindows実行ファイルを生成します。
アーキテクチャ
PEライターはバックエンドデザイナーアプローチに従い、以下のためのクリーンなAPIを提供します:
- PE実行可能コンテキストの作成
- 適切なIAT/INT構造を持つインポートの追加
- セクション管理を伴うマシンコードの発行
- 必要なすべてのヘッダーを含む完全なPEファイルの書き込み
コアコンポーネント
1. 定義された構造体
- IMAGE_DOS_HEADER: e_lfanewポインタを持つ標準DOSヘッダー
- IMAGE_NT_HEADERS64: ファイルヘッダーとオプショナルヘッダーを持つNTヘッダー
- IMAGE_SECTION_HEADER: .text, .rdata, .idata用のセクションヘッダー
- IMAGE_IMPORT_DESCRIPTOR: インポートテーブル記述子
- PE_CONTEXT: PEファイル構築用の内部コンテキスト構造体
2. 主要関数
PEWriter_CreateExecutable
- 入力: RCX = イメージベース (0 = デフォルト), RDX = エントリポイントRVA
- 出力: RAX = PEコンテキストハンドル (0 = 失敗)
- 目的: 完全なPEコンテキスト構造体を割り当て、初期化する
実装の詳細:
- DOSヘッダー、NTヘッダー、セクションヘッダー用のメモリを割り当てる
- 適切なシグネチャとe_lfanewでDOSヘッダーを初期化する
- AMD64マシンタイプとPE32+マジックでNTヘッダーを設定する
- イメージベース、セクション/ファイルアラインメントでオプショナルヘッダーを構成する
- コードバッファとインポートテーブルを割り当てる
- デフォルトの仮想アドレスとファイルオフセットを設定する
PEWriter_AddImport
- 入力: RCX = PEコンテキスト, RDX = DLL名, R8 = 関数名
- 出力: RAX = 1 成功, 0 失敗
- 目的: 適切なIAT/INT構造を持つインポートテーブルを構築する
実装の詳細:
- 複数のDLLのインポート記述子を管理する
- インポートルックアップテーブル (INT) エントリを作成する
- インポートアドレステーブル (IAT) エントリを設定する
- 名前によるインポート構造を処理する
- インポート数を追跡し、制限を検証する
PEWriter_AddCode
- 入力: RCX = PEコンテキスト, RDX = コードバッファ, R8 = コードサイズ
- 出力: RAX = コードのRVA (0 = 失敗)
- 目的: 適切なセクション管理を伴うマシンコードの発行を処理する
実装の詳細:
- マシンコードを内部バッファにコピーする
- コードサイズを最大制限に対して検証する
- コードのRVAを計算して返す
- 内部コードサイズ追跡を更新する
- .textセクションの内容を管理する
PEWriter_WriteFile
- 入力: RCX = PEコンテキスト, RDX = ファイル名
- 出力: RAX = 1 成功, 0 失敗
- 目的: すべてのヘッダー、セクション、インポートテーブルを含む完全なファイル書き込み
実装の詳細:
- 適切なWin32 API呼び出しで出力ファイルを作成する
- DOSヘッダーとDOSスタブを書き込む
- 最終的なNTヘッダー値を計算して更新する
- .text, .rdata, .idataのセクションヘッダーを書き込む
- 適切なファイルパディングとアラインメントを実装する
- インポートテーブルを含むセクションデータを書き込む
- すべてのRVA計算とファイルオフセットを処理する
メモリ管理
実装はWindowsヒープAPIを使用します:
- GetProcessHeap(): 現在のプロセスヒープを取得
- HeapAlloc(): ゼロ初期化されたメモリを割り当て
- HeapFree(): クリーンアップ時に割り当てられたメモリを解放
すべてのメモリ割り当てには、適切なエラーハンドリングとクリーンアップが含まれます。
ファイル構造レイアウト
DOS Header (64 bytes)
DOS Stub (variable size, padded to 0x80)
NT Headers (248 bytes for PE32+)
Section Headers (40 bytes × 3 sections)
Padding to file alignment (0x400)
.text Section (code)
- Machine code
- Padded to file alignment
.rdata Section (read-only data)
- String constants, resources
- Padded to file alignment
.idata Section (import data)
- Import descriptors
- Import lookup table
- Import address table
- Import by name structures
- Padded to file alignment
仮想アドレスレイアウト
0x1000: .text section (SECTION_ALIGNMENT)
0x2000: .rdata section
0x3000: .idata section
0x4000: Next available virtual address
定数とデフォルト値
- イメージベース: 0x140000000 (x64のデフォルト)
- セクションアラインメント: 0x1000 (4KB)
- ファイルアラインメント: 0x200 (512バイト)
- エントリポイント: 設定可能なRVA
- サブシステム: コンソールアプリケーション (IMAGE_SUBSYSTEM_WINDOWS_CUI)
使用例
; Create PE context
mov rcx, 0 ; Default image base
mov rdx, 1000h ; Entry point RVA
call PEWriter_CreateExecutable
mov rbx, rax ; Save context
; Add kernel32.dll imports
mov rcx, rbx
mov rdx, offset dll_kernel32
mov r8, offset func_GetStdHandle
call PEWriter_AddImport
; Add machine code
mov rcx, rbx
mov rdx, offset code_buffer
mov r8, code_size
call PEWriter_AddCode
; Write executable file
mov rcx, rbx
mov rdx, offset filename
call PEWriter_WriteFile
ビルド手順
- MASM64とWindows SDKがインストールされていることを確認する
build.batを実行してPEライターとサンプルをコンパイルする
PE_Writer_Example.exeを実行してhello.exeを生成する
- 生成された実行ファイルをテストする
エラーハンドリング
すべての関数は失敗時に0を、成功時に非ゼロを返します。実装には以下が含まれます:
- メモリ割り当て失敗チェック
- ファイルI/Oエラーハンドリング
- 入力検証
- 適切なリソースクリーンアップ
- バッファの境界チェック
制限事項
- 最大99インポート (MAX_IMPORTS - 1)
- 最大64KBコードサイズ (MAX_CODE_SIZE)
- 3つの固定セクション (.text, .rdata, .idata)
- コンソールサブシステムのみ
- リロケーションサポートなし
- デジタル署名なし
高度な機能
実装は以下のための確固たる基盤を提供します:
- カスタムセクション作成
- 複雑なインポートバインディング
- リソース埋め込み
- デジタル署名
- リロケーションサポート
- 例外処理テーブル
技術メモ
- 純粋なx64 MASMアセンブリ - CRT依存なし
- メモリ管理にWindowsヒープを使用
- x64用のPE32+形式を生成
- Windows Vista以降と互換性あり
- Microsoft PE仕様に準拠
- kernel32.dll以外の外部ライブラリ依存なし
この実装は、コード生成バックエンド、カスタムコンパイラ、実行可能パッカーに適した、完全でプロダクション対応のPE32+ライターを提供します。