Weird Wired World

Programming, Security

PE形式のヘッダ

最近WindowsでのInjectionを色々と試している。本記事ではその過程で学んだPEのヘッダを取り上げる。

この手のデータ構造を網羅的に学ぶのは大変。まず数が多い。また先人の知恵が詰まっているためか解説読んでも意味の分からん(^^;)メンバもある。本記事では,Injectionを学ぶのに当たり必要になった範囲や粒度でまとめる。

ここで紹介されているもの以外のメンバや詳細を知りたい場合は,Microsoftの解説を参照されたい。

PE形式の全体像とヘッダ

f:id:enufranz:20171119180300p:plain:w400

通称「PE Header」について補足する。PE Headerは通常上図のNT Headerを指す。しかし「PEのヘッダ」という意味で,赤枠で囲んだMS-DOS Header~Section Headersまでを指す記事等が見られるため注意が必要。本記事では,PE Headerという言葉は用いず,MS-DOS Header, NT Headerと呼び分ける。

MS-DOS Header, Stub

Windows の前身である MS-DOSとの互換性をとるためのヘッダとスタブプログラム。

スタブプログラムでは,MS-DOSWindows 用のプログラムを実行した際の「This program cannot be run in DOS mode」の表示を行う。ここに任意のプログラムを配置することもできる。

_IMAGE_DOS_HEADER

メンバ名 説明
e_magic MS-DOS Headerであることを表す文字列「MZ」
e_flanew NTヘッダへのオフセットサイズ(バイト)

NT Header

Optional Header

_IMAGE_OPTIONAL_HEADER

メンバ名 説明
AddressOfEntryPoint エントリポイントのアドレス(RVA)
エントリポイントは多くの言語で言うmain関数のこと
RVA(relative virtual address)は後述のImageBaseからの相対アドレスであること
ImageBase イメージファイルがロードされるアドレス
既定値はDLLが0x10000000,実行ファイルは0x00400000
SizeOfImage 全てのヘッダを含む実行イメージののサイズ(Section Alignment)
SizeOfHeaders 全てのヘッダの合計サイズ(File Alignment)
全てのヘッダとはMS-DOSとStub,NT Header,全てのSection Header

Section Headers

このヘッダはセクションの数だけ,言い換えるとFile HeaderのNumberOfSectionsの数だけ配置される。

_IMAGE_SECTION_HEADER

メンバ名 説明
VirtualSize メモリ上でのセクションのサイズ
VirtualAddress メモリ上でのセクションのアドレス(RVA)
SizeOfRawData ディスク上でのセクションのサイズ(File Alignment)
PointerToRawData ディスク上でのセクションの位置(オフセット)

これらのメンバを使ってローダがセクションを配置する動作を簡単に考えてみる[*1]。 ローダはFile HeaderのNumberOfSectionsの数だけセクションの情報を見る。各セクションについて,見るべき範囲はPointerToRawDataの位置からSizeOfRawData分進んだ範囲である。これを(VirtualAddress + ImageBase)の位置にコピーすれば良い。