バイナリ列の解答/解説(第3回)

というわけで第3回です。
自力で(ry

では続きを。

埋まっているもの

spcamp.bmpを開いても特にわからないのでバイナリエディタで見てみましょう。

00000000  42 4d 4e 48 00 00 00 00  00 00 3e 1c 00 00 28 00  |BMNH......>...(.|
00000010  00 00 78 02 00 00 8d 00  00 00 01 00 01 00 00 00  |..x.............|
00000020  00 00 10 2c 00 00 00 00  00 00 00 00 00 00 00 00  |...,............|
00000030  00 00 00 00 00 00 00 00  00 00 ff ff ff 00 4d 5a  |..............MZ|
00000040  90 00 03 00 00 00 04 00  00 00 ff ff 00 00 b8 00  |................|
00000050  00 00 00 00 00 00 40 00  00 00 00 00 00 00 00 00  |......@.........|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 e8 00 00 00 0e 1f  |................|
00000080  ba 0e 00 b4 09 cd 21 eb  5e 90 90 90 54 68 69 73  |......!.^...This|
00000090  20 70 72 6f 67 72 61 6d  20 63 61 6e 6e 6f 74 20  | program cannot |
000000a0  62 65 20 72 75 6e 20 69  6e 20 44 4f 53 20 6d 6f  |be run in DOS mo|
000000b0  64 65 2e 0d 0d 0a 24 b3  dc b9 bd f7 31 9a aa df  |de....$.....1...|
000000c0  38 c4 df cb f1 f0 14 e7  ba 41 0e 59 dd 0d 0d 0a  |8........A.Y....|
000000d0  24 c0 ac da dc 9a 41 c5  98 ef 09 f4 80 fa c7 84  |$.....A.........|
000000e0  7c b8 dc 2d 61 36 af b9  16 00 bb 39 00 be 53 00  ||..-a6.....9..S.|
000000f0  8a 24 2e 30 27 46 43 e2  f7 ba 39 00 b4 09 cd 21  |.$.0'FC...9....!|
00000100  b8 01 4c cd 21 00 00 00  00 00 00 00 00 00 00 00  |..L.!...........|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 50 45  00 00 4c 01 05 00 e3 2d  |......PE..L....-|
00000130  76 4c 00 00 00 00 00 00  00 00 e0 00 02 01 0b 01  |vL..............|
(以下省略)

するとなにやら見慣れたものが見えませんか?

00000030  00 00 00 00 00 00 00 00  00 00 ff ff ff 00 4d 5a  |..............MZ|
00000040  90 00 03 00 00 00 04 00  00 00 ff ff 00 00 b8 00  |................|
00000050  00 00 00 00 00 00 40 00  00 00 00 00 00 00 00 00  |......@.........|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 e8 00 00 00 0e 1f  |................|
00000080  ba 0e 00 b4 09 cd 21 eb  5e 90 90 90 54 68 69 73  |......!.^...This|
00000090  20 70 72 6f 67 72 61 6d  20 63 61 6e 6e 6f 74 20  | program cannot |
000000a0  62 65 20 72 75 6e 20 69  6e 20 44 4f 53 20 6d 6f  |be run in DOS mo|
000000b0  64 65 2e 0d 0d 0a 24 b3  dc b9 bd f7 31 9a aa df  |de....$.....1...|
000000c0  38 c4 df cb f1 f0 14 e7  ba 41 0e 59 dd 0d 0d 0a  |8........A.Y....|
000000d0  24 c0 ac da dc 9a 41 c5  98 ef 09 f4 80 fa c7 84  |$.....A.........|
000000e0  7c b8 dc 2d 61 36 af b9  16 00 bb 39 00 be 53 00  ||..-a6.....9..S.|
000000f0  8a 24 2e 30 27 46 43 e2  f7 ba 39 00 b4 09 cd 21  |.$.0'FC...9....!|
00000100  b8 01 4c cd 21 00 00 00  00 00 00 00 00 00 00 00  |..L.!...........|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 50 45  00 00 4c 01 05 00 e3 2d  |......PE..L....-|

これ、PEファイルですね。
つまりビットマップ画像にPEファイルが埋め込まれてるっぽいことがわかります。

ビットマップファイルフォーマット

ビットマップファイルフォーマットは以下のようになっています。

まず最初にBITMAPFILEHEADER構造体が埋まっています。
BITMAPFILEHEADER構造体は以下のように定義されています。

typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

http://msdn.microsoft.com/en-us/library/dd183374%28VS.85%29.aspx

ここでbfOffBitsは実際の画像データが存在するオフセット値となっています。
先程のデータでオフセット値を確認すると、

00000000  42 4d 4e 48 00 00 00 00  00 00 3e 1c 00 00 28 00  |BMNH......>...(.|

ここの部分ですね。
つまりオフセット値は0x00001C3Eとなっています。
(リトルエンディアンであることに注意!)
逆に言うとそれまでの部分に何か埋め込まれてることがわかります。

取り出し

とりあえず取り出すだけなら"MZ"から始まる部分から0x00001C3Dまで取り出せばいいことになります。
これを保存して実行してみると、

spcamp!

と表示されました。
が、これを最初のspcamp/text.txtに入力しても解凍できません。
ということでまだまだ解いていきます。
今回はここまでです。

補足

ビットマップのファイルフォーマットを簡単に書いておきます。
ビットマップはいろいろな形式があるので詳細は自身で調べてください。

BITMAPFILEHEADERのあとにはBITMAPINFOHEADERが続きます。
これは以下の構造をしています。

typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

http://msdn.microsoft.com/ja-jp/library/cc352308.aspx

ここで今回はbiBitCount=1、つまり1ピクセルあたり1ビットを使うためこの構造体のあとには2^biBitCountの数だけカラーテーブルが置かれます。
カラーテーブルの中身はRGBQUADであり、

typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;

http://msdn.microsoft.com/en-us/library/dd162938%28VS.85%29.aspx

となっています。
つまり今回のビットマップ画像でビットマップのデータとして扱われないのは0x0000003Fからで、これはちょうど"MZ"の部分にあたります。


このようにビットマップ画像にはビットマップ画像として有効でありながら別のデータを埋め込めたりします。
今回はこれを利用してPEファイルの埋め込みを行ないました。

あとがき

今回はバイナリエディタで開いたときにPEファイルの特徴的なものが見えたため多分気づかれた方は多いのではないでしょうか。
もう少しここで苦労するかなぁ〜と思ってたのですが少し甘かったですねw
次回はこのEXEをどうにかします。
ということで今回はここまで!