情報機器、プログラム及び不正なプログラムコードの実行防止方法
【課題】バッファオーバーフローに関する不正アクセスを確実且つ容易に防止する。
【解決手段】メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器は、いずれかのプログラムコードの呼び出しをフックしてスタックレイアウトチェック処理を行う。スタックレイアウトチェック処理では、メモリに展開された各プログラムコードのリターンアドレスが順次取得され、各リターンアドレスが示すアドレスの属性情報に基づいてデータ処理が停止される。
【解決手段】メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器は、いずれかのプログラムコードの呼び出しをフックしてスタックレイアウトチェック処理を行う。スタックレイアウトチェック処理では、メモリに展開された各プログラムコードのリターンアドレスが順次取得され、各リターンアドレスが示すアドレスの属性情報に基づいてデータ処理が停止される。
【発明の詳細な説明】
【技術分野】
【0001】
本発明は、情報機器、プログラム及び不正なプログラムコードの実行防止方法に関する。
【背景技術】
【0002】
一般的に、PC(Personal Computer)やWS(Work Station)等の情報機器では、CPU(Central Processing Unit)などの制御部がRAM(Random Access Memory)等の記憶部の作業領域に展開されたプログラムコードを順次実行することで、各種データ処理を実行している。近年、上記情報機器においては、悪意のあるユーザによりプログラムコードの実行時に不正な操作が行われることで、データの盗みだしや改竄などの不正アクセスが発生している。
【0003】
通常、情報機器が管理するデータにはアクセス権限が設定されている。従って、データへのアクセス権限がなければ、不正アクセスが行われることはない。しかしながら、データへのアクセス権限がある通常のプログラムコードを利用し、不正な操作が実行された場合は、不正アクセスが可能となる。上述したプログラムコードを利用して不正アクセスを可能とする手法としては、プログラムコードの実行時のデータをRAM等に確保された所定領域からオーバーフローさせる、いわゆるバッファオーバーフローを用いた手法が知られている。
【0004】
ここで、バッファオーバーフローを用いた不正アクセスについて、正常にプログラムコードが実行された場合と、プログラムコードの実行時に不正が行われた場合と、を比較して詳細に説明する。
【0005】
先ず、図11、図12を参照して正常にプログラムコードが実行された場合を説明する。図11は、プログラムコードのソースコードを例示する概念図であり、図12は、プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【0006】
図11に例示されたソースコードによるプログラムコードは、main()関数から開始され、当該main()関数の中でstrcpy_helloworld()関数を呼び出している。このプログラムコードでは、strcpy_helloworld()関数の中で画面などに表示する「hello!」という文字列を用意し、main()関数のprintf()関数でそれを表示させている。関数とは、所定の機能をモジュール化してまとめたサブルーチンやサブプログラムなどであり、メインとなるプログラム内で随時呼び出すことができる。
【0007】
上記プログラムコードの実行時のデータは、RAM等に確保されたスタック領域に格納される。このスタック領域では、後入れ先出し (LIFO: Last In First Out; FILO: First In Last Out) 構造でデータが格納される。具体的には、図12に示すように、上から下に向かって順次確保された領域へプログラムコードの実行時のデータが格納される。
【0008】
例えば、図11に例示したソースコードによるプログラムコードの実行時には、main()関数を処理した際に、ReturnAddress1、ebp Backup、char Buf[8]などが1つのスタックフレームとして格納される。次いで、main()関数の中でstrcpy_helloworld()関数が呼び出された際に、ReturnAddress2、ebp Backup2、int iなどが一つのスタックフレームとして格納される。
【0009】
ReturnAddressは、プログラムの終了時に戻るべきアドレス値や、関数などによりサブプログラムが呼び出された場合の当該サブプログラム終了時に戻るべきアドレス値を示す。このReturnAddressは、プログラムの実行直後や関数などによりサブプログラムが呼び出された直後に、CPUにより自動的にスタック領域へ格納される。
【0010】
ebpは、CPUのレジスタの一種であり、現在使用している一時的なメモリ領域のアドレスの直前を示す。図12の例では、char Buf[8]、int iの前のアドレスであり、スタックフレームのReturnAddressが該当する。従って、スタックフレームにおいて、上記レジスタ値をebp Backupとしてバックアップすることで、当該スタックフレーム内の一領域を一時的なデータ(変数や配列等)を格納するメモリ領域として簡単に使用することが可能となる。
【0011】
char Buf[8]は、main()関数で使用される配列であるBufを格納する。このBufは、char型の変数(1バイト)を8個格納する配列であり、8バイト分のデータが格納可能となっている。int iは、strcpy_helloworld()関数で使用されるint型の変数であるiを格納する。
【0012】
従って、上記プログラムコードの実行により、スタック領域では、main()関数のスタックフレームが確保され、strcpy_helloworld()関数のスタックフレームが確保される。次いで、int iの値が順次インクリメントされて、「hello!」という6バイト分の文字列がchar Buf[8]に格納される。次いで、strcpy_helloworld()関数の終了により、ReturnAddress2が読み出されてmain()関数へ復帰され、main()関数の終了により、ReturnAddress1が読み出されてプログラムは正常終了する。
【0013】
次に、図13、図14を参照してプログラムコードの実行時に不正が行われた場合を説明する。図13は、プログラムコードのソースコードを例示する概念図であり、図14は、プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【0014】
図13に例示されたソースコードによるプログラムコードは、前述した図11と比較すればわかるとおり、配列bufへ「Hello World」という12バイト分(11文字+文字列終端)のデータを書き込んでいる。
【0015】
図14に示すように、スタック領域では、配列bufを格納する領域として8バイト分の領域が確保されている。従って、strcpy_helloworld()関数が実行された際には、確保されているサイズ以上のデータが書き込まれることとなる。このように、メモリに確保されているサイズ以上のデータが書き込まれることをバッファオーバーフローという。また、このバッファオーバーフローがスタック領域で起きる場合をスタックベースのバッファオーバーフローという。
【0016】
図14に例示したスタック領域おいて、領域の確保は上から下に向かって順次行われ、その確保された領域へのデータの書き込みは下から上に向かって行われる。従って、ReturnAddress1、ebp Backupはstrcpy_helloworld()関数が実行された際に、「Hello World」という12バイト分のデータにより不正に上書き(overwrite)される。上述した上書きにより、ReturnAddress1の内容が実行可能なプログラムコードが置いてあるアドレスに書き換えられた場合は、main()関数の終了によりReturnAddress1が読み出され、その書き換えられたプログラムコードが実行される。
【0017】
図13に例示したソースコードでは、「Hello World」という予め定義された文字列によりオーバーフローとなっている。しかしながら、実際には、メールサーバやWebサーバ等の通信ポートで受信されたデータや、コンソールやファイルから入力されたデータなどが配列bufに格納される場合もある。このような場合は、悪意のあるユーザにより通信、コンソール入力、ファイル入力などを介して任意のプログラムコードが実行され、データの盗みだしや改竄などの不正アクセスが発生する。
【0018】
上述した不正アクセスを防止するための有用な技術としては、特許文献1、2がある。特許文献1には、CPUが有するデバッグ機能を使用してプログラムの流れを随時チェックし、不正アクセスを防止することが開示されている。具体的には、プログラムコードにおける実行フローの妥当性をチェックし、妥当でない実行フローに遷移した場合、プログラムコードが攻撃を受けたものとして、その実行を停止もしくは修正する。また、特許文献2には、プログラムコードに随時バッファオーバーフロー検出のプログラムコードを挿入することが開示されている。
【特許文献1】国際公開番号WO2005/024630
【特許文献2】特開2001−216161号公報
【発明の開示】
【発明が解決しようとする課題】
【0019】
しかしながら、上記従来技術では、上述したバッファオーバーフローに関する不正アクセスの防止を十分に行うことができなかった。
【0020】
例えば、特許文献1では、実行フローの妥当性を定義する必要があるが、その定義は非常に難しい。不正なプログラムコードの実行による場合と正常なプログラムコードによる場合との差異を区別することは困難である。このため、不正アクセスを確実に防止するには十分ではなかった。さらに、この特許文献1に記載の技術を実装するには、CPUのデバック機能に依存する必要があり、パフォーマンスの低下を招く虞があった。
【0021】
また、特許文献2では、防御対象となるプログラムコードのソースコードが必要となる。従って、プログラムコードの開発元(提供元)が不正検出用のプログラムコードを挿入しなければならず、実質的に開発元が提供することでしか実施できない。
【0022】
本発明の課題は、上記従来技術の問題に鑑みてなされたものであり、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止する技術を提供することである。
【課題を解決するための手段】
【0023】
上記課題を解決するために、請求項1に記載の発明は、メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器であって、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記データ処理を停止させる停止手段と、
を備える。
【0024】
請求項2に記載の発明は、請求項1に記載の発明において、前記メモリは、各プログラムコードのリターンアドレスを格納するスタック領域を備え、
前記リターンアドレス取得手段は、前記スタック領域に格納されたリターンアドレスをトレースして取得する。
【0025】
請求項3に記載の発明は、請求項1又は2に記載の発明において、前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、プログラムコードを格納するコード領域を示す情報でない場合に、前記データ処理を停止させる。
【0026】
請求項4に記載の発明は、請求項1〜3のいずれか一項に記載の発明において、前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、データの書き込みが許可された領域を示す情報である場合に、前記データ処理を停止させる。
【0027】
請求項5に記載の発明は、メモリに展開された各プログラムコードを実行するコンピュータを、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる停止手段、
として機能させる。
【0028】
請求項6に記載の発明は、メモリに展開された各プログラムコードを実行するコンピュータにおける不正なプログラムコードの実行防止方法であって、
前記いずれかのプログラムコードの呼び出し時を検出し、当該検出されたプログラムコードの呼び出し時において、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得し、当該順次取得されたリターンアドレスが示すアドレスの属性情報を取得し、当該取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる。
【発明の効果】
【0029】
本発明によれば、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止することが可能となる。
【発明を実施するための最良の形態】
【0030】
以下、本発明の実施の形態について図を参照して説明するが、この発明の範囲は以下の実施の形態に限定されない。
【0031】
先ず、本実施の形態に係る情報機器の構成について、図1、図2を参照して説明する。図1は、情報機器1の機能的構成を模式的に示すブロック図である。図2は、RAM30のスタック領域を例示する概念図である。
【0032】
図1に示すように、情報機器1は、CPU10、記憶部20、RAM30、操作部40、表示部50、I/F部60を有する。上記情報機器1の各部はバス70により電気的に接続されている。具体的には、情報機器1は、PC、WS、PDA(Personal Digital Assistant)、携帯電話などであってよい。
【0033】
CPU10は、情報機器1の動作を中央制御する。具体的には、CPU10は、記憶部20に記憶されたプログラムコードや各種データをRAM30の作業領域に展開し、当該RAM30に展開されたデータとの協働により各部へ制御信号を出力することで、上記中央制御を行う。
【0034】
記憶部20は、プログラムコードや各種設定情報などのデータをCPU10から読み書き可能に記憶する。例えば、記憶部20は、HDD(Hard Disk Drive)や半導体メモリなどであってよい。また、記憶部20は、上記データをROM(Read Only Memory)などに記憶する構成であってもよい。なお、記憶部20が記憶するプログラムコードとしては、OS(Operating System)などの基本的なソフトウエアの他、ベンダーが提供した各種アプリケーションプログラム、後述する処理に係るプログラムなどが含まれる。
【0035】
RAM30には、プログラムコードの実行時のデータを格納するスタック領域が確保される。具体的には、図2に示すようなスタック領域がRAM30の所定領域に確保される。このスタック領域では、スタックフレームごとにデータが格納される。一つのスタックフレームには、ReturnAddress、ebp Backup、プログラムコードの実行時に一時的に使われるデータ(変数や配列等)などのデータが格納される。
【0036】
ReturnAddressはプログラムコードの戻り先アドレスである。ebp Backupは一つ前のスタックフレームのebp Backupを示す。ebp Backupの直前にはReturnAddressがあるので、ebp Backupを辿ることでReturnAddressを順次トレースして取得することが可能となる。
【0037】
上記スタックフレームは、各プログラムコードが順次実行された場合に、そのプログラムコードの実行に伴って順次確保される。例えば、メインとなるプログラムコードが実行され、そのプログラムコード内でサブルーチンに関するプログラムコードが呼び出され、更に別のプログラムコードが呼び出された場合などは、図示したとおり、スタックフレームFr1〜Fr3の順に各プログラムコードに係る領域が確保される。この各プログラムコードに係る処理が終了した際には、スタックフレームFr1〜Fr3のReturnAddressが読み出されることで、メインとなるプログラムコードへの復帰や、プログラム終了後の処理が行われる。
【0038】
操作部40は、ユーザからの操作入力を受け付け、当該操作に応じた操作信号をCPU10へ出力する。例えば、操作部40は、文字入力キー、数字入力キー、その他各種機能に対応付けられたキーを備えたキーボード、マウス等のポインティングデバイスなどであってよい。
【0039】
表示部50は、CPU10から出力された表示制御信号に基づいた画像を表示画面に表示する。例えば、表示部50は、CRT(Cathode Ray Tube)、LCD(Liquid Crystal Display)などであってよい。
【0040】
I/F部60は、データ通信用IC(Integrated Circuit)や接続コネクタなどを備え(いずれも図示しない)、外部機器や通信ネットワークと通信可能に接続する。例えば、I/F部60は、USB(Universal Serial Bus)通信ポートや、LAN(Local Area Network)、WAN(Wide Area Network)、インターネットなどと接続するネットワークインターフェイスカード(NIC:Network Interface Card)であってよい。
【0041】
次に、情報機器1のCPU10の制御の下で実行される処理について、図3〜図10を参照して詳細に説明する。
【0042】
図3は、情報機器1のフック処理を示すフローチャートである。図4〜図6は、関数を動的に生成するためのソースコードを例示する概念図である。図7は、通常の関数呼び出しを例示する概念図である。図8は、フックされた関数呼び出しを例示する概念図である。図9は、情報機器1のスタックレイアウトチェック処理を示すフローチャートである。図10は、情報機器1のスタックレイアウトチェック処理の変形例を示すフローチャートである。
【0043】
情報機器1において、不正なプログラムコードの実行を防止するためには、当該不正なプログラムコードの実行に必要なAPI、ライブラリ関数、システムコールなどの検出、すなわち、サブプログラムコードの呼び出しを検出し、不正なプログラムコードの実行の有無をチェックする処理を挿入する必要がある。本実施の形態では、このサブプログラムコードの呼び出し検出と、不正のチェックを行う処理の挿入を、フック(Hook)を用いて実現している。
【0044】
フックは、プログラム中の特定の箇所に、利用者が独自の処理を追加できるようにする仕組みである。すなわち、フックされる側のプログラムコードを作成したプログラマーと、フックする側のプログラムコードを作成したプログラマーと、が同じプログラマーでなく、互いのプログラムコードに関するソースコードが同一のプログラマーにより作成されない場合に利用される仕組みである。従って、ベンダーが提供するOSや関数の機能変更や、任意の処理の追加時に使用される。
【0045】
なお、フックは、チェック対象となる関数などのサブプログラムをプログラマー自身が修正可能である場合であっても用いてよい。但し、プログラマー自身がサブプログラムを修正可能であり、当該サブプログラムが実行された際に不正のチェックを行うように修正した場合は、フックを使用する必要はなくなるとともに、既存の関数やライブラリをより安全なものとして実装することが可能となる。
【0046】
先ず、APIフック(ライブラリ関数をフック)して不正なプログラムコードの実行の有無をチェックする場合について図3〜図9を参照して説明する。
【0047】
以下では、ベンダーが用意したWinExec()というライブラリ関数のフックを例示し、当該ライブラリ関数が呼び出された際に実行されるスタックレイアウトチェック処理を例示している。
【0048】
図3に示すように、WinExec()というライブラリ関数が呼び出されることで、フック処理が開始されると、WinExec()の関数の存在するアドレスが取得される(ステップS1)。この関数のアドレス取得は、ベンダーから提供される関数を呼び出すことで可能である。
【0049】
次いで、APIの実行にフックをかける小さな関数(一時的な関数)が動的に生成される(ステップS2)。この動的に生成される関数とは、後述するスタックレイアウトチェック処理を呼び出す関数である。
【0050】
次いで、WinExec()関数の先頭コードの書き換えが行われ、ステップS2で生成された関数にジャンプするように変更される(ステップS3)。
【0051】
上述したAPIフック用の関数を動的に生成するためのソースコードを図4〜図6に例示する。図4に示すように、ソースコードC1は、フックターゲットのコードを定義する。図5に示すように、ソースコードC2は、実際に生成されるコードのテンプレートを出力するTrampolineStdcall_CodeHook()関数である。この関数の中で、0xccccccc1とある部分では、WinExec()関数のアドレスに5バイト加算したアドレスを入力する。また、5つあるnopとある部分では、コード書き換え前のオリジナルのWinExec()関数の先頭5バイトをそのままコピーする。
【0052】
図6に示すように、ソースコードC3は、BuildTrampolineCode_CodeHook()関数である。この関数により、TrampolineStdcall_CodeHook()関数の2つの書き換えが行われる。
【0053】
情報機器1では、上述したフック処理により、サブプログラムコードの呼び出しを検出し、不正のチェックを行う処理の挿入が可能となっている。通常、関数に係るサブプログラムが呼び出された場合は、図7に示すように、関数f1で呼び出された関数f2、f3や、関数f2で呼び出された関数f4がそのまま実行される。しかしながら、情報機器1では、図8に示すように、関数f1で関数f2が呼び出された場合、関数f2が呼び出される前にスタックレイアウトチェック処理を呼び出すフック関数f2aが実行される。
【0054】
図9に示すように、フック処理に次いで、スタックレイアウトチェック処理が開始されると、StackWolk()ライブラリの初期化が行われる(ステップS11)。StackWolk()ライブラリは、ベンダーが用意したスタックトレースを行う関数である。このStackWolk()を利用してトレース位置をインクリメント又はデクリメントすることで、スタック領域に格納されたリターンアドレスを順次取得することが可能となる。
【0055】
次いで、StackWolk()が呼び出されてスタック領域のスタックフレームを順次呼び出すように、スタックが1つバックトレースされ(ステップS12)、トレース後にリターンアドレスが正しく取得できたか否かが判定される(ステップS13)。
【0056】
ステップS13において、リターンアドレスが正しく取得できない場合は、正常終了としてチェック対象であるWinExec()の実行が続行される。これは不正アクセス以外の未知の理由などにより、スタックが破壊されており、StackWolk()が正常に動作しない場合等が該当する。なお、本実施の形態では、StackWolk()が正常に動作しない場合に正常終了しているが、このスタックトレースが失敗した場合にも、プログラムの停止や、ユーザに停止するか否かを確認するためのダイアログを表示部50へ表示してもよい。
【0057】
ステップS13において、リターンアドレスが正しく取得できた場合は、取得されたリターンアドレスが示すメモリ領域の属性情報が取得される(ステップS14)。この属性情報は、アドレスを指定することで当該アドレスの属性情報を出力する関数などが用いて取得される。
【0058】
次いで、ステップS13により取得された属性情報に基づいて、リターンアドレスが示すメモリ領域がコード領域であるか否かが判定される(ステップS15)。コード領域とは、プログラムコードが格納されるメモリ領域である。このステップS15において、コード領域であると判定された場合は、リターンアドレスが示すメモリ領域が書き込みが不可であるか否か(又は、書き込みが許可された領域であるか否か)が判定される(ステップS16)。
【0059】
ステップS16において、書き込みが不可な領域であると判定された場合は、未チェックのリターンアドレスが存在するか否かが判定され(ステップS17)、未チェックのリターンアドレスが存在する場合はステップS12へ戻って、次のリターンアドレスがトレースされる。また、ステップS17において、未チェックのリターンアドレスが存在しない場合は正常終了としてチェック対象であるWinExec()が実行される。
【0060】
ステップS15においてコード領域でない(データ領域である)と判定された場合、及び、ステップS16において書き込みが不可でない領域(書き込みが許可された領域)と判定された場合は、不正アクセス等の攻撃を検出し、不正なプログラムコードの実行を防止するためにデータ処理を一時的に停止する旨のダイアログが表示部50に表示され(ステップS18)、プログラムの実行が停止される(ステップS19)。
【0061】
不正なプログラムコードなどは、データを格納するデータ領域に一旦格納された後、バッファオーバーフローを利用して実行権限を有するプログラムコードによりデータ領域から実行される。従って、情報機器1では、ステップS15において、リターンアドレスが示すメモリ領域がコード領域でない(データ領域である)と判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0062】
また、不正なプログラムコードなどは、データを格納するデータ領域に一旦格納される必要があるため、データの書き込みが許可された領域に存在する。従って、情報機器1では、ステップS16において、リターンアドレスが示すメモリ領域が書き込みが許可された領域であると判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0063】
次に、変形例として、システムコールをフックして不正なプログラムコードの実行の有無をチェックする場合について図10を参照して説明する。
【0064】
図10では、何らかのシステムコールが呼び出された際に、カーネルからユーザランドのスタックをチェックするスタックレイアウトチェック処理を例示している。なお、このスタックレイアウチェック処理では、通常のebpを用いた方法でスタックトレースを行っている。
【0065】
スタックレイアウトチェック処理は、システムコールを処理しているカーネル内の関数をフックすることで、当該システムコール処理の前に実行される。このように、システムコールをフックすることで、スタックレイアウトチェック処理に関するプログラムコードをカーネルモジュールとして作成することが可能となり、カーネル本体のリビルドや改造を必要としない。
【0066】
従って、カーネルのソースコードが未公開の場合であっても実装可能である。また、ソースコードが提供されている場合であっても、カーネルの入れ替えをする必要がなく、カーネルモジュールをインストールするだけで実装可能である。
【0067】
図10に示すように、システムコールが呼び出されることで、スタックレイアウトチェック処理が開始されると、現在のebpの値から最新のebp backupが取得される(ステップS21)。すなわち、ステップS21では、RAM30のスタック領域における現在の読み出し位置が取得される。
【0068】
次いで、ebp backupからその直前にあるリターンアドレスが取得され(ステップS23)、リターンアドレスが正しく取得できたか否かが判定される(ステップS23)。ステップS23において、リターンアドレスが正しく取得できない場合は、前述したステップS13と同様に正常終了となり、呼び出されたシステムコードが実行される。
【0069】
ステップS23において、リターンアドレスが正しく取得できた場合は、そのリターンアドレスが含まれるスタックフレームがシグナル処理用のスタックフレームであるか否かが判定される(ステップS24)。このスタックフレームの判定は、予め用意されたライブラリ関数(例えばlibunwind関数)の出力結果などに基づいて行われる。
【0070】
ステップS24において、スタックフレームがシグナル処理用のスタックフレームであると判定された場合は、正常終了となり、呼び出されたシステムコードが実行される。シグナル処理とは、OSの種類や設定によって異なるが、シグナル処理の場合は、プログラムの実行方法が特殊になる場合があり、スタックフレームも特殊なレイアウトになる。したがって、誤検知を避けるために、シグナル処理の場合はチェックを中断し、常に正常終了としている。
【0071】
ステップS24において、スタックフレームがシグナル処理用のスタックフレームでないと判定された場合は、前述したステップS14〜S17と同様の処理が行われる(ステップS26〜S28)。なお、ステップS28において、未チェックのリターンアドレスが存在する場合は、ebp backupから次のebp backupが取得され(ステップS29)、ステップS22へ戻って、次のリターンアドレスが取得される。
【0072】
また、ステップS26においてコード領域でない(データ領域である)と判定された場合、及び、ステップS27において書き込みが不可でない領域(書き込みが許可された領域)と判定された場合は、ステップS18、S19と同様に、プログラムの実行が停止される(ステップS30、S31)。
【0073】
従って、情報機器1では、システムコールが呼び出された場合も、ステップS26において、リターンアドレスが示すメモリ領域がコード領域でない(データ領域である)と判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。同様に、情報機器1では、ステップS27において、リターンアドレスが示すメモリ領域が書き込みが許可された領域であると判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0074】
以上のように、情報機器1は、メモリ(RAM30)に展開された各プログラムコードと中央制御部(CPU10)との協働によりデータ処理を行う。また、情報機器1は、いずれかのプログラムコードの呼び出し時を検出する検出手段(CPU10、フック処理)と、検出手段により検出されたプログラムコードの呼び出し時に、メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段(CPU10、ステップS12、S22)と、検出手段により検出されたプログラムコードの呼び出し時に、リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段(CPU10、ステップS14、S25)と、検出手段により検出されたプログラムコードの呼び出し時に、属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいてデータ処理を停止させる停止手段(CPU10、ステップS19、S31)と、を備える。
【0075】
このため、情報機器1は、プログラムコードの呼び出し時において、メモリに展開された各プログラムコードのリターンアドレスを全てチェックして、データ処理の停止の有無を制御することができる。また、情報機器1は、各プログラムコードを改変する必要がない。従って、1は、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止することが可能となる。
【0076】
なお、上述した実施の形態における記述は、一例を示すものであり、これに限定するものではない。上述した実施の形態における構成及び動作に関しては、適宜変更が可能である。
【0077】
例えば、以上の説明では、本発明に係るプログラムのコンピュータ読み取り可能な媒体として記憶部20やROMを使用した例を開示したが、この例に限定されない。その他のコンピュータ読み取り可能な媒体として、フラッシュメモリ等の不揮発性メモリ、CD-ROM等の可搬型記録媒体を適用することが可能である。また、本発明に係るプログラムのデータをI/F部60と接続する通信回線を介して提供する媒体として、キャリアウエーブ(搬送波)も本発明に適用される。
【図面の簡単な説明】
【0078】
【図1】本実施の形態に係る情報機器の機能的構成を模式的に示すブロック図である。
【図2】RAMのスタック領域を例示する概念図である。
【図3】情報機器のフック処理を示すフローチャートである。
【図4】関数を動的に生成するためのソースコードを例示する概念図である。
【図5】関数を動的に生成するためのソースコードを例示する概念図である。
【図6】関数を動的に生成するためのソースコードを例示する概念図である。
【図7】通常の関数呼び出しを例示する概念図である。
【図8】フックされた関数呼び出しを例示する概念図である。
【図9】情報機器のスタックレイアウトチェック処理を示すフローチャートである。
【図10】情報機器のスタックレイアウトチェック処理の変形例を示すフローチャートである。
【図11】プログラムコードのソースコードを例示する概念図である。
【図12】プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【図13】プログラムコードのソースコードを例示する概念図である。
【図14】プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【符号の説明】
【0079】
1 情報機器
10 CPU
20 記憶部
30 RAM
40 操作部
50 表示部
60 I/F部
70 バス
C1〜C3 ソースコード
Fr1〜Fr3 スタックフレーム
【技術分野】
【0001】
本発明は、情報機器、プログラム及び不正なプログラムコードの実行防止方法に関する。
【背景技術】
【0002】
一般的に、PC(Personal Computer)やWS(Work Station)等の情報機器では、CPU(Central Processing Unit)などの制御部がRAM(Random Access Memory)等の記憶部の作業領域に展開されたプログラムコードを順次実行することで、各種データ処理を実行している。近年、上記情報機器においては、悪意のあるユーザによりプログラムコードの実行時に不正な操作が行われることで、データの盗みだしや改竄などの不正アクセスが発生している。
【0003】
通常、情報機器が管理するデータにはアクセス権限が設定されている。従って、データへのアクセス権限がなければ、不正アクセスが行われることはない。しかしながら、データへのアクセス権限がある通常のプログラムコードを利用し、不正な操作が実行された場合は、不正アクセスが可能となる。上述したプログラムコードを利用して不正アクセスを可能とする手法としては、プログラムコードの実行時のデータをRAM等に確保された所定領域からオーバーフローさせる、いわゆるバッファオーバーフローを用いた手法が知られている。
【0004】
ここで、バッファオーバーフローを用いた不正アクセスについて、正常にプログラムコードが実行された場合と、プログラムコードの実行時に不正が行われた場合と、を比較して詳細に説明する。
【0005】
先ず、図11、図12を参照して正常にプログラムコードが実行された場合を説明する。図11は、プログラムコードのソースコードを例示する概念図であり、図12は、プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【0006】
図11に例示されたソースコードによるプログラムコードは、main()関数から開始され、当該main()関数の中でstrcpy_helloworld()関数を呼び出している。このプログラムコードでは、strcpy_helloworld()関数の中で画面などに表示する「hello!」という文字列を用意し、main()関数のprintf()関数でそれを表示させている。関数とは、所定の機能をモジュール化してまとめたサブルーチンやサブプログラムなどであり、メインとなるプログラム内で随時呼び出すことができる。
【0007】
上記プログラムコードの実行時のデータは、RAM等に確保されたスタック領域に格納される。このスタック領域では、後入れ先出し (LIFO: Last In First Out; FILO: First In Last Out) 構造でデータが格納される。具体的には、図12に示すように、上から下に向かって順次確保された領域へプログラムコードの実行時のデータが格納される。
【0008】
例えば、図11に例示したソースコードによるプログラムコードの実行時には、main()関数を処理した際に、ReturnAddress1、ebp Backup、char Buf[8]などが1つのスタックフレームとして格納される。次いで、main()関数の中でstrcpy_helloworld()関数が呼び出された際に、ReturnAddress2、ebp Backup2、int iなどが一つのスタックフレームとして格納される。
【0009】
ReturnAddressは、プログラムの終了時に戻るべきアドレス値や、関数などによりサブプログラムが呼び出された場合の当該サブプログラム終了時に戻るべきアドレス値を示す。このReturnAddressは、プログラムの実行直後や関数などによりサブプログラムが呼び出された直後に、CPUにより自動的にスタック領域へ格納される。
【0010】
ebpは、CPUのレジスタの一種であり、現在使用している一時的なメモリ領域のアドレスの直前を示す。図12の例では、char Buf[8]、int iの前のアドレスであり、スタックフレームのReturnAddressが該当する。従って、スタックフレームにおいて、上記レジスタ値をebp Backupとしてバックアップすることで、当該スタックフレーム内の一領域を一時的なデータ(変数や配列等)を格納するメモリ領域として簡単に使用することが可能となる。
【0011】
char Buf[8]は、main()関数で使用される配列であるBufを格納する。このBufは、char型の変数(1バイト)を8個格納する配列であり、8バイト分のデータが格納可能となっている。int iは、strcpy_helloworld()関数で使用されるint型の変数であるiを格納する。
【0012】
従って、上記プログラムコードの実行により、スタック領域では、main()関数のスタックフレームが確保され、strcpy_helloworld()関数のスタックフレームが確保される。次いで、int iの値が順次インクリメントされて、「hello!」という6バイト分の文字列がchar Buf[8]に格納される。次いで、strcpy_helloworld()関数の終了により、ReturnAddress2が読み出されてmain()関数へ復帰され、main()関数の終了により、ReturnAddress1が読み出されてプログラムは正常終了する。
【0013】
次に、図13、図14を参照してプログラムコードの実行時に不正が行われた場合を説明する。図13は、プログラムコードのソースコードを例示する概念図であり、図14は、プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【0014】
図13に例示されたソースコードによるプログラムコードは、前述した図11と比較すればわかるとおり、配列bufへ「Hello World」という12バイト分(11文字+文字列終端)のデータを書き込んでいる。
【0015】
図14に示すように、スタック領域では、配列bufを格納する領域として8バイト分の領域が確保されている。従って、strcpy_helloworld()関数が実行された際には、確保されているサイズ以上のデータが書き込まれることとなる。このように、メモリに確保されているサイズ以上のデータが書き込まれることをバッファオーバーフローという。また、このバッファオーバーフローがスタック領域で起きる場合をスタックベースのバッファオーバーフローという。
【0016】
図14に例示したスタック領域おいて、領域の確保は上から下に向かって順次行われ、その確保された領域へのデータの書き込みは下から上に向かって行われる。従って、ReturnAddress1、ebp Backupはstrcpy_helloworld()関数が実行された際に、「Hello World」という12バイト分のデータにより不正に上書き(overwrite)される。上述した上書きにより、ReturnAddress1の内容が実行可能なプログラムコードが置いてあるアドレスに書き換えられた場合は、main()関数の終了によりReturnAddress1が読み出され、その書き換えられたプログラムコードが実行される。
【0017】
図13に例示したソースコードでは、「Hello World」という予め定義された文字列によりオーバーフローとなっている。しかしながら、実際には、メールサーバやWebサーバ等の通信ポートで受信されたデータや、コンソールやファイルから入力されたデータなどが配列bufに格納される場合もある。このような場合は、悪意のあるユーザにより通信、コンソール入力、ファイル入力などを介して任意のプログラムコードが実行され、データの盗みだしや改竄などの不正アクセスが発生する。
【0018】
上述した不正アクセスを防止するための有用な技術としては、特許文献1、2がある。特許文献1には、CPUが有するデバッグ機能を使用してプログラムの流れを随時チェックし、不正アクセスを防止することが開示されている。具体的には、プログラムコードにおける実行フローの妥当性をチェックし、妥当でない実行フローに遷移した場合、プログラムコードが攻撃を受けたものとして、その実行を停止もしくは修正する。また、特許文献2には、プログラムコードに随時バッファオーバーフロー検出のプログラムコードを挿入することが開示されている。
【特許文献1】国際公開番号WO2005/024630
【特許文献2】特開2001−216161号公報
【発明の開示】
【発明が解決しようとする課題】
【0019】
しかしながら、上記従来技術では、上述したバッファオーバーフローに関する不正アクセスの防止を十分に行うことができなかった。
【0020】
例えば、特許文献1では、実行フローの妥当性を定義する必要があるが、その定義は非常に難しい。不正なプログラムコードの実行による場合と正常なプログラムコードによる場合との差異を区別することは困難である。このため、不正アクセスを確実に防止するには十分ではなかった。さらに、この特許文献1に記載の技術を実装するには、CPUのデバック機能に依存する必要があり、パフォーマンスの低下を招く虞があった。
【0021】
また、特許文献2では、防御対象となるプログラムコードのソースコードが必要となる。従って、プログラムコードの開発元(提供元)が不正検出用のプログラムコードを挿入しなければならず、実質的に開発元が提供することでしか実施できない。
【0022】
本発明の課題は、上記従来技術の問題に鑑みてなされたものであり、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止する技術を提供することである。
【課題を解決するための手段】
【0023】
上記課題を解決するために、請求項1に記載の発明は、メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器であって、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記データ処理を停止させる停止手段と、
を備える。
【0024】
請求項2に記載の発明は、請求項1に記載の発明において、前記メモリは、各プログラムコードのリターンアドレスを格納するスタック領域を備え、
前記リターンアドレス取得手段は、前記スタック領域に格納されたリターンアドレスをトレースして取得する。
【0025】
請求項3に記載の発明は、請求項1又は2に記載の発明において、前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、プログラムコードを格納するコード領域を示す情報でない場合に、前記データ処理を停止させる。
【0026】
請求項4に記載の発明は、請求項1〜3のいずれか一項に記載の発明において、前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、データの書き込みが許可された領域を示す情報である場合に、前記データ処理を停止させる。
【0027】
請求項5に記載の発明は、メモリに展開された各プログラムコードを実行するコンピュータを、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる停止手段、
として機能させる。
【0028】
請求項6に記載の発明は、メモリに展開された各プログラムコードを実行するコンピュータにおける不正なプログラムコードの実行防止方法であって、
前記いずれかのプログラムコードの呼び出し時を検出し、当該検出されたプログラムコードの呼び出し時において、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得し、当該順次取得されたリターンアドレスが示すアドレスの属性情報を取得し、当該取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる。
【発明の効果】
【0029】
本発明によれば、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止することが可能となる。
【発明を実施するための最良の形態】
【0030】
以下、本発明の実施の形態について図を参照して説明するが、この発明の範囲は以下の実施の形態に限定されない。
【0031】
先ず、本実施の形態に係る情報機器の構成について、図1、図2を参照して説明する。図1は、情報機器1の機能的構成を模式的に示すブロック図である。図2は、RAM30のスタック領域を例示する概念図である。
【0032】
図1に示すように、情報機器1は、CPU10、記憶部20、RAM30、操作部40、表示部50、I/F部60を有する。上記情報機器1の各部はバス70により電気的に接続されている。具体的には、情報機器1は、PC、WS、PDA(Personal Digital Assistant)、携帯電話などであってよい。
【0033】
CPU10は、情報機器1の動作を中央制御する。具体的には、CPU10は、記憶部20に記憶されたプログラムコードや各種データをRAM30の作業領域に展開し、当該RAM30に展開されたデータとの協働により各部へ制御信号を出力することで、上記中央制御を行う。
【0034】
記憶部20は、プログラムコードや各種設定情報などのデータをCPU10から読み書き可能に記憶する。例えば、記憶部20は、HDD(Hard Disk Drive)や半導体メモリなどであってよい。また、記憶部20は、上記データをROM(Read Only Memory)などに記憶する構成であってもよい。なお、記憶部20が記憶するプログラムコードとしては、OS(Operating System)などの基本的なソフトウエアの他、ベンダーが提供した各種アプリケーションプログラム、後述する処理に係るプログラムなどが含まれる。
【0035】
RAM30には、プログラムコードの実行時のデータを格納するスタック領域が確保される。具体的には、図2に示すようなスタック領域がRAM30の所定領域に確保される。このスタック領域では、スタックフレームごとにデータが格納される。一つのスタックフレームには、ReturnAddress、ebp Backup、プログラムコードの実行時に一時的に使われるデータ(変数や配列等)などのデータが格納される。
【0036】
ReturnAddressはプログラムコードの戻り先アドレスである。ebp Backupは一つ前のスタックフレームのebp Backupを示す。ebp Backupの直前にはReturnAddressがあるので、ebp Backupを辿ることでReturnAddressを順次トレースして取得することが可能となる。
【0037】
上記スタックフレームは、各プログラムコードが順次実行された場合に、そのプログラムコードの実行に伴って順次確保される。例えば、メインとなるプログラムコードが実行され、そのプログラムコード内でサブルーチンに関するプログラムコードが呼び出され、更に別のプログラムコードが呼び出された場合などは、図示したとおり、スタックフレームFr1〜Fr3の順に各プログラムコードに係る領域が確保される。この各プログラムコードに係る処理が終了した際には、スタックフレームFr1〜Fr3のReturnAddressが読み出されることで、メインとなるプログラムコードへの復帰や、プログラム終了後の処理が行われる。
【0038】
操作部40は、ユーザからの操作入力を受け付け、当該操作に応じた操作信号をCPU10へ出力する。例えば、操作部40は、文字入力キー、数字入力キー、その他各種機能に対応付けられたキーを備えたキーボード、マウス等のポインティングデバイスなどであってよい。
【0039】
表示部50は、CPU10から出力された表示制御信号に基づいた画像を表示画面に表示する。例えば、表示部50は、CRT(Cathode Ray Tube)、LCD(Liquid Crystal Display)などであってよい。
【0040】
I/F部60は、データ通信用IC(Integrated Circuit)や接続コネクタなどを備え(いずれも図示しない)、外部機器や通信ネットワークと通信可能に接続する。例えば、I/F部60は、USB(Universal Serial Bus)通信ポートや、LAN(Local Area Network)、WAN(Wide Area Network)、インターネットなどと接続するネットワークインターフェイスカード(NIC:Network Interface Card)であってよい。
【0041】
次に、情報機器1のCPU10の制御の下で実行される処理について、図3〜図10を参照して詳細に説明する。
【0042】
図3は、情報機器1のフック処理を示すフローチャートである。図4〜図6は、関数を動的に生成するためのソースコードを例示する概念図である。図7は、通常の関数呼び出しを例示する概念図である。図8は、フックされた関数呼び出しを例示する概念図である。図9は、情報機器1のスタックレイアウトチェック処理を示すフローチャートである。図10は、情報機器1のスタックレイアウトチェック処理の変形例を示すフローチャートである。
【0043】
情報機器1において、不正なプログラムコードの実行を防止するためには、当該不正なプログラムコードの実行に必要なAPI、ライブラリ関数、システムコールなどの検出、すなわち、サブプログラムコードの呼び出しを検出し、不正なプログラムコードの実行の有無をチェックする処理を挿入する必要がある。本実施の形態では、このサブプログラムコードの呼び出し検出と、不正のチェックを行う処理の挿入を、フック(Hook)を用いて実現している。
【0044】
フックは、プログラム中の特定の箇所に、利用者が独自の処理を追加できるようにする仕組みである。すなわち、フックされる側のプログラムコードを作成したプログラマーと、フックする側のプログラムコードを作成したプログラマーと、が同じプログラマーでなく、互いのプログラムコードに関するソースコードが同一のプログラマーにより作成されない場合に利用される仕組みである。従って、ベンダーが提供するOSや関数の機能変更や、任意の処理の追加時に使用される。
【0045】
なお、フックは、チェック対象となる関数などのサブプログラムをプログラマー自身が修正可能である場合であっても用いてよい。但し、プログラマー自身がサブプログラムを修正可能であり、当該サブプログラムが実行された際に不正のチェックを行うように修正した場合は、フックを使用する必要はなくなるとともに、既存の関数やライブラリをより安全なものとして実装することが可能となる。
【0046】
先ず、APIフック(ライブラリ関数をフック)して不正なプログラムコードの実行の有無をチェックする場合について図3〜図9を参照して説明する。
【0047】
以下では、ベンダーが用意したWinExec()というライブラリ関数のフックを例示し、当該ライブラリ関数が呼び出された際に実行されるスタックレイアウトチェック処理を例示している。
【0048】
図3に示すように、WinExec()というライブラリ関数が呼び出されることで、フック処理が開始されると、WinExec()の関数の存在するアドレスが取得される(ステップS1)。この関数のアドレス取得は、ベンダーから提供される関数を呼び出すことで可能である。
【0049】
次いで、APIの実行にフックをかける小さな関数(一時的な関数)が動的に生成される(ステップS2)。この動的に生成される関数とは、後述するスタックレイアウトチェック処理を呼び出す関数である。
【0050】
次いで、WinExec()関数の先頭コードの書き換えが行われ、ステップS2で生成された関数にジャンプするように変更される(ステップS3)。
【0051】
上述したAPIフック用の関数を動的に生成するためのソースコードを図4〜図6に例示する。図4に示すように、ソースコードC1は、フックターゲットのコードを定義する。図5に示すように、ソースコードC2は、実際に生成されるコードのテンプレートを出力するTrampolineStdcall_CodeHook()関数である。この関数の中で、0xccccccc1とある部分では、WinExec()関数のアドレスに5バイト加算したアドレスを入力する。また、5つあるnopとある部分では、コード書き換え前のオリジナルのWinExec()関数の先頭5バイトをそのままコピーする。
【0052】
図6に示すように、ソースコードC3は、BuildTrampolineCode_CodeHook()関数である。この関数により、TrampolineStdcall_CodeHook()関数の2つの書き換えが行われる。
【0053】
情報機器1では、上述したフック処理により、サブプログラムコードの呼び出しを検出し、不正のチェックを行う処理の挿入が可能となっている。通常、関数に係るサブプログラムが呼び出された場合は、図7に示すように、関数f1で呼び出された関数f2、f3や、関数f2で呼び出された関数f4がそのまま実行される。しかしながら、情報機器1では、図8に示すように、関数f1で関数f2が呼び出された場合、関数f2が呼び出される前にスタックレイアウトチェック処理を呼び出すフック関数f2aが実行される。
【0054】
図9に示すように、フック処理に次いで、スタックレイアウトチェック処理が開始されると、StackWolk()ライブラリの初期化が行われる(ステップS11)。StackWolk()ライブラリは、ベンダーが用意したスタックトレースを行う関数である。このStackWolk()を利用してトレース位置をインクリメント又はデクリメントすることで、スタック領域に格納されたリターンアドレスを順次取得することが可能となる。
【0055】
次いで、StackWolk()が呼び出されてスタック領域のスタックフレームを順次呼び出すように、スタックが1つバックトレースされ(ステップS12)、トレース後にリターンアドレスが正しく取得できたか否かが判定される(ステップS13)。
【0056】
ステップS13において、リターンアドレスが正しく取得できない場合は、正常終了としてチェック対象であるWinExec()の実行が続行される。これは不正アクセス以外の未知の理由などにより、スタックが破壊されており、StackWolk()が正常に動作しない場合等が該当する。なお、本実施の形態では、StackWolk()が正常に動作しない場合に正常終了しているが、このスタックトレースが失敗した場合にも、プログラムの停止や、ユーザに停止するか否かを確認するためのダイアログを表示部50へ表示してもよい。
【0057】
ステップS13において、リターンアドレスが正しく取得できた場合は、取得されたリターンアドレスが示すメモリ領域の属性情報が取得される(ステップS14)。この属性情報は、アドレスを指定することで当該アドレスの属性情報を出力する関数などが用いて取得される。
【0058】
次いで、ステップS13により取得された属性情報に基づいて、リターンアドレスが示すメモリ領域がコード領域であるか否かが判定される(ステップS15)。コード領域とは、プログラムコードが格納されるメモリ領域である。このステップS15において、コード領域であると判定された場合は、リターンアドレスが示すメモリ領域が書き込みが不可であるか否か(又は、書き込みが許可された領域であるか否か)が判定される(ステップS16)。
【0059】
ステップS16において、書き込みが不可な領域であると判定された場合は、未チェックのリターンアドレスが存在するか否かが判定され(ステップS17)、未チェックのリターンアドレスが存在する場合はステップS12へ戻って、次のリターンアドレスがトレースされる。また、ステップS17において、未チェックのリターンアドレスが存在しない場合は正常終了としてチェック対象であるWinExec()が実行される。
【0060】
ステップS15においてコード領域でない(データ領域である)と判定された場合、及び、ステップS16において書き込みが不可でない領域(書き込みが許可された領域)と判定された場合は、不正アクセス等の攻撃を検出し、不正なプログラムコードの実行を防止するためにデータ処理を一時的に停止する旨のダイアログが表示部50に表示され(ステップS18)、プログラムの実行が停止される(ステップS19)。
【0061】
不正なプログラムコードなどは、データを格納するデータ領域に一旦格納された後、バッファオーバーフローを利用して実行権限を有するプログラムコードによりデータ領域から実行される。従って、情報機器1では、ステップS15において、リターンアドレスが示すメモリ領域がコード領域でない(データ領域である)と判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0062】
また、不正なプログラムコードなどは、データを格納するデータ領域に一旦格納される必要があるため、データの書き込みが許可された領域に存在する。従って、情報機器1では、ステップS16において、リターンアドレスが示すメモリ領域が書き込みが許可された領域であると判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0063】
次に、変形例として、システムコールをフックして不正なプログラムコードの実行の有無をチェックする場合について図10を参照して説明する。
【0064】
図10では、何らかのシステムコールが呼び出された際に、カーネルからユーザランドのスタックをチェックするスタックレイアウトチェック処理を例示している。なお、このスタックレイアウチェック処理では、通常のebpを用いた方法でスタックトレースを行っている。
【0065】
スタックレイアウトチェック処理は、システムコールを処理しているカーネル内の関数をフックすることで、当該システムコール処理の前に実行される。このように、システムコールをフックすることで、スタックレイアウトチェック処理に関するプログラムコードをカーネルモジュールとして作成することが可能となり、カーネル本体のリビルドや改造を必要としない。
【0066】
従って、カーネルのソースコードが未公開の場合であっても実装可能である。また、ソースコードが提供されている場合であっても、カーネルの入れ替えをする必要がなく、カーネルモジュールをインストールするだけで実装可能である。
【0067】
図10に示すように、システムコールが呼び出されることで、スタックレイアウトチェック処理が開始されると、現在のebpの値から最新のebp backupが取得される(ステップS21)。すなわち、ステップS21では、RAM30のスタック領域における現在の読み出し位置が取得される。
【0068】
次いで、ebp backupからその直前にあるリターンアドレスが取得され(ステップS23)、リターンアドレスが正しく取得できたか否かが判定される(ステップS23)。ステップS23において、リターンアドレスが正しく取得できない場合は、前述したステップS13と同様に正常終了となり、呼び出されたシステムコードが実行される。
【0069】
ステップS23において、リターンアドレスが正しく取得できた場合は、そのリターンアドレスが含まれるスタックフレームがシグナル処理用のスタックフレームであるか否かが判定される(ステップS24)。このスタックフレームの判定は、予め用意されたライブラリ関数(例えばlibunwind関数)の出力結果などに基づいて行われる。
【0070】
ステップS24において、スタックフレームがシグナル処理用のスタックフレームであると判定された場合は、正常終了となり、呼び出されたシステムコードが実行される。シグナル処理とは、OSの種類や設定によって異なるが、シグナル処理の場合は、プログラムの実行方法が特殊になる場合があり、スタックフレームも特殊なレイアウトになる。したがって、誤検知を避けるために、シグナル処理の場合はチェックを中断し、常に正常終了としている。
【0071】
ステップS24において、スタックフレームがシグナル処理用のスタックフレームでないと判定された場合は、前述したステップS14〜S17と同様の処理が行われる(ステップS26〜S28)。なお、ステップS28において、未チェックのリターンアドレスが存在する場合は、ebp backupから次のebp backupが取得され(ステップS29)、ステップS22へ戻って、次のリターンアドレスが取得される。
【0072】
また、ステップS26においてコード領域でない(データ領域である)と判定された場合、及び、ステップS27において書き込みが不可でない領域(書き込みが許可された領域)と判定された場合は、ステップS18、S19と同様に、プログラムの実行が停止される(ステップS30、S31)。
【0073】
従って、情報機器1では、システムコールが呼び出された場合も、ステップS26において、リターンアドレスが示すメモリ領域がコード領域でない(データ領域である)と判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。同様に、情報機器1では、ステップS27において、リターンアドレスが示すメモリ領域が書き込みが許可された領域であると判定された場合にプログラムの実行が停止されるため、不正なプログラムコードの実行を防止することが可能となる。
【0074】
以上のように、情報機器1は、メモリ(RAM30)に展開された各プログラムコードと中央制御部(CPU10)との協働によりデータ処理を行う。また、情報機器1は、いずれかのプログラムコードの呼び出し時を検出する検出手段(CPU10、フック処理)と、検出手段により検出されたプログラムコードの呼び出し時に、メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段(CPU10、ステップS12、S22)と、検出手段により検出されたプログラムコードの呼び出し時に、リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段(CPU10、ステップS14、S25)と、検出手段により検出されたプログラムコードの呼び出し時に、属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいてデータ処理を停止させる停止手段(CPU10、ステップS19、S31)と、を備える。
【0075】
このため、情報機器1は、プログラムコードの呼び出し時において、メモリに展開された各プログラムコードのリターンアドレスを全てチェックして、データ処理の停止の有無を制御することができる。また、情報機器1は、各プログラムコードを改変する必要がない。従って、1は、バッファオーバーフローに関する不正アクセスを確実且つ容易に防止することが可能となる。
【0076】
なお、上述した実施の形態における記述は、一例を示すものであり、これに限定するものではない。上述した実施の形態における構成及び動作に関しては、適宜変更が可能である。
【0077】
例えば、以上の説明では、本発明に係るプログラムのコンピュータ読み取り可能な媒体として記憶部20やROMを使用した例を開示したが、この例に限定されない。その他のコンピュータ読み取り可能な媒体として、フラッシュメモリ等の不揮発性メモリ、CD-ROM等の可搬型記録媒体を適用することが可能である。また、本発明に係るプログラムのデータをI/F部60と接続する通信回線を介して提供する媒体として、キャリアウエーブ(搬送波)も本発明に適用される。
【図面の簡単な説明】
【0078】
【図1】本実施の形態に係る情報機器の機能的構成を模式的に示すブロック図である。
【図2】RAMのスタック領域を例示する概念図である。
【図3】情報機器のフック処理を示すフローチャートである。
【図4】関数を動的に生成するためのソースコードを例示する概念図である。
【図5】関数を動的に生成するためのソースコードを例示する概念図である。
【図6】関数を動的に生成するためのソースコードを例示する概念図である。
【図7】通常の関数呼び出しを例示する概念図である。
【図8】フックされた関数呼び出しを例示する概念図である。
【図9】情報機器のスタックレイアウトチェック処理を示すフローチャートである。
【図10】情報機器のスタックレイアウトチェック処理の変形例を示すフローチャートである。
【図11】プログラムコードのソースコードを例示する概念図である。
【図12】プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【図13】プログラムコードのソースコードを例示する概念図である。
【図14】プログラムコード実行時におけるスタック領域の概要を例示する概念図である。
【符号の説明】
【0079】
1 情報機器
10 CPU
20 記憶部
30 RAM
40 操作部
50 表示部
60 I/F部
70 バス
C1〜C3 ソースコード
Fr1〜Fr3 スタックフレーム
【特許請求の範囲】
【請求項1】
メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器であって、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記データ処理を停止させる停止手段と、
を備える情報機器。
【請求項2】
前記メモリは、各プログラムコードのリターンアドレスを格納するスタック領域を備え、
前記リターンアドレス取得手段は、前記スタック領域に格納されたリターンアドレスをトレースして取得する請求項1に記載の情報機器。
【請求項3】
前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、プログラムコードを格納するコード領域を示す情報でない場合に、前記データ処理を停止させる請求項1又は2に記載の情報機器。
【請求項4】
前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、データの書き込みが許可された領域を示す情報である場合に、前記データ処理を停止させる請求項1〜3のいずれか一項に記載の情報機器。
【請求項5】
メモリに展開された各プログラムコードを実行するコンピュータを、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる停止手段、
として機能させるためのプログラム。
【請求項6】
メモリに展開された各プログラムコードを実行するコンピュータにおける不正なプログラムコードの実行防止方法であって、
前記いずれかのプログラムコードの呼び出し時を検出し、当該検出されたプログラムコードの呼び出し時において、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得し、当該順次取得されたリターンアドレスが示すアドレスの属性情報を取得し、当該取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる不正なプログラムコードの実行防止方法。
【請求項1】
メモリに展開された各プログラムコードと中央制御部との協働によりデータ処理を行う情報機器であって、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段と、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記データ処理を停止させる停止手段と、
を備える情報機器。
【請求項2】
前記メモリは、各プログラムコードのリターンアドレスを格納するスタック領域を備え、
前記リターンアドレス取得手段は、前記スタック領域に格納されたリターンアドレスをトレースして取得する請求項1に記載の情報機器。
【請求項3】
前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、プログラムコードを格納するコード領域を示す情報でない場合に、前記データ処理を停止させる請求項1又は2に記載の情報機器。
【請求項4】
前記停止手段は、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報が、データの書き込みが許可された領域を示す情報である場合に、前記データ処理を停止させる請求項1〜3のいずれか一項に記載の情報機器。
【請求項5】
メモリに展開された各プログラムコードを実行するコンピュータを、
前記いずれかのプログラムコードの呼び出し時を検出する検出手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得するリターンアドレス取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記リターンアドレス取得手段により順次取得されたリターンアドレスが示すアドレスの属性情報を取得する属性取得手段、
前記検出手段により検出されたプログラムコードの呼び出し時に、前記属性取得手段により取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる停止手段、
として機能させるためのプログラム。
【請求項6】
メモリに展開された各プログラムコードを実行するコンピュータにおける不正なプログラムコードの実行防止方法であって、
前記いずれかのプログラムコードの呼び出し時を検出し、当該検出されたプログラムコードの呼び出し時において、前記メモリに展開された各プログラムコードのリターンアドレスを順次取得し、当該順次取得されたリターンアドレスが示すアドレスの属性情報を取得し、当該取得された各リターンアドレスが示すアドレスの属性情報に基づいて前記各プログラムコードによるデータ処理を停止させる不正なプログラムコードの実行防止方法。
【図1】
【図2】
【図3】
【図4】
【図5】
【図6】
【図7】
【図8】
【図9】
【図10】
【図11】
【図12】
【図13】
【図14】
【図2】
【図3】
【図4】
【図5】
【図6】
【図7】
【図8】
【図9】
【図10】
【図11】
【図12】
【図13】
【図14】
【公開番号】特開2009−199529(P2009−199529A)
【公開日】平成21年9月3日(2009.9.3)
【国際特許分類】
【出願番号】特願2008−43003(P2008−43003)
【出願日】平成20年2月25日(2008.2.25)
【出願人】(507351506)株式会社フォティーンフォティ技術研究所 (4)
【Fターム(参考)】
【公開日】平成21年9月3日(2009.9.3)
【国際特許分類】
【出願日】平成20年2月25日(2008.2.25)
【出願人】(507351506)株式会社フォティーンフォティ技術研究所 (4)
【Fターム(参考)】
[ Back to top ]