Windowsの実行ファイル形式(3)

面倒なことが嫌いな私にとって、毎日blogを書くのは意外と大変だったりします。

さらに今日は22時からF1だったのでそちらをみようと早めに更新です。

さて、今回はIMAGE_NT_HEADERSIMAGE_OPTIONAL_HEADERです。

ものすごいたくさんのメンバがあるのでその中でも必要なものだけです。

この部分はちゃんと32bitと64bitで分かれているのでいくつか注意が必要です。

  • Magic

このヘッダの種別を示します。IMAGE_NT_OPTIONAL_HDR32_MAGICだと32bit用、IMAGE_NT_OPTIONAL_HDR64_MAGICだと64bit用になります。

通常はIMAGE_NT_OPTIONAL_HDR_MAGICを使っていればコンパイル時に分岐してくれるはずですが、手動で定めた方がいいときはそのどちらかを使います。

  • MajorLinkerVersion,MinorLinkerVersion

このヘッダを作った実行ファイルのリンカのバージョンです。VC2003なら7.1、VC2005なら8.0となります。

VisualStudio以外で作られたものでも、これ相当として表記するか、独自で定めるかはそれぞれで決められます。

ま、もちろんごまかしもきく値なので完全には信頼できないと思います。

  • SizeOfCode,SizeOfInitializedData,SizeOfUninitializedData

セクション内でそのデータとして確保されているデータの総バイト数を示します。

SizeOfCode コード領域(実行用の機械語の領域)
SizeOfInitializedData 初期化済みデータ(固定文字列やstatic変数などのメモリ領域)
SizeOfUninitializedData 初期化されていないデータ(仮想メモリ確保用)

実行ファイルの自己圧縮などであらかじめ実行ファイルメモリとして仮想メモリを確保するタイプのものはSizeOfUninitializedDataが0でなくなります。

  • AddressOfEntryPoint

このプログラムの「ロードされた後でもっともはじめに実行される」コードのアドレスを示します。プログラムのロードされた先頭メモリからの相対アドレスです。

ちなみに、このアドレスがWinMainのアドレスではありません。WinMainがロードされる前後の処理(CRTの初期化など)があるためです。

よくOllyDbgで「コードメモリ外にエントリポイントがある」という表示がありますが、それはこのアドレスが「コード領域」となるべき場所にないことを言っています。

  • BaseOfCode,BaseOfData

コード領域の開始アドレスとデータ領域の開始アドレスを示します。

64bit側にはBaseOfDataはありません。ちょっとびっくりです。

  • ImageBase

実行ファイルがロードされる時の仮想メモリの「要求する先頭アドレス」を示します。先頭アドレスなので64bitでは64bit値になります。

EXEの場合、ほとんどの場合実行ファイルでのGetModuleHandle(NULL)の戻り値と同じになります。

DLLの場合、一応予約アドレスはありますが、衝突することもあるので必ずこのアドレスになるとは限りません。衝突した場合は移動します。

32bitの場合、EXEなら0x00400000、DLLなら0x10000000がデフォルト値です。それ以外の値を設定することもあります。

コードの中にはこのアドレスをあてにして機械語になっているやつもいますので機械語ごと取り込んで移すとアドレスがあわなくなりますので、ぶっこぬき時にはちょっと注意です。

  • SectionAlignment

メモリにロードされた後の各セクションのアライメント値を示します。

仮想メモリ上では必ずこの数の倍数となる位置で切りそろえられます。

  • FileAlignment

ファイル上での各セクションのアライメント値を示します。

ファイル上ではこの値の倍数でデータが切りそろえられています。

  • MajorOperatingSystemVersion,MinorOperatingSystemVersion

実行可能な最低のWindowsOSのバージョンを示します。たとえば、5.1になっていると、Win2000では実行できない(ロードした段階で実行不可能といってくる)実行ファイルになります。

  • MajorImageVersion,MinorImageVersion

イメージのバージョンを示します。リンカに指示を与えると適当に設定できます。無くてもいい上にファイルリソースとしてつけることのできるファイルバージョンともまた違います。

だいたいのプログラムでは設定されていなかったりします。それだけあまり意味のない数字です。

  • MajorSubsystemVersion,MinorSubsystemVersion

MajorOperatingSystemVersion,MinorOperatingSystemVersionの親戚です。・・・ひどい解説・・・

  • SizeOfImage

実行ファイル全体のイメージサイズを示します。ロードした後にこの実行ファイルで使用する仮想メモリの総サイズです。

なぜか64bitのイメージでも32bit値です。前回にもいったとおり、この形式だと2^32byte以上の実行ファイルは作れないわけです。

  • SizeOfHeaders

ファイル中のヘッダ領域のサイズを示します。その部分までをローダーが先読みするという意味です。

  • CheckSum

実行ファイルの全データチェックサムを示します。実行ファイルの後ろにデータを結合するとこの値も一緒に変更しないと誤りになります。

VC2005以降だと設定しなくても勝手に計算されるようになっているようです。間違っていてもドライバファイルとかシステムファイルでもない限りエラーとならないので

あまり気にしなくてもいいですが、チェックツールでみると「間違っている」といわれるので気分はよくありません。0のときは無効という意味です。

  • DataDirectory

実行ファイルに必要なデータ情報のアドレス情報です。これは次回以降に説明します。

・・・ま、この辺は基礎中の基礎なので説明するまでもないのかもしれませんが・・・。


コメントを残す

メールアドレスが公開されることはありません。

*

この記事のトラックバック用URL