314バイトのWindowsのデジタルレイン

最近のトピックに対するコメントで、「Hello、World!」というコンソールに出力されるWindows EXEをどれだけ大きく絞ることができるかという議論が生じました。 回答:268バイト、 Windowsは小さなファイルの読み込みを拒否します。



「Hello World!」の場合、可能な限り縮小の限界に既に達しているので、少なくとももっと面白いことをするプログラムをどの程度縮小できるのだろうと思いました。



最初は、その結果を誇っています。私のプログラムは、理論上の最小値よりもわずか46バイト大きいだけです。







base64
  TVprZXJuZWwzMgAAUEUAAEwBAQC4AwABAPdlEIlFEMN4AA8BCwEFDL0UEEAAjXyNAFfraD
 gQAAAzyesoDAAAAAAAQAAAEAAAAAIAAAAAAAAACAgoCBAAAAAAAAAAAAQAAAAIAALFQ68AD
 AAAAEgEAAAAAAABQABkAABAAAFAAGQADAAAAAAAAAAAAAAAAAoEQAAKAAAAAAAAAAAAAAAAA / 9
 Wr4vvrEQAAMAAAABAAADkBAAABAAAAi / df6wMAAAAzybFQV4sHgPwZdygPttyNHJvB4waN
 HItQweAYwegei0RFOIhEMwKIpDPC / v /// 9WIJDNY / sSA / GR8Av / Vq + LFjUVcUFH / dWhWZI
 tBMItAEP9wHP9VWOuiV3JpdGVDb25zb2xlT3V0cHV0QQBsEAAAAAAAAAAAAAAAAAAAAAbBA = 


(これらの314バイトをホストするボランティアがいる場合、ここにリンクを追加します。)








以前の愛好家は、Win2000とWinXPの最小プログラムが133バイトかかることを発見しました。 Windows x64の最小の32ビットプログラムは268バイトです。 最後の制限は、Windows x64ブートローダーにハードコードされていますIMAGE_NT_HEADERS64



ヘッダーの先頭からファイルの末尾までがIMAGE_NT_HEADERS64



= 0x108バイト未満の場合、Windowsはファイルのダウンロードを拒否します。 PEヘッダーはオフセット4よりも先に開始できないため、( 可能な限り最小の )268バイト未満を占めるプログラムのコンテンツは、最小サイズまでゼロにする必要があります。



268バイトプログラムの既存の例には1つのセクションが含まれておらず、実際には、Windowsが1ページのメモリ(4KB)を割り当てるPEヘッダー内に完全に配置されています。 ただし、「デジタルレイン」の場合、スクリーンバッファー(80列×25行×1文字あたり4バイト= 8000バイト)を保存する必要があるため、プログラムのセクションなしで行うことはできません。 これはそれほど無駄ではありません。セクションヘッダーは0x28バイトのみで、そのうち半分以上は使用されていないため、コードで使用できます。 実際、私のプログラムのセクションの「内部」は、その見出しの後、実行可能コードの一部、インポートされる関数の名前、およびインポートテーブルの一部です(そのバイトの最後の0x16はゼロであり、ファイルに保存されません)。 インポートテーブルと操作中の次の8 KBのメモリは、データ(状態配列と画面バッファー)を格納するために使用されます。 すべての初期化されたデータ、サービス情報の一部(インポートチェーンとライブラリ名)、およびコードの一部はヘッダーに固定されます。 「2回使用」フィールドは上記のプレゼンテーションで署名されています。データはMajorOperatingSystemVersion, MinorOperatingSystemVersion, MajorImageVersion, MinorImageVersion, SizeOfStackCommit, SizeOfHeapReserve



LoaderFlags



にあり、コードはSizeOfCode, SizeOfInitializedData, SizeOfUninitializedData, BaseOfCode, CheckSum



PointerToRelocations, PointerToLinenumbers, NumberOfRelocations, NumberOfLinenumbers



およびCharacteristics



のヘッダー。 Characteristics



フィールド(セクションフラグ)の場合、MSBを設定するだけで十分です( IMAGE_SCN_MEM_WRITE



)。 他のいくつかのフィールドの値にも制限が課されます。たとえば、 SizeOfStackCommit



SizeOfHeapReserve



をメモリに配置する必要があります。 システムによるPointerToLinenumbers



フィールドの値の誤解は、デバッグ情報のテーブルのサイズと見なされます。値がメモリ内のプログラムのサイズ(0x4000)よりも大きい場合、プログラムはロード時にクラッシュします。



以前の「最小」プログラムでは、 FileAlignment



= 4およびSectionAlignment



= 4が使用されていました。 Windows x64のセクションのないファイルでは、これにより許可されます。 ただし、少なくとも1つのセクションが宣言されている場合、 FileAlignment



は少なくとも0x200、 SectionAlignment



は0x1000でなければなりません。 したがって、セクションが存在するサイズが268バイトのプログラムを作成することはできませんe_lfanew



= 4とSectionAlignment



オーバーラップは許可されません。 ImageBase



は0x1000の倍数でなければならないため、PEヘッダーを4バイトシフトするのはわずかです。 セクションを含むプログラムの最小サイズは276バイトであり、 e_lfanew



= e_lfanew



e_lfanew



が重複しています。 つまり、私のプログラムは、4KBを超えるメモリを使用する可能性のある最小サイズよりも38バイト大きくなります。



Win7およびWin2008でプログラムのパフォーマンスをテストしました。 残念ながら、私のプログラムはWinXPで動作しません( 編集:動作しますが、しばらくすると)-ディレクトリに0xDエントリ未満のプログラムをロードすることを拒否します。 プログラム「Hello、World!」ですべてのコードが0x10バイトを使用し、WinXPとの互換性のために0x50ファイルに0バイトを入力することを残念に思わない場合、プログラムをサイズの4分の1に増やすのは残念でした。 ビンテージOSを愛するすべての人に謝罪します。



All Articles