WINDOWSのGUIで最小のHello Worldを作ってみる
ネット上で面白いテーマを発見。
はてな 組み込み日記 ■[Windows]Hello, world!
はてな 趣味的にっき ■Hello, world!といえば…
OSASKプロジェクト
メッセージが「Hello,world!」(12バイト)
GUIでMessageBoxを使用。
という条件で作成してみることに。
まず、小手調べにアセンブラ。
22バイトですね。
0100 B409 MOV AH,09 0102 BA0801 MOV DX,0108 0105 CD21 INT 21 0107 C3 RET 0108 48 65 6C 6C 6F DB 'Hello World!',13,'$' 20 57 6F 72 6C 64 21 0D 24 |
取り敢えず、Cで普通にソフトを組んでみました。
#include "stdafx.h" char msg[]="Hello,World!"; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow ) { MessageBoxA(0,msg,msg,0); } |
コンパイラオプションは
cl -GF -O1 /c miniexe.cpp /nologo /Fominiexe.obj
link /section:.data,RW /nologo /merge:.rdata=.data /merge:.text=.data
/subsystem:windows /incremental:no /machine:I386 /out:miniexe.exe
/OPT:NOWIN98 miniexe.obj user32.lib
結果。
2008/02/15 00:28 27,136 miniexe.exe
う~ん、予想通り大きい。
次にスタブを用意して、M$シグネチャをストリップしてみました。
スタブはこんな感じ。
4D 5A 40 00 01 00 00 00 01 00 00 00 FF FF 00 00 MZ@ 00 00 00 00 08 00 00 00 0E 1F BA 15 00 B4 09 CD 21 B4 4C CD 21 57 69 6E 33 32 41 50 0D 0A 24 C3 ! L !Win32AP $ 48 65 6C 6C 6F 2C 57 6F 72 6C 64 21 00 00 00 00 Hello,World! |
コンパイラオプションにNOWIN98ではなく -ALIGN:16を指定してみることにしてデフォルトライブラリを無効にしてアセンブラ化してみます。
#include "stdafx.h" __declspec(naked) void APIENTRY WinMainCRT() { __asm{ push eax //eax=0 mov edx,0x00400030 push edx push edx push eax call DWORD ptr[MessageBoxA] ret 10h } } |
コンパイラオプションがちょっと長くなって、
link /section:.data,RW /nologo /merge:.rdata=.data /merge:.text=.data
/subsystem:windows /incremental:no /machine:I386 /nodefaultlib
/out:miniexe.exe /entry:"WinMainCRT" /align:16 miniexe.obj user32.lib
/stub:mini.exe
2008/02/15 00:44 464 miniexe.exe
いきなり、512バイトの壁を突破。
ここからは手動でバイナリをいじることに。
取り敢えずサイトを参考にしました。EXEヘッダ
4D 5A 40 00 01 00 00 00 01 00 00 00 FF FF 00 00 00 00 00 00 08 00 00 00 50 45 00 00 4C 01 01 00 FF FF FF FF FF FF FF FF FF FF FF FF 08 01 0F 01 0B 01 FF FF FF FF FF FF FF FF FF FF 18 00 00 00 68 01 00 00 60 01 00 00 FF FF FF FF 00 00 40 00 10 00 00 00 10 00 00 00 FF FF FF FF FF FF FF FF 04 00 FF FF FF FF FF 7F C4 01 00 00 C0 00 00 00 FF FF FF FF 02 00 00 00 FF FF FF 3F FF FF FF 3F FF FF FF 2F 00 10 00 00 FF FF FF FF 02 00 00 00 FF FF FF FF FF FF FF FF 7C 01 00 00 1C 00 00 00 0C 01 00 00 C0 00 00 00 10 01 00 00 C0 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 64 61 74 61 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 8C 00 00 00 40 01 00 00 90 00 00 00 80 01 00 00 FF FF FF FF FF FF FF FF 2E 64 61 74 61 FF FF FF 6C 00 00 00 60 01 00 00 70 00 00 00 60 01 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 33 C0 50 BA 30 00 40 00 52 52 50 FF 15 0C 00 40 00 C2 10 00 A4 01 00 00 00 00 00 00 00 00 00 00 BA 01 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AC 01 00 00 00 00 00 00 BE 01 4D 65 73 73 61 67 65 42 6F 78 41 00 55 53 45 52 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00 00 00 00 00 |
取り敢えず、PEヘッダは18Hに移動してきても大丈夫そうなのでこれで組んでみることに。
いじっても平気そうな場所をFFで塗りつぶします。
4D 5A 40 00 01 00 00 00 01 00 00 00 FF FF 00 00 00 00 00 00 8C 00 00 00 50 45 00 00 4C 01 01 00 4D 65 73 73 61 67 65 42 6F 78 41 00 70 00 0F 01 0B 01 BE 01 40 00 00 00 28 63 29 2E 18 00 00 00 58 00 00 00 E0 00 00 00 32 30 30 38 00 00 40 00 10 00 00 00 10 00 00 00 BA 88 00 40 00 33 C0 50 04 00 52 52 B2 0C EB 74 E8 00 00 00 C8 00 00 00 50 46 57 2F 02 00 00 00 75 73 65 72 33 32 2E 64 6C 6C 00 00 00 10 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 21 00 0D 0A 24 B8 00 00 00 0E 1F BA 78 00 B4 09 CD 21 EB 2D 00 1E 00 00 00 C8 00 00 00 20 00 00 00 C8 00 00 00 CC 00 00 00 00 00 00 00 00 00 00 00 78 00 00 00 0C 00 00 00 1E 00 00 00 00 00 00 00 B4 4C CD 21 00 00 00 00 50 FF 12 C2 10 00 00 00 42 57 43 2E 00 00 00 00 00 00 00 00 C8 00 00 00 28 00 |
取り敢えず、動かせる限界まで切り詰めてみました。
2008/02/15 01:49 246 miniexe_p1.exe
ネットで検索すると233バイトになったという記事を発見。
これ以上削るってことは、イメージディレクトリが削れるのかな?
DOSの処理を断念しよう。(この状態ではMS-DOSでもHello,World!が表示されるのです。)
というわけで、イメージディレクトリを削ってみます。
4D 5A 40 00 01 00 00 00 01 00 00 00 1E 00 00 00 00 00 00 00 08 00 00 00 50 45 00 00 4C 01 01 00 4D 65 73 73 61 67 65 42 6F 78 41 00 68 00 0F 01 0B 01 50 BA 58 00 40 00 52 52 EB 4C 18 00 00 00 32 00 00 00 C0 00 00 00 72 6C 64 21 00 00 40 00 10 00 00 00 10 00 00 00 48 65 6C 6C 6F 20 57 6F 04 00 00 00 00 0D 24 00 A5 00 00 00 1E 00 00 00 00 00 00 00 02 00 00 00 00 55 53 45 52 33 32 2E 44 4C 4C 00 0C 00 00 00 50 EB 25 90 02 00 00 00 79 00 00 00 0C 00 00 00 84 00 00 00 1C 00 00 00 68 00 00 00 30 00 00 00 70 00 00 00 30 00 00 00 8B 4A F0 89 4A 08 B2 0C FF 12 C2 10 00 |
調子に乗って削ってみました、
2008/02/15 3:05 189 miniexe_p2.exe
いかがなもんでしょう?
んで、ネットでこれ以上小さいのはないだろうと探してみたら、めっちゃ小さいHelloWorld
なるブログを発見。これは204バイト。
。。。しかし、PEヘッダがオフセット0chまで移動可能じゃあありませんか?!
そんなわけで、コードも最適化しつつ。。。
2008/02/16 00:06 157 miniexe_p3.exe
一応、2000とXPで動作検証したよん。
Comments