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

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

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

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

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

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

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

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

┗ 機械語の説明

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




■デジタル用語辞典:
■ Blue Screen ■

前回はWindowsの例外ハンドラの特徴について説明しました。

Windowsの例外ハンドラが「制御を移行」しようとした瞬間は、
「必ず」レジスタ「EBX」は「メッセージを表示するプログラ
ムの場所」情報の「4バイト手前」を指しているのでした。

以下に、前回示したイメージをもう1度示します。

                      ┌──────────────┐
                      │元々は「メッセージを表示する│
                      │プログラムの場所」情報だが、│
                      │バッファオーバーフローにより│
                      │書き換わっている。     │
   例外ハンドラが制御を移行しようとした └─────────────┬┘
   瞬間は必ずここを指している。         ┌───────┐ │
   ┏━━━━━━━━━━━━━━━━━━━━━→│ FF FF FF FF │ │
   ┃        ・             ├───────┤ │
   ┃        ・             │ FF FF FF FF │←┘
   ┃        ・             └──┬────┘
   ┃     ×××××××             │
   ┃     ×そんな所に×             │
   ┃     ×実行可能な×             │
   ┃     ×プログラム×             │
   ┃     ×ありません×             │
   ┃     ×××××××             │
   ┃        │★例外発生           │
   ┃  ┌─────┴────┐           │
   ┃  │          │           │
   ┃  │例外ハンドラ動作開始│           │
   ┃  │          │           │
   ┃  └─────┬────┘           │
   ┃        │何を起動するか参照       │
┌──┸──┐     │←───────────────┘
│     │制御を移行↓
└─────┘  ×××××××
レジスタEBX   ×そんな所に×
         ×実行可能な×
         ×プログラム×
         ×ありません×
         ×××××××
            │★例外発生


前回説明した、Windowsの例外ハンドラの特徴を知っていると、
どういう事が行えるのでしょうか?


まず、この特長には以下の2つの事が言えます。

1.例外ハンドラは「メッセージを表示するプログラムの場所」
  へ「制御を移行」する。

2.レジスタEBXは必ず「メッセージを表示するプログラムの
  場所」情報の4バイト手前を指している。


まず1番目の特徴を具体的に見てみましょう。

上のイメージで、「メッセージを表示するプログラムの場所」
情報は「FF FF FF FF」となっています。

                      ┌──────────────┐
                      │元々は「メッセージを表示する│
                      │プログラムの場所」情報だが、│
                      │バッファオーバーフローにより│
                      │書き換わっている。     │
                      └─────────────┬┘
                          ┌───────┐ │
                          │ FF FF FF FF │ │
                          ├───────┤ │
                          │ FF FF FF FF │←┘
                          └───────┘


この「FF FF FF FF」という値は、バッファオーバーフローを
利用する事によりどんな値にでも書き換える事が出来ます。

ここで、例えば「FF FF FF FF」という「実行不可能」な命令
のある場所を指定するのではなく、何かしら実行可能な命令の
ある場所を指定するとどうなるでしょうか?

インテルプロセッサは、素直に指定された場所の命令を実行し
てしまいます。

ここまでは良いでしょうか?

1番目の特徴を言い換えると、どこへでも自由に制御を移行す
る事が出来る、という事です。

この時、もう1つの特徴を利用します。

2.レジスタEBXは必ず「メッセージを表示するプログラムの
  場所」情報の4バイト手前を指している。

2番目の特徴を言い換えると、「レジスタEBXはバッファオー
バーフローにより自由に書き換え可能な場所を示している」と
いう事です。

この1番目と2番目の特徴を組合わせると、以下の事が行えま
す。

「バッファオーバーフローにより自由に書き換え可能な場所へ
制御を移行する事が出来る。」

つまり、バッファオーバーフローにより自由に書き換え可能な
場所にコンピュータウィルスのコードを書き込んでおけば、そ
こに制御を移行させ任意のコードを実行する事が出来るという
わけです。


それでは、より具体的に見てみましょう。

1項の「コンピュータウィルス製作者は自分の意図した場所の
どこへでも自由に制御を移行する事が出来る。」という特徴を
利用して、OS内部へ制御を移行させます。

この時、OS内部の「call ebx」という命令が存在している場所
へ制御を移行させるようにします。

「call ebx」というのは、レジスタEBXが示す場所へ制御を移
行しなさい、という命令です。

この命令を実行する事により、レジスタEBXが示している場所
(任意のコード)へ制御を移行する事が出来ます。

以下に動作イメージを示します。

                      ┌──────────────┐
                      │元々は「メッセージを表示する│
                      │プログラムの場所」情報だが、│
                      │バッファオーバーフローにより│
                      │書き換わっている。     │
   例外ハンドラが制御を移行しようとした └─────────────┬┘
   瞬間は必ずここを指している。         ┌───────┐ │
   ┌─────────────────────→│ FF FF FF FF │ │
   │┌───→──────────→─────→├───────┤ │
   ││       ・             │call ebxの場所│←┘
   ││       ・             └───┬───┘
   ││    ×××××××              │
   ││    ×そんな所に×              │
   ││    ×実行可能な×              │
   ││    ×プログラム×              │
   │↑    ×ありません×              │
   ││    ×××××××              │
   ││       │★例外発生            │
   ││ ┌─────┴────┐            │
   ││ │          │            │
   ││ │例外ハンドラ動作開始│            │
   ││ │          │            │
   ││ └─────┬────┘            │
   │└──┐    │何を起動するか参照        │
┌──┴──┐│ 制御を│←────────────────┘
│     ││  移行↓
└─────┘↑ ┌─────┐
レジスタEBX │ │ call ebx │
       │ └──┬──┘
       │ 制御を│
       │  移行↓
       └─←──┘


上の動作イメージを見ると、インテルプロセッサは「スタック
領域」に制御を移行しています。

スタック領域はデータを格納する為の領域であり、実行する事
は不可能だと思っている方もいらっしゃるかもしれません。

しかし意外な事にスタック領域上で実行する事は可能なのです。

この様にしてインテルプロセッサはスタック領域上を、つまり
バッファオーバーフローにより自由に書き換え可能な場所を実
行してしまうのです。


それでは実際にプログラムを作成してみましょう。

今回はWindows98上で動作するプログラムのみ示します。
Windows2000を御使用の方は次回に示します。

まずは以前に作成したプログラム"of3.c"をコピー&貼り付け
して新しく出来たファイルを"of4.c"という名前に変更しまし
ょう。

今回は"of4.c"に変更を加えていきます。
以下に変更後の"of4.c"を示します。
変更部分にはコメントを付けておきます。


─↓"of4.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,
// ●↓ここから変更
             0xcd, 0x01, 0x90, 0x90,
             0x0c, 0x67, 0xf2, 0xbf,
// ●↑ここまで変更
          };
  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));
  }
}
─↑"of4.c"ここまで──────────────────


1箇所だけ変更しました。

変更前は
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,

となっていたのを

変更後は
0xcd, 0x01, 0x90, 0x90,
0x0c, 0x67, 0xf2, 0xbf,

としました。

変更部分の2行目は「メッセージを表示するプログラムの場所」
情報が格納されるはずの部分ですが、ここを「call ebx」が格
納されているOS内部の場所を示すように変更しました。

Windows98では「BFF2670C」という場所に「call ebx」という
命令が存在しています。(ただし1部例外はあると思います。)

0xcd, 0x01, 0x90, 0x90,
0x0c, 0x67, 0xf2, 0xbf,←call ebxが存在している場所

変更部分の1行目には実行コードを格納してあります。
「call ebx」という命令が実行される事により、変更部分の1
行目の部分に制御が移行され、コードが実行される事になりま
す。

「cd 01」という機械語コードは割込みを発生させる命令で、
「90 90」というのは「何もしない。」という機械語コードで
す。

0xcd, 0x01, 0x90, 0x90,←割込みを発生させる機械語コード
0x0c, 0x67, 0xf2, 0xbf,←call ebxが存在している場所

たった1箇所ですが、この変更を行う事により上のイメージに
示したように「call ebx」が実行され、割込みを発生させる機
械語コードが実行される事になります。

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

sc of4.c -j

これで"of4.exe"という実行形式ファイルが出来上がるはずで
す。

出来上がったら実行しましょう、と言いたいところですが、そ
の前に注意事項があります。

【注意】
┌────────────────────────────┐
│このプログラムにはわざとバグを仕込んであります。    │
│実行するにあたっては必ず自己責任において実行させるように│
│してください。                     │
│                            │
│特にこのプログラムは非常に危険な機械語コードを実行するよ│
│うプログラムされています。(システムが不安定になる。) │
│                            │
│実行結果においては著者は一切の責任を負いませんので、予め│
│御了承下さい。                     │
│                            │
│尚、このプログラムはWindows98 上で動作するように作られて│
│いますが、Windows98 上であれば必ず動作するという事を保証│
│するものではありません。                │
│1部意図した様に動作しない場合もあると思いますが、あわせ│
│て御了承下さい。                    │
└────────────────────────────┘

上記注意事項が守れる方は実行させてみてください。


真っ青な画面が表示されたと思います。

これは先ほどの「cd 01」という割込みを発生させる機械語コ
ードが実行された事により表示されたものです。


次回はWindows2000上で動作するプログラムを作ってみる予定
です。



▲このページの上へ

▲このページの上へ

▲このページの上へ

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

▲このページの上へ