msiファイルとは

Windowsで使用されるインストールパッケージのファイル形式、Microsoft Installerというプログラムの元の名前に由来。プログラムのインストール、保存、削除に使用される

EXEファイルのセクション

セクションにはデータサイズ、RVAなどが保存される
L ネイティブコード、リソース情報、デバッグ情報など
L 読み込み専用領域、再配置情報、インポート関数、エクスポート関数など

なるほど、ソースコードだけでなく、ソフトウェア一式ってイメージだな

typedef struct _IMAGE_SECTION_HEADER {
	BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
	union {
		DWORD PhysicalAddress:
		DWORD VirtualSize;
	}
	DWORD VirtualAddress; // セクションサイズ
	DWORD SizeOfRawData; // セクション位置
	DWORD PointerToRawData;
	DWORD PointerToRelocations; //再配置エントリ情報
	DWORD PointerToLinenumbers; //行番号
	WORD NumberOfRelocations; //再配置エントリ
	WORD NumberOfLinenumbers;
	DWORD Characteristics; // セクション特性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADERS;

Nameはセクション名
.text, .data, .idata, .edata, .rsrc, .debug, .reloc, .tls

.text, .data, .rsrcなどの各セクションはIMAGE_SECTION_HEADER構造体の後に配置。やっとか。

インポートは外部DLLと動作リンクを行う
リソースセクション(.rsrc)では、実行に直接関係ない特徴的なデータを管理
 L データ型、ID、言語

結構気の遠くなるようなことやってるなー
あれ、でもメモリのポインタってC言語だとソースの中で指定するはずだけど、PointerToRawDataでIMAGE_SECTION_HEADER構造体で指定している?
それと、ネイティブコードのセクションは構造化されるのだろうか?それとも、1つのセクションに纏められるのだろうか?データ処理で考えると、.textセクション、.dataセクション、.rsrcセクションなど各セクション内部で構造化された方が効率的に見えるが。。
ああああ、メモリかー

EXEファイルのPEヘッダ

IMAGE_NT_HEADERS32に定義

typedef struct _IMAGE_NT_HEADERS {
	DWORD Signature;
	IMAGE_FILE_HEADER FileHeader;
	IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADER32, *PIMAGE_NT_HEADERS32;

PE headerにもSignature
4byte? 32bitOSを意志的している

IMAGE_FILE_HEADER構造体

typedef struct _IMAGE_FILE_HEADERS {
	WORD Machine;
	WORD NumberOfSections;
	DWORD TimeDataStamp;
	DWORD PointerToSymbols;
	DWORD NumberOfSymbols;
	WORD SizeOfOptionalHeader;
	WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_NT_HEADERS;

Machineはそれぞれフラグがあう
unknown:0x0 あらゆるマシンタイプ
I386:0x14c Intel386以降
R3000: 0x162
R4000: 0x166 MIPS(r)リトルエンディアン
R10000: 0x168
….

NumberOfSections: 保持するセクション数
TimeDataStamp: 作成された日時
PointerToSymbols, NumberOfSymbols:シンボルテーブルの位置、数
SizeOfOptionalHeader: 構造体サイズ保持
Characteristics:ファイズ属性値
 IMAGE_FILE_EXECUTABLE: 0x0002
IMAGE_FILE_LINE_NUMS_STRIPPED: 0x0004

IMAGE_OPTIONAL_HEADER32構造体も同様に定義される
 Magic,MajorLinkerVersion, SizeOfCode, SizeOfInitializedData,
SizeOfInitializedData, SizeOfUnitializedData,AddressOfEntryPoint, BaseifCode, BaseOfData, ImageBase, …

IMAGE_DATA_DIRECTORY構造体はRVA, Size

PE Headerにはターゲットマシン、アライメント情報、セクション情報、メモリサイズ情報などが格納されており、OSがメモリにロードして実行する際に書き込まれる

OS側では書き込まれた内容を元にメモリで実行する
ツールを使用すればコンパイル時に自動生成される
第一印象項目が多いなと思ったが、exeファイルの共有フォーマットと考えると妥当か

EXEファイルの内部構造

Windowsの実行ファイルEXEファイルは、通常Visual C++, Visual Basic, Delphiなどのコンパイラが自動生成する
L ほとんどがデータサイズ、ファイル、メモリを指し示すオフセット値で構成されている

MS DOSはマイクロソフトが開発したパソコン用OS
sublimeで開くとバイナリコードでどのように書かれているかわかりません。
 L x86に対応する機械語。アセンブラではない。

MZシグネチャはEXEファイルを裏付けるデータ

EXEファイルが動くマシン
– Intel 386以降(Windows)
– MIPS(r)
– Alpha AXP(tm)
– Motorola 68000
– Power PC
– 日立SH3, SH4

リソース箇所にデータを格納する

PEヘッダ(Portable Executable)
EXEファイルの先頭部分の情報

EXEファイルのロード方法
MicrosoftのOSが、MZシグネチャ、マシンタイプ、ネイティブコードなどの情報をもとにEXEファイルをメモリ上にロードして実行する
1. シグネチャ、マシンタイプを確認
2. EXEイメージをメモリ上にコピー
3. PEヘッダ記載データを元にEXEイメージの初期化
4. PEヘッダで指定されたスタートポイントからプログラム実行
なるほど、ディスクに保存したexeファイルをメモリ上に読み込んで、1行ずつ処理していくのね。

EXEファイルイメージは実行前にプロセスメモリの任意の場所にロードされる。メモリの先頭位置をイメージベースという。
RVA(Relative Virtual Address)とはイメージベースからの相対オフセット値
ファイルポインタで読み込み対象となるデータ位置を指定し、RVAでプロセスメモリ上のデータを指し示す

イメージベース + RVA = データアドレス

EXEファイル先頭
IMAGE_DOS_HEADER …MS-DOSで認識可能なデータフォーマット
MS-DOS用スタブ …ネイティブコードを保存できるスペース
NULL空間 … PEヘッダの先頭位置は8バイト境界
PEヘッダ

なるほど、*.exeと*.pkgではソースコードは一緒だけど単純に拡張子だけ異なるって訳ではないのね。当たり前か。
EXEファイルがMS-DOS用のヘッダやデータフォーマットということは、一つのソフトでもOSが変われば当然、ファイルの中身が違うってことですな。