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で動作検証したよん。

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です