(57)【要約】プログラムの実行時におけるバッファオーバーフローによるリターンアドレスの改ざん防止のための方法を提供する。  プログラムが実行されたときにリターンアドレスが書き換えられた場合、中央演算処理装置のデバッグ機能を利用して、エラー出力を行う。エラー出力によって、リターンアドレスの改ざんを検知し、予め保存された値で改ざんされたリターンアドレスを書き直して、プログラムを正常な動作に戻す。【特許請求の範囲】
【請求項１】
電子計算機の記憶媒体に格納されているプログラムが中央演算処理装置によって実行されるとき、
メモリのスタックメモリ領域に格納されているリターンアドレスが、不正コードの実行によってオーバーライトされる前記メモリのバッファオーバーフローを検知し、前記バッファオーバーフローの発生を防止する方法において、
前記リターンアドレスをバックアップし、
前記不正コードの実行によって前記リターンアドレスが改ざんされるとき、前記改ざんを前記中央演算処理装置のデバッグ機能によって検知する
ことを特徴とする不正コード実行の防止方法。
【請求項２】
請求項１において、
前記デバッグ機能に利用されるデバッグレジスタに、前記リターンアドレスが格納されているメモリ番地を記録し、
前記デバッグレジスタに記録された前記メモリ番地の値が改ざんされたとき、前記中央演算処理装置がエラーの信号を出力して前記検知を行う
ことを特徴とする不正コード実行の防止方法。
【請求項３】
請求項１又は２において、
前記リターンアドレスを実行プログラムのデータが格納されていないメモリ領域に保存して前記バックアップを行う
ことを特徴とする不正コード実行の防止方法。
【請求項４】
請求項３において、
前記スタックメモリ領域に格納されている前記リターンアドレスを、前記バックアップされたアドレスと比較して前記バッファオーバーフローを検知する手段を有する
ことを特徴とする不正コード実行の防止方法。
【請求項５】
請求項３又は４において、
前記リターンアドレスが改ざんされたとき、前記メモリ番地を保存された前記リターンアドレスで書き換える制御手段を有する
ことを特徴とする不正コード実行の防止方法。
【請求項６】
請求項１又は２において、
前記リターンアドレスが格納されている前記スタックメモリ領域を読み出し専用の属性にして、前記リターンアドレスを保護し、
読み出し専用の属性に設定されている前記前記スタックメモリ領域に書き込みを行うときに、前記中央演算処理装置がエラーの信号を出力して前記検知を行い、
前記エラーの信号を受けて、前記プログラムを停止又は、前記プログラムの流れを制御するための制御手段を有する
ことを特徴とする不正コード実行の防止方法。
【請求項７】
請求項１から６の中から選択されるいずれか１項において、
前記リターンアドレスは、前記プログラムが実行されるときに呼び出されるプロセス、前記プロセスから呼び出されるスレッドの内の１以上のリターンアドレスである
ことを特徴とする不正コード実行の防止方法。
【請求項８】
電子計算機の記憶媒体に格納されているプログラムが中央演算処理装置によって実行されるとき、
メモリのスタックメモリ領域に格納されているリターンアドレスが不正コードの実行によってオーバーライトされるメモリのバッファオーバーフローを検知し、前記バッファオーバーフローの発生を防止させるように前記電子計算機を動作させる不正コード実行の防止用プログラムにおいて、
前記プログラムが前記記憶媒体から呼び出されるとき、前記プログラムの中の分岐命令を取得して解析するための解析ステップと、
前記プログラムのプロセス又はスレッドの前記リターンアドレスを抽出するための抽出ステップと、
前記リターンアドレスが前記スタックメモリ領域に格納される番地を前記中央演算処理装置のデバッグ機能のデバッグアドレスに登録するための登録ステップと、
前記プログラムが動作するとき、前記プログラムの流れを制御するための制御ステップと、
前記リターンアドレスと前記番地を登録してバックアップするためのバックアップステップと
から構成され、
前記プログラムの実行時に前記リターンアドレスが改ざんされるとき、前記デバッグ機能により前記中央演算処理装置がエラーの信号を出力し、前記プログラムの実行に割り込みを行い、前記プログラムの流れを前記制御ステップに移動させる
ことを特徴とする不正コード実行の防止用プログラム。
【請求項９】
請求項８において、
前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記プログラムを停止させるステップを有する
ことを特徴とする不正コード実行の防止用プログラム。
【請求項１０】
請求項８又９において、
前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記リターンアドレスをバックアップされた前記リターンアドレスで書き換えするステップを有する
ことを特徴とする不正コード実行の防止用プログラム。
【請求項１１】
請求項８又９において、
前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記書き換えした値を保存するステップを有する
ことを特徴とする不正コード実行の防止用プログラム。
【請求項１２】
請求項８において、
前記リターンアドレスが格納されている前記スタックメモリ領域を読み出し専用の属性にして、前記リターンアドレスを保護するための保護ステップと、
読み出し専用の属性に設定されている前記前記スタックメモリ領域に書き込みを行うときに、前記中央演算処理装置がエラーの信号を出力して前記検知を行うための検知ステップと、
前記エラーの信号を受けて、前記プログラムを停止又は、前記プログラムの流れを制御するための前記制御ステップとを有する
ことを特徴とする不正コード実行の防止用プログラム。
【請求項１３】
請求項８から１２の中から選択される１項において、
前記プログラムは、アプリケーションソフトウェア、オペレーティングシステムのソフトウェアモジュール、カーネルモードソフトウェア、これらの中で使用する関数、サブルーチンから選択される内１以上である
ことを特徴とする不正コード実行の防止用プログラム。
【請求項１４】
請求項８から１３の中から選択される１項に記載された、不正コード実行の防止用プログラムを記録した不正コード実行の防止用プログラムの記録媒体。
【発明の詳細な説明】
【技術分野】
【０００１】  本発明は、電子計算機で動作するプログラムが不正コードによる動作不備又は外部からの攻撃から保護する不正コード実行の防止方法、不正コード実行の防止用プログラム、及び不正コード実行の防止用プログラムの記録媒体に関する。
詳しくは、バッファオーバーフローを検出し、プログラムの動作不備を改善する不正コード実行の防止方法、不正コード実行の防止用プログラム、及び不正コード実行の防止用プログラムの記録媒体に関する。
【背景技術】
【０００２】  電子計算機のオペレーティングシステムは複雑に設計されている。このため、オペレーティングシステムには、セキュリティホールと呼ばれる弱点がある。セキュリティホールとは、ソフトウェアの設計の欠陥やバグにより生じる脆弱性の構造である。悪意のあるユーザは、オペレーティングシステムのこのセキュリティホールを利用して、オペレーティングシステムへ不正に侵入し、ハッキング、クラッキング等の悪意の行為を行うことがある。その手段としては、メモリのバッファオーバーフロー（Ｂｕｆｆｅｒ  ｏｖｅｒ  ｆｌｏｗ）を利用する方法がある。【０００３】  ここで、バッファオーバーフローについて説明する。電子計算機で動作するプログラムは、プログラムコードとプログラムデータの２つの部分から構成される。プログラムコードは、機械語で書かれた読み出し専用のコードである。プログラムデータは、オペレーティングシステムの実行命令によって実行されるプログラムコードのメモリ上の位置等のインフォメーション部分である。【０００４】  プログラムは、通常は、電子計算機のハードディスクに保存されている。プログラムはオペレーティングシステムによって呼び出され実行するとき、プログラム全体で又はその一部が電子計算機のメインメモリであるＲＡＭ（Ｒａｎｄｏｍ  Ａｃｃｅｓｓ  Ｍｅｍｏｒｙ）に格納されて動作する。メインメモリは、電子計算機のＣＰＵ（中央処理装置）から直接データの読み書きできるメモリで、データを格納する単位容量ごとに番地番号をつけて管理されている。メインメモリの番地番号の小さい方を上位番地（Ｈｉｇｈ  Ｍｅｍｏｒｙ）領域、番地番号が大きくなると下位番地（Ｌｏｗ  Ｍｅｍｏｒｙ）領域としている。以下、メインメモリを単にメモリとして説明する。【０００５】  プログラムがオペレーティングシステムによって読み出されると、メモリの一部がこのプログラムに割り当てられて、その割り与えられたメモリの上位番地（Ｈｉｇｈ  Ｍｅｍｏｒｙ）領域にプログラムデータが格納され、下位番地（Ｌｏｗ  Ｍｅｍｏｒｙ）領域にプログラムコードが格納される。プログラムデータは、スタックデータ（Ｓｔａｃｋ  ｄａｔａ）、ヒープデータ（Ｈｅａｐ  ｄａｔａ）、スタティックデータ（Ｓｔａｔｉｃ  ｄａｔａ）の３つのデータ領域に分かれている。これらの３つの領域は、お互いに独立してメモリに配置されている。実行されるプログラムが、オペレーティングシステムによってハードディスクから呼び出されると、最初は、プログラムコードが読み出されメモリに格納される。続いて、プログラムデータが読み出されてメモリに格納される。【０００６】  図５は、電子計算機のメモリの構造を示す概念図である。メモリの上位番地側はスタックメモリ領域になっている。スタックメモリ領域は、プログラムが実行されるごとに、そのプログラムとプログラム内のサブルーチン用のスタックメモリがここに確保されてメモリの下位番地へと順番に格納される。スタックメモリは、引数（Ａｒｇｕｍｅｎｔ）領域、リターンアドレス（Ｒｅｔｕｒｎ  Ａｄｄｒｅｓｓ）領域、スタックデータ領域等から構成される。【０００７】  メモリの下位番地側は、ヒープデータ領域、スタティックデータ領域、プログラムコード領域等の領域から構成されている。スタティックデータ領域は、プログラムコード領域より上位番地側に位置し、グローバル変数とｓｔａｔｉｃ  Ｃ＋＋クラスメンバーが予約されるメモリ領域である。スタティックデータ領域より上位番地側にはヒープデータ領域が位置する。ヒープデータ領域はＣ言語のｍａｌｌｏｃ（）、ａｌｌｏｃ（）関数、Ｃ＋＋言語のｎｅｗオペレータに割り当てられている領域である。【０００８】  スタックメモリ領域はＬＩＦＯ（Ｌａｓｔ−ｉｎ，ｆｉｒｓｔ−ｏｕｔ）方式でアクセスされる。スタックメモリは、実行命令が終了後の次の命令が実行されるリターンアドレス等の関数パラメータやローカル変数等が格納される。このリターンアドレスはもっとも重要な値である。【０００９】  図６には、Ｃ言語で書かれているプログラムを例示している。プログラムが実行されると、まずｍａｉｎ（）関数が実行されて（行１〜３）、４行目のサブルーチンのｓｕｂ（Ｄａｔａ１）が呼び出されてプログラムの処理が１０行目に移っている。ｓｕｂ（）サブルーチンでは、１６行目のｒｅｔｕｒｎ命令で、ｓｕｂ（）を呼び出した元の位置へ処理を移している。このとき、メモリにどのようにデータが格納されるかを説明する。【００１０】  サブルーチンが呼び出されると、図７に図示したように、スタックメモリ領域にデータが書き込まれる。スタックメモリ領域の上位番地側から「ｍａｉｎ（）へのリターンアドレス」が格納されて、サブルーチン内のローカル変数が格納される領域が予約される。この例では、変数ｉ（１１行目）とｂｕｆ（１２行目）がある。１４行目のｓｔｒｃｐｙ命令でサブルーチンの引数Ｄａｔａの値をｂｕｆにコピーしている。このとき、引数Ｄａｔａの値がｂｕｆのサイズより大きい場合は、ローカル変数ｉ、場合によっては、ｍａｉｎ（）ルーチンへのリターンアドレスまで上書きしてしまうことになる。このように、データが確保されたメモリの領域に入りきれないで別の変数のための領域にまで書き込まれる。これは、バッファオーバーフローである。リターンアドレスが別の値に書き換えられているので、プログラムは正常の動作をしなくなる。【００１１】  通常これらのプログラム、プログラムのサブルーチン、関数が実行されて終わると、リターンアドレスに示された位置に戻され、プログラムの実行が継続される。しかし、プログラムの作り方に不具合があると、上に説明したように、データを書き込みするときにローカル変数の確保領域を超えてリターンアドレスを上書きすることが可能になる。【００１２】  通常リターンアドレスの書き換えによってバッファオーバーフローを起こしたプログラムは、不定な実行状態となる。場合によっては、プログラムが暴走、あるいは停止することが殆どである。リターンアドレスが意図的に用意したメモリ番地に戻されると、オペレーティングシステムはこれを不正なコードと分からずにこのメモリ番地に格納されている命令を継続して実行させる。バッファオーバーフローによる脆弱性を利用した攻撃は、このように意図的に用意したコードを実行させることである。【００１３】  このようなバッファオーバーフローによる不正コードの実行は、プログラムの実行管理を行っているオペレーテ���ングシステムでは全く把握できない。この不正コードの実行を防ぐには、リターンアドレスの改ざん、書き換えを如何に防ぐか、あるいは検知できるかが非常に重要である。【００１４】  この問題を解決する方法としては、オペレーティングシステムに修正を加える方法や、コンパイラにバッファオーバーフローを防ぐ仕組みを作る方法等が提案されている。オペレーティングシステムに修正を加える方法としては、非特許文献１のプロジェクトがある。このプロジェクトでは、オープンソースのオペレーティングシステムのバッファオーバーフローを防ぐためには、スタックのリターンアドレス領域を関数が実行されない別のメモリ領域に移す方法で対処している。【００１５】  コンパイラにバッファオーバーフローを防ぐ仕組みをする方法としては、非特許文献２がある。この方法は、ＧＣＣコンパイラに、スタックメモリの下位番地に保護セクションを設けてデータのオーバーライトを検知している。【００１６】  また、特許文献１の場合は、記憶装置に保護数値の領域を定義し、スタックメモリのデータを保護数値の領域に保存して保護し、処理指令を実行している。保護数値の領域にリターンアドレス等が保護されているためサブルーチン等の処理指令が実行されてもプログラムカウンタが保護される。
【非特許文献１】Ｏｐｅｎｗａｌｌ  Ｌｉｎｕｘ  ｋｅｒｎｅｌ  ｐａｔｃｈ  ｐｒｏｊｅｃｔ，ＵＲＬ：ｈｔｔｐ：／／ｗｗｗ．ｏｐｅｎｗａｌｌ．ｃｏｍ／ｌｉｎｕｘ／
【非特許文献２】ＳｔａｃｋＧｕａｒｄ：Ｓｉｍｐｌｅ  Ｓｔａｃｋ  Ｓｍａｓｈ  Ｐｒｏｔｅｃｔｉｏｎ  ｇｏ  ＧＣＣ，ＵＲＬ：ｈｔｔｐ：／／ｗｗｗ．ｉｍｍｕｎｉｘ．ｃｏｍ／〜ｗａｇｌｅ
【特許文献１】米国公開特許番号  ＵＳ２００１０１３０９４？Ａ１？−？２００１−０８−０９、“Ｍｅｍｏｒｙ  ｄｅｖｉｃｅ，ｓｔａｃｋ  ｐｒｏｔｅｃｔｉｏｎ  ｓｙｓｔｅｍ，ｃｏｍｐｕｔｅｒ  ｓｙｓｔｅｍ，ｃｏｍｐｉｌｅｒ，ｓｔａｃｋ  ｐｒｏｔｅｃｔｉｏｎ  ｍｅｔｈｏｄ，ｓｔｏｒａｇｅ  ｍｅｄｉｕｍ  ａｎｄ  ｐｒｏｇｒａｍ  ｔｒａｎｓｍｉｓｓｉｏｎ  ａｐｐａｒａｔｕｓ”．
【発明の開示】
【発明が解決しようとする課題】
【００１７】  上記のいずれの方法においても、プログラムコードの変更及びリビルドが必要である。よって、これらの方法を実施しする際には、時間が掛かる。また、この不正コードの実行を利用している代表的なものは、コンピュータウィルスである。従来からコンピュータウィルスからの防止手法はシグネチャ方式であり、未知の攻撃パターンの場合は何の効果も無い。そのため、不具合が生じる度にオペレーティングシステムの変更、パッチファイルの提供が必要とされている。【００１８】  本発明は上述のような技術背景のもとになされたものであり、下記の目的を達成する。
本発明の目的は、電子計算機のメモリの番地に格納されているデータの改ざん防止、データ改ざんの検出を行う方法、そのプログラム、プログラムの記録媒体を提供することである。
本発明の目的は、プログラムの実行時におけるスタックメモリ内のリターンアドレスへの改ざん防止と検出を行う方法を提供することである。
本発明の他の目的は、ハードウェア、オペレーティングシステム、カーネルモードソフトウェア、アプリケーションソフトウェアを変更することなく利用できる不正コード実行の防止機能を提供することである。
本発明の更に他の目的は、アプリケーションソフトウェア及び、カーネルモードソフトウェアがバッファオーバーフローによる脆弱性を有するときも有効に不正コード実行の防止機能を提供することである。
本発明の更に他の目的は、不正コードが実行される前に検出し、不正なコードの実行を抑止することである。
【課題を解決するための手段】
【００１９】  本発明は、前記目的を達成するため、次の手段を採る。
本発明の１発明の不正コード実行の防止方法は、電子計算機の記憶媒体に格納されているプログラムが中央演算処理装置によって実行されるとき、メモリのスタックメモリ領域に格納されているリターンアドレスが、不正コードの実行によってオーバーライトされる前記メモリのバッファオーバーフローを検知し、前記バッファオーバーフローの発生を防止するための方法である。【００２０】  この不正コード実行の防止方法は、前記リターンアドレスをバックアップし、前記不正コードの実行によって前記リターンアドレスが改ざんされるとき、前記改ざんを前記中央演算処理装置のデバッグ機能によって検知することを特徴とする。【００２１】  また、前記デバッグ機能に利用されるデバッグレジスタに、前記リターンアドレスが格納されているメモリ番地を記録し、前記デバッグレジスタに記録された前記メモリ番地の値が改ざんされたとき、前記中央演算処理装置がエラーの信号を出力して前記検知を行うと良い。【００２２】  更に、前記リターンアドレスを実行プログラムのデータが格納されていないメモリ領域に保存して前記バックアップを行うと良い。
また更に、前記スタックメモリ領域に格納されている前記リターンアドレスを、前記バックアップされたアドレスと比較して前記バッファオーバーフローを検知する手段を有すると良い。【００２３】  また更に、前記リターンアドレスが改ざんされたとき、前記メモリ番地を保存された前記リターンアドレスで書き換える制御手段を有すると良い。
また更に、前記リターンアドレスが格納されている前記スタックメモリ領域を読み出し専用の属性にして、前記リターンアドレスを保護し、読み出し専用の属性に設定されている前記前記スタックメモリ領域に書き込みを行うときに、前記中央演算処理装置がエラーの信号を出力して前記検知を行い、前記エラーの信号を受けて、前記プログラムを停止又は、前記プログラムの流れを制御するための制御手段を有すると良い。
前記リターンアドレスは、前記プログラムが実行されるときに呼び出されるプロセス、前記プロセスから呼び出されるスレッドの内の１以上のリターンアドレスであると良い。【００２４】  本発明の第２の発明の不正コード実行の防止用プログラムは、電子計算機の記憶媒体に格納されているプログラムが中央演算処理装置によって実行されるとき、メモリのスタックメモリ領域に格納されているリターンアドレスが不正コードの実行によってオーバーライトされるメモリのバッファオーバーフローを検知し、前記バッファオーバーフローの発生を防止させるように前記電子計算機を動作させるためのプログラムである。
この不正コード実行の防止用プログラムは、前記プログラムが前記記憶媒体から呼び出されるとき、前記プログラムの中の分岐命令を取得して解析するための解析ステップと、前記プログラムのプロセス又はスレッドの前記リターンアドレスを抽出するための抽出ステップと、前記リターンアドレスが前記スタックメモリ領域に格納される番地を前記中央演算処理装置のデバッグ機能のデバッグアドレスに登録するための登録ステップと、前記プログラムが動作するとき、前記プログラムの流れを制御するための制御ステップと、前記リターンアドレスと前記番地を登録してバックアップするためのバックアップステップとから構成され、前記プログラムの実行時に前記リターンアドレスが改ざんされるとき、前記デバッグ機能により前記中央演算処理装置がエラーの信号を出力し、前記プログラムの実行に割り込みを行い、前記プログラムの流れを前記制御ステップに移動させることを特徴とする。【００２５】  また、前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記プログラムを停止させるステップを有すると良い。
更に、前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記リターンアドレスをバックアップされた前記リターンアドレスで書き換えするステップを有すると良い。【００２６】  また更に、前記リターンアドレスが書き換えられたとき、前記制御ステップは、前記書き換えした値を保存するステップを有すると良い。
前記リターンアドレスが格納されている前記スタックメモリ領域を読み出し専用の属性にして、前記リターンアドレスを保護するための保護ステップと、読み出し専用の属性に設定されている前記前記スタックメモリ領域に書き込みを行うときに、前記中央演算処理装置がエラーの信号を出力して前記検知を行うための検知ステップと、前記エラーの信号を受けて、前記プログラムを停止又は、前記プログラムの流れを制御するための前記制御ステップとを有すると良い。
また更に、前記プログラムは、アプリケーションソフトウェア、オペレーティングシステムのソフトウェアモジュール、カーネルモードソフトウェア、これらの中で使用する関数、サブルーチンから選択される内１以上であると良い。【００２７】  本発明の第３の発明の不正コード実行の防止用プログラムの記録媒体は、上述の不正コード実行の防止用プログラムを記録した記録媒体である。
【発明の効果】
【００２８】  本発明によると、次の効果が奏される。
本発明の不正コード防止方法は、ハードウェア、オペレーティングシステム、カーネルモードソフトウェア、アプリケーションソフトウェアを変更することなく、不正コードの実行を防止できる。
本発明の不正コード防止方法は、アプリケーションソフトウェア及び、カーネルモードソフトウェアが、バッファオーバーフローによる脆弱性を有するときも有効に対応できる。
本発明の不正コード防止方法は、不正コードが実行される前に検出し、不正なコードの実行を抑止できる。
【発明を実施するための最良の形態】
【００２９】  以下、本発明の最良の実施の形態を図面によって具体的に説明する。
［実施の形態１］
以下、本発明の実施の形態１を説明する。
本発明は、電子計算機のメインメモリに格納されているデータが書き換えをされ、改ざんされる行為を検知する方法を提供するものである。また、この方法により、電子計算機のメインメモリに格納されているデータが書き換えをされ、改ざんされる行為を検知し、書き換えまたは改ざんされたデータを復元するためのプログラムを提供する。更に、本発明は、そのプログラムを記録した記録媒体を提供するものである。この本発明の実施の形態の概要を説明する。【００３０】  ＣＰＵのデバッグ機能は、アプリケーションプログラムが実行されるときに発生するエラーを検出するための機能である。このためには、ＣＰＵにデバッグレジスタと呼ばれる複数のメモリを用意しており、メインメモリの特定の番地の動作を監視するために利用している。このデバッグレジスタに監視する番地のアドレス及びＣＰＵ動作を登録し、この番地の値が変更されるときにＣＰＵがこれを検知してエラー信号を出している。そして、アプリケーションプログラムの実行に割り込みをして、別のプログラムを動作させることが可能である。【００３１】  本実施の形態１では、バッファオーバーフローによる不正コードの実行を検知し、データ改ざん等を防止するプログラムの動作を説明する。電子計算機上にプログラムが動作するときに、従来技術で説明したように、プログラム、サブプログラム、関数が呼び出されるごとにそのリターンアドレスがスタックメモリ領域に格納される。電子計算機のＣＰＵのデバッグレジスタには、リターンアドレスが格納されているメインメモリの番地を指定して記録して置く。【００３２】  また同時に、リターンアドレスをメインメモリの別の領域にバックアップして置く。この番地のデータが改ざんされるとＣＰＵによってエラーが検知され、実行されているプログラムに割り込みをし、制御を別のプログラムに移動させて、データ改ざん、不正コードの実行を防止することができる。バックアップしたリターンアドレスを、元の番地に書き換えし、プログラムを正常な動作に戻す。また、書き換えられたアドレスをバックアップして、バッファオーバーフローによるコンピュータウィルス攻撃のパターン解析にも利用することが可能である。【００３３】  以下、本発明の実施の形態１の不正コード防止方法は、このデバッグレジスタを利用したデータの改ざんを検知し、改ざんされたデータを修復する方法を実現させるために、ドライバウェア層と、エラールーチンを提供するものである。このドライバウェア層は、上述のリターンアドレスを把握し、デバッグレジスタに登録し、バックアップする機能を有する。エラールーチンは、リターンアドレスのデータが改ざんされると、この改ざんを修復するための機能を提供している。以下、本発明の実施の形態１を詳細に説明する。【００３４】  図１には、本発明の実施の形態の概要を図示している。図１には、電子計算機上で動作するソフトウェア１、ドライバウェア２、ファイルシステムドライバ３、ハードディスク４が図示されている。通常、実行可能なプログラムはハードディスク４に実行可能ファイル５として保存され、オペレーティングシステムの呼び出し命令で読み出されメモリ６へ格納される。ソフトウェア１は、電子計算機上に��作しているアプリケーションプログラムを意味する。このアプリケーションプログラムは、オペレーティングシステムのカーネルモード又は、ユーザモードで動作するどのようなプログラムでも良い。【００３５】  ドライバウェア２は、ファイルシステムドライバ３とオペレーティングシステムが提供するサービスとの間に位置するもので、オペレーティングシステムから電子計算機の各デバイスから／へ読み出し／書き込みをするときの制御を行うプログラムである。【００３６】  ファイルシステムドライバ３は、電子計算機に内蔵又は接続されている記憶装置に格納されているデータを読み出し、この記憶装置にデータを書き込みするためのドライバである。ハードディスク４は、通常、電子計算機に内蔵されているハードディスクである。しかし、ソフトウェア１が格納され、オペレーティングシステムから呼び出されて実行可能であれば、外付けハードディスク、フラッシュメモリ、ＣＤ−ＲＯＭなどの外部記憶装置であっても良い。【００３７】  本実施の形態１では、オペレーティングシステムからプログラム（図１の実行可能ファイル５）を呼び出しする命令は、ドライバウェア２を介してファイルシステムドライバ３へ送信される形式をとる。
ファイルシステムドライバ３はハードディスク４からプログラムを呼び出し、ドライバウェア２へ渡す。ドライバウェア２はプログラムを解析してメインルーチン、サブルーチンを把握し、それぞれのリターンアドレスを取得し、バッファオーバーフローを検出する制御を行う。リターンアドレスは、ＣＡＬＬ命令等の分岐命令で出力されてスタックメモリに格納され、ＲＥＴ、ＲＥＴｘｘ命令で戻るためのアドレスである。
この一連の動作を図３のフローチャートを参照しながら説明する。オペレーティングシステム、又はアプリケーションプログラムからプログラム（図１の実行可能ファイル５）を起動する（ステップ１）。ドライバウェア２は、プログラムの起動を検出する（ステップ２）。ドライバウェア２は、プログラムを解析してメインルーチン、サブルーチンを把握し、それぞれのリターンアドレスを取得する。ドライバウェア２は、プログラムの起動によって生成される引数、ローカル変数、関数アドレスを調べ（ステップ３）、関数アドレスを保存する。具体的には、プログラム内で実行されるコール（ＣＡＬＬ）、リターン（ＲＥＴ、ＲＥＴＮ）、ジャンプ（ＪＭＰ）等の分岐命令の実行するイベントを調べリターンアドレスを取得し、保存する（ステップ４）。【００３８】  そして、ドライバウェア２は、プログラムが実行している間に、コール命令（Ｃａｌｌ命令）等の分岐命令をフックするようにしてドライバウェア２へ制御を移動できるようにする（ステップ５）。具体的には、ＯＳが提供するＰｓＳｅｔＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ（）を呼び出し、プロセス起動時に呼び出されるコールバック関数（ＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ）を登録して行われる。スレッド生成の場合は、＿ｂｅｇｉｎｔｈｒｅａｄ（）の開始アドレスを取得し、この開始アドレスにブレークポイントを設置する。ドライバウェア２は、プログラムの実行時に、スタックメモリ上のリターンアドレスの保護と改ざんの検出機能を組み込む（ステップ６）。【００３９】  リターンアドレスの保護には、上述のＣＰＵのデバッグ機能を利用する。このように、ＣＰＵのデバッグ機能の内、特定のメモリ番地が書き換えられるとエラー出力をする機能があり、制御が指定された番地へ移動させることが可能である。このとき、ＣＰＵのデバッグレジスタにリターンアドレスのメモリ番地を指定してエラーが検知されるとき、オペレーティングシステムは割り込み命令を出し、ドライバウェア２へ制御を移す。
リターンアドレスにこの機能を適用する。よって、リターンアドレスが書き換えられるとデバッグ機能によりエラーを検出し、ドライバウェア２へ制御が移動するように設定される。ドライバウェア２はステップ１で指定されたプログラムを実行する（ステップ７）。【００４０】  図４は、プログラムが起動されて実行されるときのバッファオーバーフローを検出する手順を示すフローチャートである。【００４１】  オペレーティングシステム又はアプリケーションプログラムからは、プログラムを実行するときに呼び出し命令（Ｃａｌｌ命令）が実行されると、ＣＰＵの割り込みが発生し、ドライバウェア２に制御が移る（ステップ１０〜１１）。ドライバウェア２はプログラムの実行によって生成される引数、ローカル変数、関数アドレスを調べ（ステップ１２）、実行時におけるスタックメモリ上のリターンアドレスをデバッグ機能によって保護、又は、記憶する（ステップ１３）。【００４２】 この保護は、リターンアドレスが格納されているスタックメモリを読み出し専用の属性に設定して行われる。このスタックメモリに書き込みを行うときＣＰＵがエラーを発生し、ＣＰＵの割り込みが発生し、ドライバウェア２に制御が移るため、リターンアドレスを変更し改ざんすることができなくなり、保護することが可能になる。上述の記憶は、スタックメモリ上のリターンアドレスをメモリの別の領域にバックアップして保存する。リターンアドレスが改ざんされたときは、このバックアップしてリターンアドレスと比較して改ざんを検証することが可能になる。【００４３】  そして、ドライバウェア３が命令（ＩＲＥＴ）を出し（ステップ１４）、ステップ１１で割り込まれた実行アドレスへ制御を戻す（ステップ１５）、実行する（ステップ１６）。
プログラムの実行中にバッファオーバーフローになると、リターンアドレスが上書きされて、ＣＰＵがエラーを出力する。又は、呼び出された関数からの戻る直前で、ドライバウェアがステップ１３で記憶したリターンアドレスと、スタック上のリターンアドレスを比較する（ステップ１７〜１９）。ドライバウェア２がエラーを検出する（ステップ２０）。そして、プログラムの実行を中断して、エラールーチンへ制御が移る（ステップ２１）。エラールーチン（図示せず）は、エラーが検出されたときに実行され、プログラムの実行が停止、スタックメモリの内容の保存やリターンアドレスを事前に保存したデータで書き換えする等の機能を持つプログラムである。このエラールーチンによって、プログラムの実行を停止、継続、そして不正コードの保存ができる（ステップ２２）。【００４４】  図２には、電子計算機が外部から攻撃される例を図示している。ネットワークカード１０を介して、ウィルスや不正コード等を有する外部データが送信されてくる。外部データはネットワークカード１０、ＮＤＩＳ１１、Ｗｉｎｓｏｃｋ１２を介してメモリ６に格納される。外部データがメモリ６に格納されるとき、プログラムのリターンアドレスの一部又は全部が書き換えられると、ＣＰＵがエラーを出力し制御がドライバウェア２に移る。ドライバウェア２はこのエラー検出を受けてエラールーチンをフックして対応する。
このように、バッファオーバーフローを利用した不正侵入、攻撃はすべて把握し、対処することができる。実行中のプロセスの停止、スタックメモリの内容の保存、元のプロセスの実行継続などができる。プロセスの停止によっては、実行しているプロセスを停止して、プログラムの暴走を止めることができる。スタックメモリの内容の保存によっては、不正コードを保存でき、その後の解析などの作業で攻撃、ウィルスの種類、そのパターンを把握できる。【００４５】  本実施の形態は、ユーザモードだけで動作するアプリケーションプログラムだけはなくて、カーネルモードで動作するプログラムにも適応される。また、同様な方法でバッファオーバーフローの手法を利用するプログラムであれば全てに適応できる。
【実施例】
【００４６】  本発明の実施の形態１の実施例を示す。本実施例では、Ｉｎｔｅｌ社（登録商標）の３２ビットアーキテクチャーのプロセッサで、命令トレース機能を実装しているものを想定している。具体的には、ＰｅｎｔｉｕｍＰｒｏ（登録商標）以後に開発されたプロセッサ、又はこのプロセッサと互換性のあるプロセッサである。オペレーティングシステムは、マイクロソフト社のＷｉｎｄｏｗｓ２０００（登録商標）である。
ドライバウェア２が動作し、バッファオーバーフローの検知を行うための準備としての初期化処理、プログラムが実行されると発生されるプロセスとスレッドを検知し、メインルーチン、サブルーチンを把握する。そして、ドライバウェア２がバッファオーバーフローを検知すると、エラールーチンとしてプロセス中断処理を動作させて対処する。これらの動作について、詳細に説明する。【００４７】  ドライバウェアが起動すると初期化処理を行う（図８を参照、説明は後述する。）。この初期化処理では、プログラムが呼び出されるとき生成されるプロセスとスレッドの検知を行う。この初期化処理の詳細は、図８〜１０のフローチャート（後述する）で示している。
この初期化処理を行った後は、プログラムが動作を開始する。このプログラムの動作中に実行されるジャンプ（ＪＭＰ）、コール（ＣＡＬＬ）、リターン（ＲＥＴ）等の分岐命令をすべて登録し、トレースする。ＣＡＬＬ、ＲＥＴ、ＲＥＴｘｘ命令が実行されるとき、バッファオーバーフローを検知している。ＣＡＬＬ、ＲＥＴ、ＲＥＴｘｘ命令の検知は、図１１、１２に示すフローチャートに示している。【００４８】  ＣＡＬＬ、ＲＥＴ、ＲＥＴｘｘ命令の検知された後の処理は、図１３〜図１６のフローチャートと、このフローチャートに対応する説明中のプログラムコードに示している。【００４９】  （初期化処理）
図８のフローチャートは、初期化処理の概要を示している。まずは、ドライバウェアが起動し、バッファオーバーフローを監視するプロセス名をレジストリから読み込む（ステップ１００）。そして、監視対象のプロセスのプロセス生成コールバックを登録する（ステップ１０１）。このプロセス生成コールバックの登録について詳細には、図９のフローチャートに示している。その後、スタックレコーダを初期化し、メモリ領域を確保する（ステップ１０２）。そして、監視対象スレッドのスレッド生成イベントのフック設定を行う（ステップ１０３）。それから、実行命令のトレースを開始する。
プロセス生成コールバックの登録は、ＯＳが提供するＰｓＳｅｔＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ（）を呼び出し、プロセス起動時に呼び出されるコールバック関数（ＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ）を登録して行われる。このコールバック関数は、次のプロトタイプで定義される。【００５０】
2005024630.tif 000002
【００５１】  次に、図９のフローチャートには、プロセス生成コールバックの登録の手順を示している。プロセスが生成されるとＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ関数が呼び出される（ステップ１１０）。以下、ＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅ内での動作を示す。監視する対象のプロセスかを判定する（ステップ１１１）。この判定のときは、ＬｏａｄＩｍａｇｅＮｏｔｉｆｙＲｏｕｔｉｎｅの引数ＦｕｌｌＩｍａｇｅＮａｍｅに、対象となるプロセスモジュール名が存在するかどうかを調べる。存在していた場合は次の処理に移る（はい）。
プロセスモジュールのエントリポイントアドレスの取得する（ステップ１１２）。Ｗｉｎｄｏｗｓで使用される実行モジュールファイルの先頭部分（ヘッダ）を調査し、最初に実行される関数（エントリポイント）のアドレスを取得する。そして、エントリポイントに、ブレークポイントを設置する（ステップ１１３）。このときのプログラムコードの例は次の通りである。【００５２】
2005024630.tif 000003
【００５３】  そして、ＩＡ−３２命令のトレース機能を有効にして、トレースコールバック関数（ＡＳＯ＿Ｈｏｏｋ＿ＩＮＴ０１Ｈ）の登録のためにＩＤＴ（割り込みディスクリプタテーブル）の０１Ｈを書き換える（ステップ１１４）。この登録のためのプログラムコードは以下の通りである。【００５４】
2005024630.tif 000004
【００５５】  プロセスが起動した時に最初に実行される命令にハードウェアブレークポイントを設定し、実行された際にトレースコールバック関数（ＡＳＯ＿Ｈｏｏｋ＿ＩＮＴ０１Ｈ）が呼び出されるようにする（ステップ１１５）。このためのプログラムコードは以下の通りである。【００５６】
2005024630.tif 000005
【００５７】  スタックレコーダの初期化（ステップ１０２を参照）は、指定された監視対象のプロセスのスレッドが生成される度に動的に実施される。スタックレコーダの各スタックは、次のように定義される。【００５８】
2005024630.tif 000006
【００５９】  図１０のフローチャートには、スレッド生成イベントのフック設定（ステップ１０３を参照）の手順を示している。スレッドが生成される（ステップ１２０）と、監視する対象のプロセスか否かを判定する（ステップ１２１）。生成されたスレッドが監視する対象のプロセスのときは、＿ｂｅｇｉｎｔｈｒｅａｄ（）の開始アドレスを取得する（ステップ１２２）。この開始アドレスにブレークポイントを設置する（ステップ１２３）。それから、トレースを開始する（ステップ１２４）。
複数スレッドのシステムには、スレッドを生成するカーネルＡＰＩであるＮｔＣｒｅａｔｅＴｈｒｅａｄをフックすることで適用させている。そのため、ＮｔＣｒｅａｔｅＴｈｒｅａｄを呼び出す際に経由されるベクタ２Ｅの割り込みハンドラ（ＡＳＯ＿Ｈｏｏｋ＿ＩＮＴ２ＥＨ）を書き換える。このときのプログラムコードは次のようになる。【００６０】
2005024630.tif 000007
【００６１】  スレッド生成イベント（ＣｒｅａｔｅＴｈｒｅａｄ（））のフック設定で使用されるプログラムコードは次のとおりである。【００６２】
2005024630.tif 000008
【００６３】  このように、一連の初期化処理が終了すると、プログラムが実行され、ＣＡＬＬ、ＲＥＴ等の分岐命令をトレースする。次に、トレースしているときの処理を、図１１、１２のフローチャートに示している。トレース処理が開始されると（ステップ１５０）、ＤＲ６のトレースフラッグをクリアして（ステップ１５１）、ＣＡＬＬ命令、ＲＥＴ命令を判別している。図１１、図１２の分岐判定のときは（ステップ１５４〜１８３）、ＣＡＬＬ、ＲＥＴ、ＲＥＴＮ命令を判別し、それぞれ「ＣＡＬＬ処理へ」、「ＲＥＴ処理へ」、「ＲＥＮＴ処理へ」となっている。「ＣＡＬＬ処理へ」、「ＲＥＴ処理へ」、「ＲＥＮＴ処理へ」は、それぞれ図１３、図１４、図１５のフローチャートに示している。
ＣＡＬＬ、ＲＥＴ、ＲＥＴＮ命令を判別するときのプログラムコードは、次のようになる。【００６４】
2005024630.tif 000009
【００６５】  ここでは、ＣＡＬＬ、ＲＥＴ、ＲＥＴＮの判別は、それぞれＣＡＬＬ＿ＦＯＵＮＤ、ＲＥＴ＿ＦＯＵＮＤ、ＲＥＴＮ＿ＦＯＵＮＤとしてコード化されている。プログラムコードの分岐命令にてＣＡＬＬ＿ＦＯＵＮＤにジャンプした場合、ＣＡＬＬ命令が実行されたと見なして、図１３のフローチャートに示す処理が行われる。ＲＥＴ、ＲＥＴＮの場合は同様である。
図１３には、ＣＡＬＬ命令が実行されるときの処理を示している。ＣＡＬＬ命令の実行が開始されると（ステップ２００）、ＣＡＬＬ命令に割り与えられたスタックメモリのスタックセグメント（ＣＳ）のアドレスを取得する（ステップ２０１）。そして、ＣＡＬＬ命令で格納されるリターンアドレスのスタックポイントを取得する（ステップ２０２）。その後、スタックメモリからリターンアドレスを取得する（ステップ２０３）。このときのプログラムコードは次のようになる。【００６６】
2005024630.tif 000010
【００６７】  この取得したリターンアドレスをスタックレコーダに登録する（ステップ２０４）。このときのプログラムコードは、次のようになる。【００６８】
2005024630.tif 000011
【００６９】  そして、ＭＳＲとＥＦＬＡＧを設定して命令トレースを再開する（ステップ２０５、２０６）。ＩＲＥＴＤにて処理を完了。
図１４には、ＲＥＴ命令が実行されるときの処理を示している。ＲＥＴ命令の実行が開始されると（ステップ２５０）、ＲＥＴ命令に割り与えられたスタックメモリのスタックセグメント（ＣＳ）のアドレスを取得する（ステップ２５１）。そして、ＲＥＴ命令で指定されたリターンアドレスのスタックポインタを取得する（ステップ２５２）。その後、スタックメモリからリターンアドレスを取得する（ステップ２５３）。このときのプログラムコードは次のようになる。【００７０】
2005024630.tif 000012
【００７１】  そして、スタックレコーダからリターンアドレスと同じ値があるかを検索する（ステップ２５４）。リターンアドレスは、このＲＥＴ命令に対応するＣＡＬＬ命令のときにスタックレコーダに登録されているものである。しかし、リターンアドレスが改ざんされた場合は、スタックレコーダの中から同じアドレスが見つからない。このときは、プロセス中断処理（次のコードのＴｅｒｍｉｎａｔｅ＿ＶｉｒｕｓＣｏｄｅ（））へ移る（ステップ２６０）。同じアドレスが見つかると、スタックレコーダから１レコードを削除（ステップ２５５）する。このときのプログラムコードは次のようになる。【００７２】
2005024630.tif 000013
【００７３】  そして、ＭＳＲとＥＦＬＡＧを設定して命令トレースを再開する（ステップ２５６、２５７）。ＩＲＥＴＤにて処理を完了。
図１５には、ＲＥＴＮ命令が実行されるときの処理を示している。ＲＥＴＮ命令の実行が開始されると（ステップ３００）、ＲＥＴＮ命令に割り与えられたスタックメモリのスタックセグメント（ＣＳ）のアドレスを取得する（ステップ３０１）。そして、ＲＥＴＮ命令で指定されたリターンアドレスのスタックポイントを取得する（ステップ３０２）。その後、スタックメモリからリターンアドレスを取得する（ステップ３０３）。このときのプログラムコードは次のようになる。【００７４】
2005024630.tif 000014
【００７５】  そして、スタックレコーダからリターンアドレスと同じ値があるかを検索する（ステップ３０４）。リターンアドレスは、このＲＥＴＮ命令に対応するＣＡＬＬ命令のときにスタックレコーダに登録されているものである。しかし、リターンアドレスが改ざんされた場合は、スタックレコーダの中から同じアドレスが見つからない。このときは、プロセス中断処理（次のコードのＴｅｒｍｉｎａｔｅ＿ＶｉｒｕｓＣｏｄｅ（））へ移る（ステップ３１０）。同じアドレスが見つかると、スタックレコーダから１レコードを削除（ステップ３０５）する。このときのプログラムコードは次のようになる。【００７６】
2005024630.tif 000015
【００７７】  そして、ＭＳＲとＥＦＬＡＧを設定して命令トレースを再開する（ステップ３０６、３０７）。ＩＲＥＴＤにて処理を完了。
図１６には、ＪＭＰ  ＥＳＰ処理が実行されるときの処理を示している。ＪＭＰ  ＥＳＰは、例えばネットワークを経由して侵入するウィルス等がスタックメモリ上のプログラムコードを実行するために必要な命令である。そのためスタックのリターンアドレスの検索結果に依存することなく、ＪＭＰＥＳＰ命令を使用する実行モジュールは稀であるため禁止対象としてある。ＪＭＰＥＳＰが判別すると、プロセス中断処理を行う（ステップ３５１）。
ステップ２６０、３１０、３５１のプロセス中断処理は、ＲＥＴ、ＲＥＴＮ命令の次に実行される命令のアドレスを取得し、そこを不正な命令（ＩＮＴ３等）に書き換える。プロセスの実行を継続させ、不正な命令でプロセスを停止させる。このときのプログラムコードは次のようになる。【００７８】
2005024630.tif 000016
【００７９】  上述したように、バッファオーバーフローを利用した不正侵入、攻撃はすべて把握し、対処することができる。実行しているプロセスを停止して、プログラムの暴走を止めることができる。
このような方法でバッファオーバーフローを実現可能な、すべてのオペレーティングシステムにも適応可能である。【００８０】  （その他の実施の形態）
【産業上の利用可能性】
【００８１】  本発明は、コンピュータウィルス対策、外部からの不正侵入の防止、セキュリティが要求される分野のすべてに利用される。特に、ネットワークに接続して利用されるパソコン、スーパーコンピュータ、サーバを利用したシステムに利用してよい。個人情報保護、電子ファイルのセキュリティが要求される電子政府、軍事、防衛関連のシステムに用いられる。
また、プログラムの欠陥、不正コードの利用を検知するとき利用すると良い。
【図面の簡単な説明】
【００８２】
【図１】図１は、本発明の概要を図示している概念図である。
【図２】図２は、本発明のバッファオーバーフローによるエラー検出を示す概念図である。
【図３】図３は、実行ファイルのロード時の手順を示すフローチャートである。
【図４】図４は、実行ファイルの実行時の手順を示すフローチャートである
【図５】図５は、メモリの構造を示す図である。
【図６】図６は、プログラムのメインルーチン、サブルーチンを例示した図ある。
【図７】図７は、スタックメモリの構造を示す図ある。
【図８】図８のは、ドライバウェアが起動するときの初期化処理の手順を示すフローチャートである。
【図９】図９は、プロセス生成コールバックの登録の手順を示すフローチャートである。
【図１０】図１０は、スレッド生成イベントのフック設定の手順を示しているフローチャートである。
【図１１】図１１は、ＣＡＬＬ、ＲＥＴ等の分岐命令をトレースしているときの処理の流れを示すフローチャートである。
【図１２】図１２は、図１１のＣＡＬＬｏｒＪＭＰ処理の処理手順を示すフローチャートである。
【図１３】図１３は、ＣＡＬＬ命令が実行されるときの処理を示すフローチャートである。
【図１４】図１４は、ＲＥＴ命令が実行されるときの処理を示すフローチャートである。
【図１５】図１５は、ＲＥＴ命令が実行されるときの処理を示すフローチャートである。
【図１６】図１６は、ＪＰＭ  ＥＳＰ処理の手順を示すフローチャートである。
【符号の説明】
【００８３】  １…ソフトウェア
２…ドライバウェア
３…ファイルシステムドライバ
４…ハードディスク
５…実行可能ファイル
６…メモリ
１０…ネットワークカード
１１…ＮＤＩＳ
１２…Ｗｉｎｓｏｃｋ
【図１】
2005024630.tif 000017
【図２】
2005024630.tif 000018
【図３】
2005024630.tif 000019
【図４】
2005024630.tif 000020
【図５】
2005024630.tif 000021
【図６】
2005024630.tif 000022
【図７】
2005024630.tif 000023
【図８】
2005024630.tif 000024
【図９】
2005024630.tif 000025
【図１０】
2005024630.tif 000026
【図１１】
2005024630.tif 000027
【図１２】
2005024630.tif 000028
【図１３】
2005024630.tif 000029
【図１４】
2005024630.tif 000030
【図１５】
2005024630.tif 000031
【図１６】
2005024630.tif 000032
【国際調査報告】
2005024630.tif 000033
2005024630.tif 000034
2005024630.tif 000035