分かりやす〜い
コンピュータ技術情報

TOPに戻る
▼Processor
バッファオーバーフロー
┣ 異常な動作
┣ 本当に怖い事
┣ プログラムを作る
┣ バッファオーバーフロ
┃ ーを発生させる

┣ スタック領域の構成
┣ 何故強制終了されるの
┃ か?

┣ 強制終了されないよう
┃ に作り変える

┣ 任意のコードを実行す
┃ る

┣ of1.cとof2.cとの違い
┣ 例外
┣ 例外ハンドラの行う事
┣ of3.cを作る
┣ of1.cとof3.cとの違い
┣ of3.exeの例外ハンド
┃ ラ

┣ of3.exeを強制終了す
┃ るのは?

┣ 例外ハンドラの特徴
┣ Blue Screen
┣ BufferOverFlow応用
┃ プログラム

┗ 機械語の説明

Copyright(C) 2001-2002.ugpop. All rights reserved.




■デジタル用語辞典:
■ of3.cを作る ■

前回は例外発生時に何が行われるのかを説明しました。
例外が発生すると、例外ハンドラはスタック領域から「メッセ
ージを表示するプログラムの場所」情報を取得し、指定された
場所へ制御を移行させるのでした。

以下に例外ハンドラが「メッセージを表示するプログラムの場
所」へ制御を移行しているイメージを示します。


┌──────────────────────────┐
│         OF1.EXE          │
│                          │
└───┬──────────────────────┘
    │                       スタック領域
    │call命令               格納 ┌──────┐
    ├─────────────────────→│ 呼出し元 │
    │    制御を移行┌────────┐   └──────┘
    ├────────→│ main関数 │
    │         │        │
    │         └───┬────┘
    │             │
               ┌──┴──┐
               │コピー処理│
               └──┬──┘
                  │×バッファオーバーフロー発生
                  │         スタック領域
                  │        ┌──────┐
                  ├───────→│1F 1E 1D 1C │
                  │        └──────┘
                  │処理終了     スタック領域
                  │どこへ戻るか参照┌──────┐
                  │←───────┤1F 1E 1D 1C │
                  │        └──────┘
               ×××××××
               ×そんな所に×
               ×実行可能な×
               ×プログラム×
               ×ありません×
               ×××××××
                  │
            ┌─────┘★例外発生
            │
            ↓
      ┌──────────┐
      │          │
      │例外ハンドラ動作開始│
      │          │
      └─────┬────┘          スタック領域
            │何を起動するか参照     ┌──────┐
            │←─────────────┤メッセージを│
            ↓              │表示するプロ│
      ┌──────────┐         │グラムの場所│
      │          │         └──────┘
      │メッセージを表示する│
      │プログラム起動   │
      │          │
      └──────────┘


上のイメージで、1番右下にある「メッセージを表示するプロ
グラムの場所」情報ですが、バッファオーバーフローのバグに
より壊してしまう事が出来ます。

今回は「メッセージを表示するプログラムの場所」情報を意図
的に書き換えてしまうプログラムを作成し、どの様に動作する
のか、実際に確認してみましょう。


早速ですが、今回も以前に作成したプログラム"of1.c"を流用
してしまいます。

まずは"of1.c"をコピー&貼り付けして新しく出来たファイル
を"of3.c"という名前に変更してください。

今回はこの"of3.c"に変更を加えていきます。

まず"of1.c"がどういうプログラムだったか、思い出しておき
ましょう。

以下に"of1.c"のソースコードを示します。


─↓"of1.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,
          };
  unsigned char a[]= { 0x0, 0x1, 0x2, 0x3,
             0x4, 0x5, 0x6, 0x7,
          };

  // スタック領域を表示する。
  for(i=&b[0];i<=&a[15];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[15];i+=4)
  {
    printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
  }
}
─↑"of1.c"ここまで──────────────────


"of1.c"というプログラムはバッファオーバーフローにより、
スタック領域上にある「呼出し元」の情報を書き換えてしまう
プログラムでした。

このプログラムにより「呼出し元」の情報は「1F 1E 1D 1C」
という値に書き換えられてしまい、「呼出し元」に制御を移行
させようとした時点で例外が発生し、強制終了されてしまいま
す。

このプログラムの動作イメージは1番上に示した通りです。


このプログラムを流用して"of3.c"では以下の様に変更を加え
ます。

変更部分にはコメントを付けておきます。


─↓"of3.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,
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
// ●↑ここまで追加
          };
  unsigned char a[]= { 0x0, 0x1, 0x2, 0x3,
             0x4, 0x5, 0x6, 0x7,
          };

  // スタック領域を表示する。
// ●変更↓スタック領域表示範囲変更
  for(i=&b[0];i<=&a[63];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[63];i+=4)
  {
    printf("%08X:%02X %02X %02X %02X\n", i, *i, *(i+1), *(i+2), *(i+3));
  }
}
─↑"of3.c"ここまで──────────────────


たった3箇所変更しただけです。
拍子抜けした方もいらっしゃるかもしれませんが、これだけの
変更で「メッセージを表示するプログラムの場所」情報を書き
換えてしまう事が出来ます。

まず初めに

// ●↓ここから追加
             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,
             0xff, 0xff, 0xff, 0xff,
// ●↑ここまで追加


というのがありますが、これはバッファbの大きさを変更した
だけです。
これにより、バッファオーバーフローが発生した時の「被害が
拡大」し、「メッセージを表示するプログラムの場所」情報が
書き換わってしまう事になります。


後の2箇所は全く同じ変更を行っています。

●プログラム変更前

// ●変更↓スタック領域表示範囲変更
  for(i=&b[0];i<=&a[15];i+=4)
            ̄

●プログラム変更後

// ●変更↓スタック領域表示範囲変更
  for(i=&b[0];i<=&a[63];i+=4)
            ̄
           ↑
       ここを変更しただけ


これはバッファbの大きさを大きくしたので、表示するスタッ
ク領域の範囲も大きくしただけです。


この変更によりバッファaのずっと下の方までスタック領域が
表示されるようになります。

それではこのプログラムをビルドしてみましょう。

この講座ではC言語のコンパイルにDigital Mars社製のコンパ
イラを使用しています。

Visual C++をお持ちの方が多くいらっしゃると思いますが、こ
のコンパイラはスタック領域を自動的に並び替えてしまう、と
いうわけの分からない機能がある為、今回の講座では使用して
いません。

スタック領域が並び替えられてしまっても混乱しないという自
信がある方は使用しても構わないと思いますが、そうでない方
はこの講座を分かりやすくする為にもDigital Mars社製コンパ
イラを使用する事をお勧め致します。

このコンパイラのインストールと環境設定方法はこちらをご覧
ください。

下の方にスクロールすると説明があります。
>>> academy002-039.htm


それではビルドしましょう。

sc of3.c -j


これでビルドが行われ、"of3.exe"という実行形式ファイルが
出来上がります。

さて、このプログラムを実行すると、"of1.exe"よりも沢山の
スタック領域の表示が行われて、やはり強制終了されてしまう
と思います。

なんだ、つまらない、とお思いの方もいらっしゃるかと思いま
すが、"of1.exe"と"of3.exe"との「強制終了のされ方」には、
微妙な違いがあります。

どんな違いでしょうか?

分からない、という方は何回か"of1.exe"と"of3.exe"を実行し
てみると微妙な違いに気が付くかもしれません。
(強制終了されるまでのタイミングを計ってみると良いかもし
れません。)

次回は、"of1.exe"と"of3.exe"のプログラムの動作の仕方にど
んな違いがあるのか説明し、具体的な動作イメージを見てみる
予定です。



▲このページの上へ

▲このページの上へ

←前に戻る    ▲このページの上へ    続きを読む→

▲このページの上へ