(57)【要約】【課題】  コンピュータの不正利用の発生要因に、戻り番地の書換えがある。戻り番地はプログラムの制御にかかわる情報である。攻撃者が、戻り番地の書換えに成功した場合、プログラムは手続きから返戻する動作を実行する際に、書き換えられたアドレスにジャンプし、攻撃者の意図した不正な動作を実行してしまう。【解決手段】  手続き呼出しの実現において、呼出元から呼出先に戻り番地を渡すことを止め、代わりに戻り番地ＩＤを引き渡すことにする。戻り番地ＩＤとは、戻り番地を記録する表である戻り番地表を検索するための番号である。返戻の際には、戻り番地ＩＤが有効か調べ、有効ならば、戻り番地表から戻り番地ＩＤに対応する戻り番地を求め、求めた戻り番地にジャンプする。有効でないならば、割込みの発生により管理者に異常の発生を通知する。以上により、返戻の際のジャンプ先を戻り番地表に登録してあるアドレスのみに制限し、攻撃を抑止できる。【選択図】  図５
2006048257.tif 000002
【特許請求の範囲】
【請求項１】
言語処理系において、入力プログラムのコンパイルにあたり、表Tを作成する手段と、入力プログラム中にある手続呼出しのコンパイルにあたり、コンパイル対象の手続呼出しにおける戻り番地Rを表Tに登録する手段と、手続呼出しのコンパイル済コードの中に、表Tにおける、戻り番地Rの登録先を特定する情報を呼出先に渡すコードをプロセッサが出力する第一の出力手段と、入力プログラム中にある、手続きからの返戻のコンパイルにあたり、呼出元から受け取った、登録先を特定する情報に対応する戻り番地が表Tに登録されているか調べ、登録されているならば、該戻り番地にジャンプするコードをプロセッサが出力する第二の出力手段をもつことを特徴とするプログラムコードの生成方法。
【請求項２】
請求項１において、表Tを、実行時に、プロセッサが、書込不可の領域に配置する手段をもつことを特徴とする方法。
【請求項３】
請求項１に記載の方法を用いる言語処理系。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソフトウェアの一種である言語処理系に関する。
【背景技術】
【０００２】
本発明の目的は、コンピュータシステムを不正な利用から守ることにある。コンピュータシステムを不正に利用しようと試みる者（攻撃者）が、コンピュータに任意の動作を実行させる手順の例を示す。
【０００３】
攻撃者はコンピュータシステム上で動作しているソフトウェアに対して、攻撃のための入力を与える。このとき、入力先のソフトウェアに脆弱性（欠陥）があると、ソフトウェアの設計者が想定しなかった記憶領域を書き換えられる。攻撃者は、この書き換えによって、戻り番地など、コンピュータの制御に関する情報を書き換えるよう、ソフトウェアに与える入力に細工する。戻り番地とは、手続呼出しの終了後に継続して実行すべきコードの番地である。一般的な言語処理系における手続呼出しの実現では、手続呼出しのコンパイル済コードの中に、戻り番地を呼出先に渡すコードを出力し、また、呼出先の手続きからの返戻に対応するコードとして、呼出元から受け取った戻り番地にジャンプするコードを出力する（図１、非特許文献１ I-3頁参照）。攻撃者が戻り番地を任意の値に書き換えることに成功すると、コンピュータは、手続呼出しが終了した後に、本来の戻り番地（書き換え前の戻り番地）とは異なる、書き換えられた番地にジャンプし、攻撃者が望む任意の動作を実行してしまう。
【０００４】
たとえば図１では、呼出元のコードが１〜２行目にあり、２行目にある分岐命令ｂｌが、戻り番地を、レジスタＬＲに格納して呼出先に渡す。そして、４〜１２行目にある呼出先では、まず、６〜７行目でレジスタＬＲの値をスタックフレームに退避する。この時点における実行時スタックの内容を図２に示す。図２では実行時スタックに呼出先のスタックフレームが確保されており、その中に戻り番地が退避されている。図１に戻り、６〜７行目の実行に続いて、呼出先の手続き本体の実行が始まる。呼出先本体の実行中に、攻撃者からの入力をうけとると、図２の呼出先のスタックフレームに退避した戻り番地が書き換えられることがある。図１に戻り、呼出先の手続き本体の実行が終了し、８行目に到達したら、呼出元へ返戻するためのコードを実行する。具体的には、９〜１０行目でスタックフレームから戻り番地をレジスタＬＲに復帰し、最後に１２行目のｂｃｌｒ命令で、レジスタＬＲが指示するアドレスにジャンプする。ここで呼出先の手続き本体の実行中に、攻撃者によって、スタックフレームに退避していた戻り番地を書き換えられた場合、１２行目のｂｃｌｒ命令から、書き換えられたアドレスにジャンプしてしまう。
【０００５】
攻撃者による書換えから戻り番地を保護する従来技術として、戻り番地の退避先の近傍に特定の値ｃを保存し、返戻時に、保存しておいた特定の値ｃが書き換えられていないか検査する方法がある（非特許文献２参照）。この方法で検出可能な攻撃は、戻り番地の退避先だけでなく、その近傍も書き換えるものであり、たとえば戻り番地のみ書き換える攻撃は検知できない。
【０００６】
戻り番地のみ書き換える攻撃を検知する従来技術として、予備の戻り番地を（暗号化して）記録しておき、返戻時に、戻り番地と、予備の戻り番地が一致するか検査する方法がある（非特許文献２参照）。この方法も完璧でなく、戻り番地と、予備の戻り番地をまとめて書き換える攻撃を検知できない。
【０００７】
【非特許文献１】Gerry Kane: PA-RISC 2.0 ARCHITECTURE, Prentice Hall (1996). ISBN 0-13-182734-0
【非特許文献２】Wagle, P. and Cowan, C.: Stack Guard: Simple Buffer Overflow Protection for GCC, Proceedings of the First Annual GCC Developers' Summit, pp. 243-256 (2003).
【発明の開示】
【発明が解決しようとする課題】
【０００８】
攻撃者によって、呼出元が引数として渡した戻り番地が書き換えられ、呼出先から戻る際に、書き換えられた番地にジャンプすることを防ぐ。
【課題を解決するための手段】
【０００９】
戻り番地の書き換えを不可能にするために、本発明の言語処理系は、戻り番地表と呼ぶ表を作成して、戻り番地を登録する。さらに、攻撃者による戻り番地表の書換えを防ぐために、戻り番地表を実行時に書込不可のメモリ領域に配置する。さらに、本発明の言語処理系は、手続呼出しの呼出元に対応するコードの中に、戻り番地ＩＤを呼出先に引き渡すコードを出力する。ここで戻り番地ＩＤとは、該呼出元における戻り番地の、戻り番地表における登録先を特定するための情報を表す。また、本発明の言語処理系は、手続き呼出しからの返戻に対応するコードとして、呼出元から受け取った戻り番地ＩＤに対応する戻り番地が、戻り番地表に登録されているか調べ、登録されていたならば、該戻り番地にジャンプし、さもなくば、呼出元から受け取った戻り番地ＩＤが、攻撃者によって書き換えられたとみなし、プロセスを強制終了させるなどの措置をとるコードを出力する。
【発明の効果】
【００１０】
本発明の言語処理系が出力するコードによってプログラムの実行をおこなえば、攻撃者が返戻のコードを使ってコンピュータの制御を奪い、コンピュータに任意の動作を実行させることが困難になる。なぜなら、本発明の言語処理系が出力する返戻のコードは、手続きからの戻り番地を、手続きの呼出元に後続する処理の番地のみに制限するので、返戻のコードを使って任意の番地にジャンプすることが困難になるからである。
【００１１】
本発明を適用した場合であっても、別の呼出元に後続する処理の番地にジャンプさせることは可能だが、一般に、異なる呼出元に無理に返戻させたとしても、プログラムの実行を継続することは困難であり、多くの場合、不正なメモリ参照などを実施してプログラムの実行が中断される。このような予期せぬ中断は、ソフトウェアの脆弱性を除去する上で役立つ。なぜなら、コンピュータシステムの管理者が、予期せぬ中断を契機として、ソフトウェアに脆弱性がないか調査を開始することが可能だからである。
【発明を実施するための最良の形態】
【００１２】
任意のプログラミング言語向けの言語処理系に本発明を適用し、戻り番地表を生成させ、また手続呼出しのコードとして本発明のコードを出力させる。
【実施例１】
【００１３】
本発明の適用対象である言語処理系が動作するコンピュータシステムの実施例を図３に示す。図３において、本発明の適用対象である言語処理系３０１は、ハードディスク３０２にインストールされており、実行時にバス３０３を通じて主記憶３０４に読み込まれ、プロセッサ３０５によって実行される。実行の過程で、言語処理系のプロセス３０６は、入力となるソースプログラム３０７を読み込み、コンパイルして、実行プログラム３０８として出力する。コンパイルの過程で、言語処理系のプロセス３０６は、主記憶３０４上に中間表現３０９、呼出元数表３１０、戻り番地表３１１、機械コードバッファ３１２といったデータ構造を生成、参照する。個々のデータ構造の役割については後述する。
【００１４】
本発明の適用対象である言語処理系の処理フローを図４に示す。図４の処理フローでは、まず処理４０１でソースプログラム３０７を中間表現３０９に変換し、次に処理４０２で中間表現３０９に最適化を適用し、最後に処理４０３で中間表現３０９を機械コードやデータに変換し、実行プログラム３０８として出力する。処理４０１の中にある処理４０４においては、個々の手続きに対して、呼出元の数を数えて呼出元数表３１０に記録する。関数ポインタ経由の手続き呼出しなど、呼出先が不定の手続き呼出しは、全手続きの呼出元として計算する。呼出元数表３１０は、処理４０３で本発明の戻り番地表３１１を生成する際に必要になる。
【００１５】
本発明を含む処理４０３の実施例を図５に示す。図５から判るように、処理４０３では、まず処理５０１で本発明の戻り番地表３１１を生成し、次に処理５０２で全ての中間表現３０９を走査して機械コードに変換して機械コードバッファ３１２に格納し、最後に処理５０３において、処理５０２で生成した機械コードや処理５０１で生成した戻り番地表などを実行プログラム３０８として出力する。
【００１６】
処理５０１では、個々の手続きごとに戻り番地表３１１を生成しているが、戻り番地表はプログラム全体で１つ生成することもできる。個々の戻り番地表のサイズは、図４の処理４０４で生成した呼出元数表３１０から呼出元の数を求めて定める。呼出元数表３１０の実施例を図６に示す。図６の呼出元数表３１０には、手続きの名前と呼出元の数を登録する欄があり，calleeという名前の手続きが、７個の呼出元を持つと記述してある。処理５０１が図６の呼出元数表３１０を参照し、calleeの戻り番地表３１１を生成した結果を図７に示す。図７の戻り番地表３１１には、図６に記述されている通り、７個の呼出元に対応する戻り番地を格納するスロットが確保されている。なお、この時点では、戻り番地表３１１の個々のエントリには、まだ戻り番地は登録されていない。
【００１７】
図５に戻り、処理５０２では中間表現３０９を機械コードに変換する処理をおこなう。具体的には、まず判断５０４で全ての中間表現３０９を走査したか調べ、走査していないならば処理５０５に進んで次に走査すべき中間表現を取得する。取得した中間表現の種類に応じて判断５０６で分岐をおこない、中間表現が手続き呼出を表すものであれば処理５０７に進んで手続き呼出の機械コードを出力し、ｒｅｔｕｒｎ文を表すものであれば処理５０８に進んでｒｅｔｕｒｎ文に対応する機械コードを出力する。処理５０７や処理５０８が終了したら判断５０４に戻る。
【００１８】
判断５０４で全ての中間表現を走査したならば、処理５０３に進んで実行プログラム３０８を出力する。処理５０４の中には、実行時にローダが読込専用領域に読み込む部分を出力する処理５０９と、読書可能な領域に読み込む部分を出力する処理５１０が入っているが、機械コードを出力する処理５１１と、戻り番地表３１１を出力する本発明の処理５１２は、処理５０９の中にある。この結果、本発明の戻り番地表３１１は、実行時にローダによって読込専用領域に配置されるので、実行時に攻撃者が戻り番地表３１１の内容を書き換えて制御を奪うことは不可能になる。
【００１９】
処理５０７および処理５０８では本発明の機械コードの出力をおこなう。処理５０７の実施例を図８に示す。図８では、まず処理８０１を実施して、引数を引き渡すための機械コードを出力する。続く処理８０２と処理８０３が本発明の処理である。処理８０２では、手続呼出しからの戻り番地を、呼出先の手続きに対応する戻り番地表３１１に登録する。関数ポインタ経由の手続き呼出しなど、呼出先が不定の場合には、全手続きに対応する戻り番地表３１１について、同一スロット番号の空きスロットを確保し、該スロットに登録する。そして、登録先のスロット番号を取得する。本実施例では、ここで取得したスロット番号を戻り番地ＩＤとして使う。処理８０３で戻り番地ＩＤ、つまりスロット番号を呼出先に引き渡すために、レジスタ（ここではＲ１とする）に格納する機械コードを出力する。最後に処理８０４で呼出先にジャンプする機械コードを出力する。
【００２０】
処理５０８の実施例を図９に示す。図９ではまず、判断９０１でｒｅｔｕｒｎ文が値を返戻するか調べ、返戻するならば処理９０２で返戻値を、返戻値を格納するためのレジスタに読み込む機械コードを出力して処理９０３に進み、返戻しないならば処理９０３に進む。続く処理９０３と、処理９０５から処理９０６までが本発明の処理である。処理９０３では、呼出元から受け取った戻り番地ＩＤを、レジスタＲ１に復帰する機械コードを出力し、処理９０４でスタックフレームを破棄する機械コードを出力する。続く処理９０５でレジスタＲ１に格納された戻り番地ＩＤが、戻り番地表３１１のスロット番号として有効か検査するコードを出力する。より具体的には、レジスタＲ１に格納された値（符号なし整数）が、戻り番地表３１１の大きさ以上ならば割込みを発生する機械コードを出力する。こうすると、実行時に攻撃者が戻り番地ＩＤを、戻り番地表の大きさ以上の値に書き換えた場合には、割込みが発生してプログラムが停止する。割込みによるプログラムの停止が発生した場合、コンピュータシステムの管理者は、攻撃にあった疑いがあるとみなして、調査を開始できる。戻り番地表３１１の大きさは呼出元数表３１０を参照して求める。次の処理９０６では、戻り番地表３１１の、レジスタＲ１に格納してある番号のスロットから戻り番地を求める機械コードを出力し、最後に処理９０７で、求めた戻り番地にジャンプする機械コードを出力する。
【００２１】
図１０の手続きcallee()を呼び出す機械コードと、手続きcallee()の中にあるｒｅｔｕｒｎ文に対応する機械コードを図１１に示す。図１１の機械コードのうち、callee()の呼出元に対応する部分（１〜３行目）は、図８の処理５０７が出力する機械コードの実施例であり、また、ｒｅｔｕｒｎ文に対応する部分（７〜１４行目）は、図９の処理５０８が出力する機械コードの実施例である。図１１の機械コード中にある戻り番地ＩＤや、戻り番地表のアドレスは定数として機械コード中にエンコードされている。機械コードは実行時にローダによって読込専用領域に配置され、したがって実行時に攻撃者が図１１の戻り番地ＩＤや戻り番地表のアドレスを書き換えることはできない。図１１の１０行目にある定数７は、手続きcallee()の戻り番地表３１１（図７）のサイズである。
【００２２】
図１１では、呼出元のコードの２行目において、戻り番地ＩＤを引数としてレジスタＲ１にセットしてから３行目の分岐命令ｂｌで呼出先（４行目のcallee）にジャンプする。呼出先では、まず、６行目で戻り番地ＩＤをスタックフレームに退避し、次に手続き本体の実行を開始する。手続き本体の実行を終了し、７行目の返戻のコードに到達したら、まず８行目で戻り番地ＩＤを復帰し、１０行目で戻り番地ＩＤが有効な範囲内にあるか（戻り番地表３１１のサイズ未満か）検査し、有効な範囲内にあるならば、１１〜１３行目で戻り番地表から戻り番地を取得し、取得した戻り番地に１４行目からジャンプする。
【００２３】
図１に示した一般的な手続呼出しの実現と、図１１に示した本発明の手続き呼出しの実現を比較すると、本発明の実現では、攻撃者が書き換え可能な情報が戻り番地ＩＤにおきかわっており、しかも戻り番地ＩＤが有効な範囲内（戻り番地表３１１のサイズ）でないと割込が発生するので、返戻のコードによるジャンプ先が、戻り番地表に載っているアドレスのみに制限され、結果として攻撃者が返戻のコードを利用して任意のコードを実行させることが困難になっていることが判る。
【産業上の利用可能性】
【００２４】
本発明のコンパイラでコンパイルすることにより、戻り番地を書き換える攻撃があっても、制御を奪われにくくなる。
【図面の簡単な説明】
【００２５】
【図１】一般的な言語処理系のコードが出力する手続呼出しのコード
【図２】実行時スタック
【図３】言語処理系の実施例
【図４】言語処理系の処理フロー
【図５】処理２０４の実施例
【図６】呼出元数表３１０の実施例
【図７】戻り番地表３１１の実施例
【図８】処理５０７の実施例
【図９】処理５０８の実施例
【図１０】コンパイル対象の手続きcallee()
【図１１】処理５０７および処理５０８が出力するコードの実施例
【符号の説明】
【００２６】
３０８  実行プログラム
３０９  中間表現
３１０  呼出元数表
３１１  戻り番地表
３１２  機械コードバッファ
５０１  個々の手続きに対応する戻り番地表を生成する処理
５０２  全中間表現を走査して機械コードに変換する処理
５０３  実行プログラムを出力する処理
５０４  全中間表現が走査済か否かの判断
５０５  次の中間表現を取得する処理
５０６  中間表現の種類に対する判断
５０７  手続呼出しに対応する機械コードを出力する処理
５０８  return文に対応する機械コードを出力する処理
５０９  実行時に読込専用領域に配置するデータを出力する処理
５１０  実行時に読書可能領域に配置するデータを出力する処理
５１１  機械コードを出力する処理
５１２  戻り番地表を出力する処理
【図１】
2006048257.tif 000003
【図２】
2006048257.tif 000004
【図３】
2006048257.tif 000005
【図４】
2006048257.tif 000006
【図５】
2006048257.tif 000007
【図６】
2006048257.tif 000008
【図７】
2006048257.tif 000009
【図８】
2006048257.tif 000010
【図９】
2006048257.tif 000011
【図１０】
2006048257.tif 000012
【図１１】
2006048257.tif 000013