(57)【要約】      （修正有）【課題】攻撃者がコンピュータプログラムの実行フローを修正することを防止する。【解決手段】攻撃者によって修正されていないプログラム実行フローの操作が置かれているコンピュータのメモリの１つ以上の範囲を識別し、メモリアドレスが１つ以上の識別されたメモリ範囲の中にあることを確実にするためにメモリアドレスをマスクするためのマスクを決定し、プログラムの実行フローを検査して、プログラムの実行フローが、プログラム実行フローの次の操作が置かれている目標メモリアドレスへジャンプすることを引き起こすプログラムの１つ以上の操作を識別し、識別された１つ以上の操作の実行前にプログラム実行フローの中へある操作を挿入する。挿入された操作は、決定されたマスクを目標アドレスへ適用し、これによってジャンプを引き起こす操作が、１つ以上の識別されたメモリ範囲の中にあるメモリ場所へ向けられる。【選択図】図１
2011008778.tif 000002
【特許請求の範囲】
【請求項１】
攻撃者がコンピュータプログラムの実行フローを修正することを防止する方法であって、前記コンピュータプログラムは、順次に実行される操作のシーケンスを含み、
攻撃者によって修正されていない前記プログラムの実行フローの操作が置かれていることが期待されるコンピュータのメモリの１つ以上の範囲を識別するステップと、
メモリアドレスが前記１つ以上の識別されたメモリ範囲の中にあることを確実にするために、前記メモリアドレスをマスクするためのマスクを決定するステップと、
前記プログラムの実行フローを検査して、前記プログラムの実行フローが、前記プログラムの実行フローの次の操作が置かれている目標メモリアドレスへジャンプすることを引き起こす前記プログラムの１つ以上の操作を識別するステップと、
前記識別された１つ以上の操作の実行前に、前記プログラムの実行フローの中へある操作を挿入するステップであって、前記挿入された操作は、前記決定されたマスクを前記目標メモリアドレスへ適用することによって前記目標メモリアドレスをマスクし、これによって、前記ジャンプを引き起こす操作が、前記１つ以上の識別されたメモリ範囲の中にあるメモリ場所へ向けられることを確実にする、ステップと
を含み、
前記コンピュータの前記メモリの１つ以上の範囲を識別するステップは、
プログラムコードの前記プログラムの実行フローを検査し、前記プログラムの実行フローの間に呼び出される関数について、前記関数が呼び出されるメモリアドレス場所を決定することを含み、
前記方法は、
前記プログラムの実行フローが、前記呼び出された関数から、前記関数が呼び出されたアドレス又は前記関数が呼び出されたアドレスの次のアドレスへ戻るようにするマスクを決定するステップと、
前記呼び出された関数からのリターン処理が実行される前は常に、前記挿入された操作へ前記マスクを適用するステップと
を更に含む方法。
【請求項２】
前記１つ以上の識別されたメモリ範囲は、
前記コンピュータプログラムの前記プログラムコードが置かれているメモリ範囲と、
前記コンピュータプログラムによって使用されるようにロードされた１つ以上のライブラリが置かれているメモリ範囲との１つ以上を含む、請求項１に記載の方法。
【請求項３】
前記プログラムの実行フローが目標メモリアドレスへジャンプすることを引き起こす前記１つ以上の操作は、
関数又はメソッドのコール処理、
関数又はメソッドのコール処理からのリターン処理、
計算されたジャンプ、
ライブラリ関数へのジャンプ
の１つ以上を含む、請求項１又は２に記載の方法。
【請求項４】
ライブラリがロードされた前記メモリ範囲を読み出し専用としてマークするステップと、
グローバル・オフセット・テーブル及びプロシージャ・リンケージ・テーブルの双方あるいはいずれか一方を読み出し専用としてマークするステップと
の両方又はいずれか一方のステップを更に含む、請求項１ないし３のいずれか一項に記載の方法。
【請求項５】
任意の計算されたジャンプの前に前記マスクを適用する操作を挿入するステップと、
任意のライブラリコールの前に前記マスクを適用する操作を挿入するステップと、
グローバル・オフセット・テーブルにアクセスする前に前記マスクを前記グローバル・オフセット・テーブルへ適用するステップと、
プロシージャ・リンケージ・テーブルにアクセスする前に前記マスクを前記プロシージャ・リンケージ・テーブルへ適用するステップと
の１つ以上を含む、請求項１ないし４のいずれか一項に記載の方法。
【請求項６】
修正されていないプログラムコードが置かれていることが期待される前記メモリ範囲の最後のメモリアドレスが、一連の連続した論理「１」で構成されていない場合、前記メモリ範囲の前記最後のメモリアドレスが一連の論理「１」で構成されるまで、ダミー命令又はＮＯＰ命令又は存在しない命令で前記メモリ範囲を充填するステップを含む、請求項１ないし５のいずれか一項に記載の方法。
【請求項７】
前記マスクは、前記関数が呼び出された操作のメモリアドレスの次にある操作のメモリアドレスをＯＲ操作することに基づいて決定されるものである、請求項１に記載の方法。
【請求項８】
前記プログラムの実行フローの間に呼び出される各関数について、前記関数に対して特有のマスクが決定され、前記関数特有のマスクは、前記呼び出された関数からの戻り処理が実行されるべきときに常に適用される、請求項１又は７に記載の方法。
【請求項９】
前記プログラムの実行フローの操作を整列させるステップであって、メソッドコール又は計算されたジャンプが、ある一定の区間又はこの区間の倍数だけ分離されたメモリアドレスに置かれるように整列される、ステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、メソッドコール又は計算されたジャンプではない命令が置かれているアドレスの１つになるように、前記マスクを決定するステップと
を更に含む、請求項１ないし８のいずれか一項に記載の方法。
【請求項１０】
メソッドコール又は計算されたジャンプが、奇数メモリアドレスに置かれるように、前記プログラムの実行フローの操作を整列させるステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、偶数アドレスであって、ジャンプ又はメソッドコールからのリターン処理が次のジャンプ又はメソッドコールの前にあるアドレスで生じるように、前記マスクを決定するか、又は、メソッドコール又は計算されたジャンプが偶数メモリアドレスに置かれるように、前記プログラムの実行フローの操作を整列させるステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、奇数アドレスであって、メソッドコールからのジャンプ又はリターン処理が、次のジャンプ又はメソッドコールの前にあるアドレスで生じるように、前記マスクを決定するステップと
を含む、請求項９に記載の方法。
【請求項１１】
前記挿入された操作によって、操作が実行される前にチェックされるパラメータを設定するステップと、
前記パラメータが設定されている場合にのみ、前記マスクの操作に後続する前記ジャンプの操作について及び前記ジャンプの実行に後続する操作について設定を実行するステップと
を更に含む、請求項１ないし１０のいずれか一項に記載の方法。
【請求項１２】
攻撃者がコンピュータプログラムの実行フローを修正することを防止する装置であって、前記コンピュータプログラムは、順次に実行される操作のシーケンスを含み、
攻撃者によって修正されていない前記プログラムの実行フローの操作が置かれていることが期待されるコンピュータのメモリの１つ以上の範囲を識別するモジュールと、
メモリアドレスが前記１つ以上の識別されたメモリ範囲の中にあることを確実にするように、前記メモリアドレスをマスクするためのマスクを決定するモジュールと、
前記プログラムの実行フローを検査して、前記プログラムの前記実行フローが、前記プログラムの実行フローの次の操作が置かれている目標メモリアドレスへジャンプすることを引き起こす前記プログラムの１つ以上の操作を識別するモジュールと、
前記識別された１つ以上の操作の実行前に、前記プログラムの実行フローの中へある操作を挿入するモジュールであって、前記挿入された操作は、前記決定されたマスクを前記目標メモリアドレスへ適用することによって前記目標アドレスをマスクし、これによって、前記ジャンプを引き起こす操作が、前記１つ以上の識別されたメモリ範囲の中にあるメモリ場所へ向けられることを確実にする、モジュールと
を備え、
前記コンピュータのメモリの１つ以上の範囲を識別する前記モジュールは、
プログラムコードの前記プログラムの実行フローを検査して、前記プログラムの実行フローの間に呼び出される関数について、前記関数が呼び出されるメモリアドレス場所を決定するモジュールを備え、
前記装置は、
前記プログラムの実行フローが、前記呼び出された関数から、前記関数が呼び出されたアドレス又は前記関数が呼び出されたアドレスの次のアドレスへ戻るようにするマスクを決定するモジュールと、
前記呼び出された関数からのリターン処理が実行される前は常に、前記挿入された操作へ前記マスクを適用するモジュールと
を更に備える、装置。
【請求項１３】
請求項２ないし１１のいずれか一項に記載の方法を実行するためのモジュールを更に備える、請求項１２に記載の装置。
【請求項１４】
コンピュータの上で実行するときに、請求項１ないし１１のいずれか一項に記載の方法を実行させるコンピュータ・プログラム・コードを備えるコンピュータプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、攻撃者によるプログラム実行フローの修正、例えば、バッファオーバーフロー攻撃を防止する方法及び装置に関する。
【背景技術】
【０００２】
バッファオーバーフロー攻撃者は、しばしば、リターンアドレス（return address）（例えば、関数コール（関数呼び出し）又はメソッドコール（メソッド呼び出し）からのリターンアドレス）を変更できることを利用して、注入された悪意のあるコードを実行することによって、制御フローが継続するようにする。これによって、攻撃者は任意のコードを実行することができるようになるため、バッファオーバーフロー脆弱性を重大な脅威へと変えることになる。
【０００３】
バッファオーバーフロー攻撃を防止し、あるいはこれらの攻撃を大きく減らすための効果的な対策が必要となる。従来、メインストリームのオペレーティングシステムにはこのような対策が加えられていたが、時間が経過するにつれて、攻撃者は、これらの対策を迂回するやり方を発見してきた。したがって、新しい効果的な対策が開発されるべきである。
【０００４】
今日まで、様々な対策が知られている。対策は、概して２つの種類に分類される。
対策の第１の種類としては、攻撃者がリターンアドレスを変更することを不可能にするやり方である。この種の対策の例は、非特許文献１に記載されている。
対策の別の種類としては、攻撃者がリターンアドレスを修正することを許容するが、損害が起こる前に、これらの変更を検出しようと試みるやり方である。そのような対策の例は、スタック・クッキー（例えば、非特許文献２を参照）、ポインタ暗号化（例えば、非特許文献３を参照）、及び制御フロー・インテグリティＣＦＩ（例えば、非特許文献４を参照）である。
【先行技術文献】
【非特許文献】
【０００５】
【非特許文献１】Ｙｖｅｓ  Ｙｏｕｎａｎ，Ｄａｖｉｄｅ  Ｐｏｚｚａ，Ｆｒａｎｋ  Ｐｉｅｓｓｅｎｓ  ａｎｄ  Ｗｏｕｔｅｒ  Ｊｏｏｓｅｎ．Ｅｘｔｅｎｄｅｄ  ｐｒｏｔｅｃｔｉｏｎ  ａｇａｉｎｓｔ  ｓｔａｃｋ  ｓｍａｓｈｉｎｇ  ａｔｔａｃｋｓ  ｗｉｔｈｏｕｔ  ｐｅｒｆｏｒｍａｎｃｅ  ｌｏｓｓ．Ｐｒｏｃｅｅｄｉｎｇｓ  ｏｆ  ｔｈｅ  ２２ｎｄ  Ａｎｎｕａｌ  Ｃｏｍｐｕｔｅｒ  Ｓｅｃｕｒｉｔｙ  Ａｐｐｌｉｃａｔｉｏｎｓ  Ｃｏｎｆｅｒｅｎｃｅ  （ＡＣＳＡＣ’０６），Ｍｉａｍｉ  Ｂｅａｃｈ，Ｆｌｏｒｉｄａ，Ｕ．Ｓ．Ａ，Ｄｅｃｅｍｂｅｒ  ２００６．ＩＥＥＥ  Ｐｒｅｓｓ
【非特許文献２】Ｊａｓｏｎ  Ｃｏｍｂｓ：Ｗｉｎｄｏｗｓ（登録商標）  Ｓｔａｃｋ  Ｂｕｆｆｅｒ  Ｏｖｅｒｆｌｏｗ  Ｐｒｏｔｅｃｔｉｏｎ（http://www.ddj.com/security/184405546）
【非特許文献３】Ｃｒｉｓｐｉｎ  Ｃｏｗａｎ，Ｓｔｅｖｅ  Ｂｅａｔｔｉｅ，Ｊｏｈｎ  Ｊｏｈａｎｓｅｎ，ａｎｄ  Ｐｅｒｒｙ  Ｗａｇｌｅ．Ｐｏｉｎｔ−Ｇｕａｒｄ：ｐｒｏｔｅｃｔｉｎｇ  ｐｏｉｎｔｅｒｓ  ｆｒｏｍ  ｂｕｆｆｅｒ  ｏｖｅｒｆｌｏｗ  ｖｕｌｎｅｒａｂｉｌｉｔｉｅｓ．Ｉｎ  Ｐｒｏｃｅｅｄｉｎｇｓ  ｏｆ  ｔｈｅ  １２ｔｈ  ＵＳＥＮＩＸ  Ｓｅｃｕｒｉｔｙ  Ｓｙｍｐｏｓｉｕｍ，ｐａｇｅｓ  ９１−１０４，Ｗａｓｈｉｎｇｔｏｎ，Ｄ．Ｃ．，Ｕ．Ｓ．Ａ．，Ａｕｇｕｓｔ  ２００３．ＵＳＥＮＩＸ  Ａｓｓｏｃｉａｔｉｏｎ
【非特許文献４】Ｍａｒｔｉｎ  Ａｂａｄｉ，Ｍｉｈａｉ  Ｂｕｄｉｕ，Ｕｌｆａｒ  Ｅｒｌｉｎｇｓｓｏｎ，ａｎｄ  Ｊａｙ  Ｌｉｇａｔｔｉ．Ｃｏｎｔｒｏｌ−ｆｌｏｗ  ｉｎｔｅｇｒｉｔｙ．Ｉｎ  Ｐｒｏｃｅｅｄｉｎｇｓ  ｏｆ  ｔｈｅ  １２ｔｈ  ＡＣＭ  Ｃｏｎｆｅｒｅｎｃｅ  ｏｎ  Ｃｏｍｐｕｔｅｒ  ａｎｄ  Ｃｏｍｍｕｎｉｃａｔｉｏｎｓ  Ｓｅｃｕｒｉｔｙ，ｐａｇｅｓ  ３４０−３５３，Ａｌｅｘａｎｄｒｉａ，Ｖｉｒｇｉｎｉａ，Ｕ．Ｓ．Ａ．，Ｎｏｖｅｍｂｅｒ  ２００５
【非特許文献５】Ａｎｄｒｅｗ  Ｓｌｏｓｓ，Ｄｏｍｉｎｉｃ  Ｓｙｍｅｓ，ａｎｄ  Ｃｈｒｉｓ  Ｗｒｉｇｈｔ．ＡＲＭ  Ｓｙｓｔｅｍ  Ｄｅｖｅｌｏｐｅｒ’ｓ  Ｇｕｉｄｅ  -  Ｄｅｓｉｇｎｉｎｇ  ａｎｄ  Ｏｐｔｉｍｉｚｉｎｇ  Ｓｙｓｔｅｍ  Ｓｏｆｔｗａｒｅ，Ｅｌｓｖｉｅｒ，２００４
【発明の概要】
【発明が解決しようとする課題】
【０００６】
制御フロー・インテグリティＣＦＩは、プログラム実行フローのグラフを実質的に作成し、フロー内のジャンプを識別して、どこへジャンプするかを識別する。次いで、これらの場所（location）には、ユニークなＩＤが割り当てられ、このＩＤは、コードの中へ挿入される。次いで、実行の間にジャンプが起こると、ジャンプする場所が正しいＩＤを有するかどうかがチェックされる。正しいＩＤは、プログラムフローを検査するときに前もって決定されている。正しいＩＤでない場合は、プログラムは途中停止（アボート）される。このようにして、ＣＦＩは、プログラムフローのリターンアドレスが修正されたかどうかを検出し（修正されると、誤った行き先のラベルが生じることになる）、これに基づいてプログラムが途中停止される。
【０００７】
このアプローチは、ある程度効果的であるが、オーバーヘッドがかなり大きくなる。なぜなら、各ジャンプについて、このジャンプの正しい場所へ行くかどうか、言い換えれば、ジャンプが正しいＩＤに割り当てられたかどうかを、最初に調査しなければならないからである。このような操作は、プログラムの実行をかなり遅らせることになる。したがって、本発明の目的は、安全であって、ＣＦＩよりも小さいオーバーヘッドとなる他のアプローチを提供することである。
【課題を解決するための手段】
【０００８】
１つの実施形態によれば、攻撃者がコンピュータプログラムの実行フローを修正することを防止する方法が提供される。該コンピュータプログラムは、順次に実行される操作のシーケンスを含む。該方法は、
攻撃者によって修正されていない前記プログラムの実行フローの操作が置かれていることが期待されるコンピュータのメモリの１つ以上の範囲を識別するステップと、
メモリアドレスが前記１つ以上の識別されたメモリ範囲の中にあることを確実にするために、前記メモリアドレスをマスクするためのマスクを決定するステップと、
前記プログラムの実行フローを検査して、前記プログラムの実行フローが、前記プログラムの実行フローの次の操作が置かれている目標メモリアドレスへジャンプすることを引き起こす前記プログラムの１つ以上の操作を識別するステップと、
前記識別された１つ以上の操作の実行前に、前記プログラムの実行フローの中へある操作を挿入するステップであって、前記挿入された操作は、前記決定されたマスクを前記目標メモリアドレスへ適用することによって前記目標メモリアドレスをマスクし、これによって、前記ジャンプを引き起こす操作が、前記１つ以上の識別されたメモリ範囲の中にあるメモリ場所へ向けられることを確実にする、ステップと
を含み、
前記コンピュータの前記メモリの１つ以上の範囲を識別するステップは、
プログラムコードの前記プログラムの実行フローを検査し、前記プログラムの実行フローの間に呼び出される関数について、前記関数が呼び出されるメモリアドレス場所を決定することを含み、
前記方法は、
前記プログラムの実行フローが、前記呼び出された関数から、前記関数が呼び出されたアドレス又は前記関数が呼び出されたアドレスの次のアドレスへ戻るようにするマスクを決定するステップと、
前記呼び出された関数からの戻り処理が実行される前は常に、前記挿入された操作へ前記マスクを適用するステップと
を更に含む。
【０００９】
修正されていないコードが期待されるメモリ範囲を決定し、対応するマスクを決定してジャンプ前にこれを適用することによって、プログラム実行フローの任意の修正を攻撃者が実際に使用する可能性を厳しく制限することができる。
【００１０】
１つの実施形態によれば、目標アドレスは、識別された操作の現在のメモリアドレスに隣接するメモリアドレスとは異なる。言い換えれば、「ジャンプ」は、プログラム実行フローが、プログラム・コード・メモリの次のメモリアドレスではなく、ある一層遠いメモリ場所のメモリアドレスへ実際に「ジャンプ」することを意味する。
【００１１】
１つの実施形態によれば、前記１つ以上の識別されたメモリ範囲は、前記コンピュータプログラムの前記プログラムコードが置かれているメモリ範囲と、前記コンピュータプログラムによって使用されるようにロードされた１つ以上のライブラリが置かれているメモリ範囲との１つ以上を含む。
【００１２】
プログラムコードが置かれているメモリは、任意のバッファオーバーフロー攻撃に対して安全であると考えられ得るメモリ範囲であり、したがって、この範囲は、意味のあるマスクを生成するために使用され得る。
【００１３】
同様に、ロードされたライブラリが置かれているメモリ範囲は、比較的安全な区域として見なされ、したがって、このメモリ範囲についてもマスクが生成及び適用され得る。
【００１４】
１つの実施形態によれば、前記プログラムの実行フローが目標メモリアドレスへジャンプすることを引き起こす前記１つ以上の操作は、
関数又はメソッドのコール（call：呼び出し）、
関数又はメソッドのコールからの戻り処理（リターン処理）、
計算されたジャンプ、
ライブラリ関数へのジャンプ
の１つ以上を含む。
【００１５】
これらは、プログラム実行フローが、次のメモリアドレスに置かれた命令への進行から外れる例である。したがって、これらは、潜在的に脆弱である命令であるが、マスク操作による保護が有用である命令である。
【００１６】
１つの実施形態による方法は、
ライブラリがロードされた前記メモリ範囲を読み出し専用としてマークするステップと、
グローバル・オフセット・テーブル及びプロシージャ・リンケージ・テーブルの双方あるいはいずれか一方を読み出し専用としてマークするステップと
の両方又はいずれか一方のステップを更に含む。
【００１７】
ライブラリが置かれている領域を読み出し専用としてマークすることは、ライブラリが置かれているコードの変更を防御し、
グローバル・オフセット・テーブル又はプロシージャ・リンケージ・テーブルを読み出し専用としてマークすることは、これらのテーブルの内容の修正に依存する任意の攻撃を防御する。
【００１８】
１つの実施形態の方法は、
任意の計算されたジャンプの前に前記マスクを適用する操作を挿入するステップと、
任意のライブラリのコール（呼び出し）の前に前記マスクを適用する操作を挿入するステップと、
グローバル・オフセット・テーブルにアクセスする前に前記マスクを前記グローバル・オフセット・テーブルへ適用するステップと、
プロシージャ・リンケージ・テーブルにアクセスする前に前記マスクを前記プロシージャ・リンケージ・テーブルへ適用するステップと
の１つ以上を含む。
【００１９】
これらは、マスク操作の挿入が、任意の攻撃を防止するために有用であり得る例である。
【００２０】
１つの実施形態による方法は、
修正されていないプログラムコードが置かれていることが期待される前記メモリ範囲の最後のメモリアドレスが、一連の連続した論理「１」で構成されていない場合、前記メモリ範囲の前記最後のメモリアドレスが一連の論理「１」で構成されるまで、ダミー命令又はＮＯＰ命令又は存在しない命令で前記メモリ範囲を充填するステップを含む。
【００２１】
このようにして、プログラムコードの最後のメモリアドレスが論理「０」を含む場合でも、良好なマスクが生成され得る。
【００２２】
１つの実施形態によれば、方法は、
プログラムコードのプログラムの実行フローを検査して、該プログラムの実行フローの間に呼び出される関数について、該関数が呼び出されるメモリアドレス場所を決定するステップと、
該呼び出された関数から、該関数が呼び出されたアドレス、又はこれらのアドレスの次にあるアドレスへ、プログラムの実行フローが戻るようにするマスクを決定するステップと、
呼び出された関数からのリターン処理（戻り処理）が実行される前は常に、該挿入された命令へ前記マスクを適用するステップと
を含む。
【００２３】
呼び出すアドレスに基づくマスクの決定及び適用は、一層精密なマスクを可能にし、これにより、実際にコール（呼び出し）が起こった関数又はアドレスへのみにリターン処理がジャンプすることが確実になり、セキュリティが向上する。
【００２４】
リターンのジャンプは、実際の実装又はコンパイラに依存して、ジャンプを引き起こした操作の後の「次の操作」の場所へ行くことを可能にするか、ジャンプを引き起こした命令の場所へ直接行くことを可能にする。
【００２５】
１つの実施形態によれば、前記マスクは、関数が呼び出された操作のアドレスの次にある操作のメモリアドレスをＯＲ操作することに基づいて決定されるものである。
【００２６】
論理ＯＲ結合は、多数のコールアドレス（call address）に基づくマスク決定の実際的アプローチである。
【００２７】
１つの実施形態によれば、前記プログラムの実行フローの間に呼び出される各関数について、前記関数に対して特有のマスクが決定され、前記関数特有のマスクは、前記呼び出された関数からのリターン処理が実行されるべきときに常に適用される。
【００２８】
これは、セキュリティを更に向上する関数特有のマスクの適用を確実にする。
【００２９】
１つの実施形態によれば、方法は、
前記プログラムの実行フローの操作を整列させるステップであって、メソッドコール又は計算されたジャンプが、ある一定の区間又はこの区間の倍数だけ分離されたメモリアドレスに置かれるように整列される、ステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、メソッドコール又は計算されたジャンプではない命令が置かれているアドレスの１つになるように、前記マスクを決定するステップと
を更に含む。
【００３０】
これは、攻撃者がジャンプ命令へ直接ジャンプすることによってマスキング命令を迂回することができないことを確実にする。
【００３１】
１つの実施形態によれば、方法は、
メソッドコール又は計算されたジャンプが、奇数メモリアドレスに置かれるように、前記プログラムの実行フローの操作を整列させるステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、偶数アドレスであって、ジャンプ又はメソッドコールからのリターン処理が次のジャンプ又はメソッドコールの前にあるアドレスで生じるように、前記マスクを決定するか、又は、メソッドコール又は計算されたジャンプが偶数メモリアドレスに置かれるように、前記プログラムの実行フローの操作を整列させるステップと、
前記マスクを適用した後に、結果として得られるメモリアドレスが、奇数アドレスであって、メソッドコールからのジャンプ又はリターン処理が、次のジャンプ又はメソッドコールの前にあるアドレスで生じるように、前記マスクを決定するステップと
を含む。
【００３２】
これは、ジャンプ命令の整列の具体的な実装の仕方である。
【００３３】
１つの実施形態によれば、方法は、
前記挿入された操作によって、操作が実行される前にチェックされるパラメータを設定するステップと、
前記パラメータが設定されている場合にのみ、前記マスクの操作に後続する前記ジャンプの操作について及び前記ジャンプの実行に後続する操作について設定を実行するステップとを更に含む。
【００３４】
このようにして、条件付き実行可能パラメータを利用することによりセキュリティが更に向上され得る。
【００３５】
１つの実施形態によれば、攻撃者がコンピュータプログラムの実行フローを修正することを防止する装置が提供される。該コンピュータプログラムは、順次に実行される操作のシーケンスを備える。該装置は、
攻撃者によって修正されていない前記プログラムの実行フローの操作が置かれていることが期待されるコンピュータのメモリの１つ以上の範囲を識別するモジュールと、
メモリアドレスが前記１つ以上の識別されたメモリ範囲の中にあることを確実にするように、前記メモリアドレスをマスクするためのマスクを決定するモジュールと、
前記プログラムの実行フローを検査して、前記プログラムの前記実行フローが、前記プログラムの実行フローの次の操作が置かれている目標メモリアドレスへジャンプすることを引き起こす前記プログラムの１つ以上の操作を識別するモジュールであって、前記目標メモリアドレスは、識別された操作の現在のメモリアドレスに隣接するメモリアドレスとは異なる、モジュールと、
前記識別された１つ以上の操作の実行前に、前記プログラムの実行フローの中へある操作を挿入するモジュールであって、前記挿入された操作は、前記決定されたマスクを前記目標メモリアドレスへ適用することによって前記目標アドレスをマスクし、これによって、前記ジャンプを引き起こす操作が、前記１つ以上の識別されたメモリ範囲の中にあるメモリ場所へ向けられることを確実にする、モジュールと
を備える。
【００３６】
１つの実施形態によれば、装置は、本発明の実施形態の１つに従った方法を実行するモジュールを備える。
【００３７】
１つの実施形態によれば、コンピュータ・プログラム・コードを備えるコンピュータプログラムが提供される。コンピュータ・プログラム・コードは、コンピュータ上で実行されるときに、本発明の実施形態の１つに従った方法を実行させる。
【図面の簡単な説明】
【００３８】
【図１】本発明の実施形態を概略的に示した図である。
【図２】本発明の実施形態が適用され得るメモリ・アーキテクチャを概略的に示した図である。
【発明を実施するための形態】
【００３９】
本発明は、幾つかの実施形態を用いて説明される。最初に、説明で使用される幾つかの用語について説明する。
【００４０】
ＡＮＤ：論理ＡＮＤ操作
ＢＩＣ：論理ビットクリア（ＡＮＤ  ＮＯＴ）
攻撃者：ソフトウェア内の脆弱性を探している悪意のあるユーザ
制御フロー・インテグリティ：アプリケーションにおける意図された制御フロー又はプログラムコードから外れることを識別するための対策
グローバル・オフセット・テーブル：グローバル・オフセット・テーブルは、位置独立アドレス計算（position-independent address calculation）の結果を絶対場所（absolute location）へ変換する
ヒープ：動的メモリ割り当てに使用されるコンピュータメモリ
マスク：ビット単位の操作に使用される値であって、他の値と結合されて特定の値域の中にある値を戻す
ＯＲ：論理ＯＲ操作
プログラムコード：実行されるべきアプリケーションの命令
プロシージャ・リンケージ・テーブル：プロシージャ・リンケージ・テーブルは、位置独立関数コール（position-independent function call）を絶対場所へ変換する。
シェルコード：攻撃者によって、メモリ、例えば、ヒープ又はスタックの中へ注入されるプログラムコード
スタック：固定された基点をもち、サイズが可変のコンピュータメモリ。スタックは後入れ先出し法で動作する
スタック・クッキー：予測し得ない値のトークン
【００４１】
本発明の１つの実施形態によれば、マスクは、関数コール（関数呼び出し）からリターンした後、又はメモリ内のある一定の範囲のみに対応する命令のウィンドウ（window）への関数コールを実行するとき、プログラムの実行を制限するようにする（マスクの生成及び適用は、この後で更に詳細に解明される）。
【００４２】
以下、時にはＣＲＡＭ（コール及びリターンアドレス（return address）のマスキング）と呼ばれる本発明の実施形態に従ったアプローチは、プログラム実行フローが攻撃者によって修正されていない正規のコードが置かれていることが期待されるメモリ範囲を指し示すように、リターンアドレスをマスクする。そのようなメモリ範囲は、１つの実施形態によれば、例えば、プログラムコードが置かれているメモリ範囲である。任意の関数コールの目標アドレス（target address）又は関数からリターンするときの目標アドレスをマスクすることによって、データメモリの任意のオーバーフローバッファ内に注入されたコードが、実行されないようにする。
【００４３】
提示されたアプローチは、ランタイムオーバーヘッドが小さく、且つ他の対策と両立できる対策である。このアプローチは、セキュリティに関して高い保証を提供することができる。
【００４４】
本発明の実施形態によれば、プログラム実行フローを修正するような攻撃をどのようにして防止するかの新しいカテゴリが導入される。従来のアプローチは、ジャンプアドレスの修正を防止するか、ジャンプアドレスの修正を検出するものである。本発明の実施形態の提案アプローチによれば、第３のカテゴリの対策が提示される。提示されたアプローチは、リターンアドレスの上書きを防止するか、リターンアドレスの変更を検出する代わりに、攻撃者がいくらか修正をして有用な何かを行う可能性を制限するものである。
【００４５】
１つの実施形態によれば、修正されていない正規のプログラムコードが置かれていることを期待される１つ以上のメモリ範囲が識別される。このメモリ範囲は、例えば、プログラムコードが置かれている範囲であり、または、プログラム実行の間に使用されるロードされたライブラリ（loaded library）が置かれている範囲としてもよい。その範囲に対応するメモリ場所は、例えば、コンパイラによって決定され得る。
【００４６】
そのような１つ以上のメモリ場所が識別されると、マスクが生成される。このマスクは、メモリアドレスへ適用されたときに、１つ以上の識別された範囲の中にあるメモリアドレスが得られる。次いで、ジャンプ操作の前にマスクをジャンプ操作の目標アドレスへ適用する操作が、プログラム実行フローの中へ挿入される。言い換えれば、現在の命令が置かれているアドレスの次のアドレスに置かれている命令へ実行フローが進行せず、異なるアドレスへプログラムフローがジャンプする任意のジャンプについて、プログラム実行フローが検査される。そのような検査の対象となる命令は、関数あるいはメソッドコール、又は関数あるいはメソッドコールからのリターンの命令であり得る。
【００４７】
現在の操作の場所の次のアドレスとは異なる目標アドレスへのジャンプを引き起こす操作が識別されたとき、識別されたジャンプ操作の前に、マスキング操作がプログラム実行フローの中へ挿入される。マスキング操作は、正規の命令又は操作が置かれていることを期待され得るアドレスに基づいて決定されたマスクをジャンプ操作の目標アドレスへ適用し、これにより、攻撃者によって修正されていない正規のコードのみが置かれていることを期待され得るアドレスへジャンプを導くことを確実にする。
【００４８】
したがって、プログラム実行フロー内でマスクをジャンプの目標アドレスへ適用する処理をプログラム実行フローの中へ挿入することによって、正規の及び修正されていないプログラムコードを、攻撃者による修正から保護することができる。ジャンプは、プログラム実行フロー内で識別され、次いで、識別されたジャンプの目標アドレスへマスクを適用する操作を挿入することによって、プログラム実行フローが修正される。
【００４９】
１つ以上の「安全なメモリ範囲」の識別、対応するマスクの決定、プログラムフロー内のジャンプの識別、及びジャンプの目標アドレスをマスクするマスキング操作の挿入は、コンパイラによって実行され得る。コンパイラによってコンパイルされたプログラムは、各ジャンプ操作の前にマスキング操作を実行し、したがって、プログラム実行フローのジャンプは、攻撃者によって修正されていない正規のプログラムコードのみが置かれていることを期待される「安全なメモリ範囲」へのみ行われる。
【００５０】
このアプローチは、効率性が高く、オーバーヘッドを非常に小さくすることができる。
【００５１】
ここで、実施形態の具体的な例が説明される。
【００５２】
例えば、関数コールからのリターン処理に対応するジャンプのマスキングを達成するため、あるコードが、各関数の終わりに追加される。典型的には、関数は次のように終了する（抜粋されたアセンブラコード）。
［get return address from stack（スタックからリターンアドレスを取得する）］
［jump to this address（このアドレスへジャンプする）］
【００５３】
攻撃者がコードメモリ（即ち、修正されていないプログラムコードが置かれているメモリ範囲）へのみジャンプすることが確実であれば、攻撃者は、攻撃者自身が挿入して且つ典型的にはヒープ又はスタック上に置かれている攻撃者自身のシェルコードへ、ジャンプすることはできない。
【００５４】
この動作を達成させるために、１つの実施形態によれば、例えば、特別なマスクを実行するビット単位操作（例えば、ＡＮＤ、ＯＲ、又はＢＩＣ（論理ビットクリア−ＡＮＤ  ＮＯＴ））をリターンアドレスに適用してもよい。このマスクは、結果として得られるアドレスが、コードメモリの境界を越えないことを確実にする。リターンアドレス（＝ジャンプの目標アドレス）へジャンプする代わりに、リターン処理においては、特別なマスクをリターンアドレスへ適用することから得られるアドレスへジャンプする。
【００５５】
この目的のために、上記のコードシーケンスは次のように変更される。
［get return address from stack（スタックからリターンアドレスを取得する）］
［apply mask on address, thus making sure that the return address points to code memory（マスクをアドレスに適用し、これにより、リターンアドレスがコードメモリを指し示すことを確実にする）］
［jump to this address（このアドレスへジャンプする）］
【００５６】
以上から分かるように、オリジナル（原初）のコードは、特別なマスクを適用する操作をジャンプ操作の前に挿入するように、修正されることになる。
【００５７】
これによって、アプリケーションは、依然としてバッファオーバーフローの脆弱性を有しているが、攻撃者が自身に対して有用なやり方で脆弱性を利用することがより困難になる。
【００５８】
図１は、修正される前の（オリジナルの）コードのコンパイルと、セキュリティを目的として修正された後の修正コードのコンパイルとを示している。
【００５９】
このアプローチは、オーバーヘッドを小さくし、したがって他の対策よりも良好な性能を提供し、同時にセキュリティを著しく改善する。
【００６０】
実施形態によれば、バッファオーバーフローは防止されないが、攻撃者がオーバーフローを用いてできることが制限されることになる。攻撃者は、重要なデータ、例えば、リターンアドレスを上書きすることによって、アプリケーションの制御フローを操作しようと試みる。この場合、攻撃者はリターンアドレスを操作し、このリターンアドレスがメモリ内のどこかを指し示すように操作することが想定される。提案されたアプローチは、リターンアドレスへ戻る前にリターンアドレスへマスクを適用することによって、この攻撃者が行うことを妨げる。マスクは、リターンアドレスがコードメモリ内のある場所を指し示すことを確実にし、攻撃者が、注入されたコードへリターンさせることをできないようにする。
【００６１】
同じアプローチは、プログラムフローが、関数コール又はメソッドコールから、目標アドレスとしてのリターンアドレスへ戻るときのジャンプに対して適用されるだけでなく、プログラム実行フローが、任意の他のジャンプ、例えば、ライブラリコールへジャンプするときにも適用される。この場合、適用されるマスクは、ロードされたライブラリが置かれているメモリ範囲に基づくことができる。１つを超えるメモリ範囲、例えば、プログラムコードが置かれているメモリ範囲及びライブラリが置かれているメモリ範囲に基づく組み合わせマスクが生成されるという意味で、双方のアプローチが組み合わせられてもよい。双方の範囲は、ライブラリのメモリ範囲及びプログラムコードのメモリ範囲へのジャンプを可能にするマスクを生じ得る。
【００６２】
以下では、Ｌｉｎｕｘオペレーティングシステム用の実施形態の例が示される。なお、他のオペレーティングシステムに対策を行うときは、本明細書で使用されるマスキング操作とは異なるマスキング操作が必要となるが、どのようなシステムでも、コンセプトは同じであることに留意すべきである。
【００６３】
図２で示されるように、プログラムデータ、ヒープ、及びスタックは、メモリ内でプログラムコードの上方に置かれている。例として、プログラムコードは０ｘ００００００００から０ｘ００００ＦＦＦＦまでの範囲にあることが想定され、スタック及びヒープは０ｘ００００ＦＦＦＦよりも大きいメモリアドレスに置かれている。
【００６４】
攻撃者が（例えば、バッファをオーバーフローさせることによって）シェルコードをヒープ又はスタックの中へ注入できるならば、注入されたシェルコードのアドレスでは、２つの最上位バイトの少なくとも１つのビットが常に１に設定される。ここで、リターンアドレスがマスク０ｘ００００ＦＦＦＦでマスクされるならば、これらのビットはクリアされる。結果として、プログラムコード（範囲は０ｘ００００００００から０ｘ００００ＦＦＦＦまで）の中のどこかで実行が継続することになる。最もありそうなこととして、そのように修正されたプログラムフローの場合、目標アドレスが意味をなさないので、例外が生じる。この例外としては、プログラムの実行を終了させる場合がある。しかしながら、注入されたコードの実行は、このようにして防止することができる。
【００６５】
マスクの適用を強制する提案した修正を適用するために、最初のステップにおいて、メソッドの終末部は、以下のａ）の処理からｂ）の処理へと変更される。
ａ）リターンアドレスをフェッチして、そこへジャンプする
ｂ）リターンアドレスをフェッチして、マスク及びリターンアドレスを用いて、例えば、ＡＮＤ操作（又は任意のビット単位操作）を実行し、次いで、そのＡＮＤ操作の結果へジャンプする
ヒープ及びスタックは、メモリ内のより高いアドレスに置かれているので、スタック又はヒープ内の場所を指し示すリターンアドレスは、コードセグメント内のアドレスには決して設定されることがない１つ以上のビットを常に有している。したがって、ＡＮＤ操作を用いて、コードセグメントの外側へコードが決してジャンプしないことを強制することができる。他のオペレーティングシステム又はプロセッサでは、他のビット単位操作が使用されてもよいことに留意すべきである。これらの他の操作の例は、ＯＲ、ＢＩＣ（ビットクリア）、又はリターンアドレス内のある数のビットをセット又はリセットし得る他の任意の操作である。
【００６６】
上述した対策は、標準ｒｅｔｕｒｎ−ｔｏ−ｌｉｂｃ攻撃が不可能になるという利点がある。なぜなら、ライブラリは、アプリケーションのコード領域の外側にロードされているからである。本明細書での「コード領域」は、「安全なメモリ範囲」又は攻撃者によって修正されていない正規のプログラムコードのみが置かれていることを期待されるメモリ範囲である。この範囲は、コンパイラによって決定され、次いで、対応するマスクが決定され得る。このマスクは、メモリ範囲０ｘ００００００００から０ｘ００００ＦＦＦＦまでの範囲へのジャンプを強制するものである。
【００６７】
他方、攻撃者は、アプリケーション内のｌｉｂｃを呼び出す命令へジャンプし得る。しかしながら、攻撃者は、アプリケーションによって使用されるｌｉｂｃメソッドへのジャンプしかできないので、危険は限定的なものとなる。
【００６８】
上記の例において、プログラムコードは、０ｘ００００００００から０ｘ００００ＦＦＦＦまでのメモリ範囲に置かれている。この例においては、マスクを容易に決定することができる。というのは、プログラムコードの最後のメモリ場所は、連続する論理「１」のみを含み、これによって、結果として得られるマスクも同じようなものとなるからである。しかしながら、プログラムコードの最後のメモリ場所が論理「０」も含むならば、プログラムコード区域を正確にマスクし、同時にプログラムコード区域の幾つかのアドレスを排除しないマスクを決定することはそれほど容易ではない。そのような場合、１つの実施形態によれば、プログラム・コード・メモリは、プログラムコードの最後のメモリアドレスが論理「１」のみで構成されるまで、ＮＯＰ命令、又はダミー命令あるいは存在しない命令で充填される。次いで、充填されたプログラムコードが置かれているメモリ範囲を正確にマスクすることによって、前述したのと同じやり方でマスクが生成され得る。
【００６９】
以下では、そのような状況において攻撃からの危険を更に制限することができる他の実施形態が説明される。
この実施形態において、提案されるメカニズムは、メソッドがアプリケーション内の任意のコードへジャンプすることを許容する代わりに、その任意のコードへのジャンプをコールする（呼び出す）メソッドへのみ戻ることを許容する。これを行うために、関数ごとに特有のマスクが計算される。このアプローチは、下記で更に説明されるように、コード又はバイナリ解析を必要とする。次の例を考える。
【００７０】
メソッド又は関数Ｍ１は、アドレス０ｘ０Ｂ３Ｅ（００００１０１１００１１１１１０）に置かれ、メソッドＭ２は、アドレス０ｘ０Ａ９８（００００１０１０１００１１０００）に置かれている。更に、前述したアドレスからＭ１及びＭ２によってのみＭ３が呼び出されると仮定する。この場合、マスク０ｘ０ＢＢＥ（００００１０１１１０１１１１１０）は、デフォルトマスク０ｘＦＦＦＦ（１１１１１１１１１１１１１１１１）よりもずっとうまく機能する。なぜなら、より特有なマスク０ｘ０ＢＢＥは、メソッドＭ３をＭ１又はＭ２へ戻すが、コード領域全体へは戻さないからである。この例のマスクは、関数Ｍ３が呼び出される２つのアドレス００００１０１１００１１１１１０及び００００１０１０１００１１０００を組み合わせることに基づいている。この例の組み合わせは、論理ＯＲであるが、結果として得られるマスクが、関数Ｍ３が呼び出された２つの場所のいずれかへ戻ることができる限り、他のビット単位操作も適用することができる。
【００７１】
したがって、この実施形態では、特に呼び出されるメソッド又は関数について、その関数が呼び出されるメモリ場所が識別される。次いで、これらの識別されたメモリ場所に基づいて、マスクが決定される。このマスクは、この関数に対して特有のものであり、この関数が呼び出された識別メモリ場所へ戻るようにする。
【００７２】
より正確に言えば、呼び出されたメソッド又は関数からそれを呼び出す関数へ戻るときは、呼び出しを行ったアドレスの次のアドレスへ常にジャンプするので、マスクは実際にそのようなアドレスに基づいて決定すべきである。言い換えれば、呼び出す操作が、００００１０１１００１１１１１０に置かれていれば、呼び出す操作に後続するプログラムフロー内の次の操作が置かれている次のアドレスが、マスクを決定するために使用されるべきである。もちろん、呼び出しを行う任意の場所についても、同じことが言える。呼び出す命令に後続する正規の命令であるプログラムフロー内の次の正規の命令へ戻るように、マスクが決定されるべきである。
【００７３】
しかしながら、使用される実際の実装又はコンパイラに依存して、ジャンプを引き起こした命令が置かれているメモリ場所へ直接ジャンプして戻ることも許容され得る。より一般的には、１つの実施形態によれば、呼び出しを行ったメソッド又は関数に所属する場所を、好ましくはビット単位操作、例えばＯＲにより組み合わせて、それらの場所に基づくマスクを生成することによって、関数又はメソッドコールからジャンプして戻る処理が、それらの場所へ限定される。
【００７４】
これらの関数特有のマスクは、プログラムコード範囲の全体よりも小さいアドレス範囲へ戻るように決定される方が好ましいことが明らかである。したがって、それらのマスクは、個々のコールアドレス（又は、これらのアドレスに後続するアドレス、上記を参照）に基づいて決定され、次いで、これらのコールアドレスは、マスクを生成するために組み合わせられる。このマスクは、適用されたときに、プログラムコード範囲の全体より小さい範囲をもたらし、このマスクは、より具体的には、関数が呼び出されたアドレスへ戻るようにする。
【００７５】
結果として得られるマスクは、関数特有のものなので、ある特定の関数からのリターン操作が識別されるとき、そのリターン操作の前に挿入されるマスキング操作は、その関数に対して特有のマスクを適用するという意味で、マスクを適用する操作の挿入も、もちろん関数特有のものである。
【００７６】
これらの関数特有のマスクは、バイナリファイルを解析することによって計算されるか、コンパイルプロセスの間に計算される。後者の場合、より良好なマスクを生成するために、メソッドを動かす追加のロジックがコンパイラへ追加されてもよい。これは、ある特定の他の関数を呼び出す異なる関数を実行して、それらの異なる関数が、類似するメモリアドレスに置かれるようにすることによって達成され得る。というのは、これは、論理「１」がより少なく且つ論理「０」がより多いマスクをもたらし、ジャンプが可能となるメモリ範囲を一層制限するからである。
【００７７】
しかしながら、説明された実施形態を用いる場合でも、攻撃者は、間接ポインタ上書き（indirect pointer overwrite）を実行し得る。これにより、攻撃者は、例えば、システムコール（例えば、ｐｒｉｎｔｆ）を攻撃者自身のコードへリダイレクト（変更）することができる。こうして、システムコールが次に実行されるとき、代わりに攻撃者のコードが実行される。これ（及び変形）を防御するために、１つの実施形態によれば、全ての計算されたジャンプ及びライブラリコールもマスクされる。ライブラリコールの場合、グローバル・オフセット・テーブル（ＧＯＴ）内のエントリが変更されないようにするために、プロシージャ・リンケージ・テーブル（ＰＬＴ）の中でマスキングが行われ得る。
【００７８】
この場合（マスキングがライブラリコールへ適用される場合）、マスクは、ロードされたライブラリが置かれたメモリ範囲に基づくものにすることができ、ライブラリコールに対応する各ジャンプの前にマスクを適用することができる。
【００７９】
更に、計算されたジャンプの場合、ジャンプの実行前にマスクが適用され得る。計算されたジャンプの場合、マスクは、プログラムコード区域に基づくものにすることができ、更にロードされたライブラリが置かれているメモリ範囲に基づくものにすることができる。
【００８０】
ライブラリを指し示すテーブル（ＧＯＴ及びＰＬＴ）内のアドレスは、通常、プログラムコードのアドレス範囲を指し示さない。ライブラリは、プログラムコードよりも高いアドレスへマップされているので、ジャンプが、プログラムコード区域へジャンプするようにマスクされるならば、ｌｉｂｃには決して到達することができない。マスクは、ライブラリが置かれている範囲を排除しないようにしており、なぜなら、そうしないと、プログラムが正しく実行されないからである。
【００８１】
他方、そのような場合、ｌｉｂｃライブラリによってカバーされる全メモリ範囲よりも狭いメモリ領域まで、目標アドレスを狭くするマスクを発見できることが好ましい。
【００８２】
しかしながら、全ライブラリ（ｌｉｂｃ）メモリ区域よりも狭いマスクを発見することは困難である。これは、依然として厳しい攻撃が残されている可能性があることを意味する。
【００８３】
この問題を解決するため、１つの実施形態によれば、ＧＯＴ（又はＰＬＴ）を読み出し専用（read-only）にすることができる。これは、いわゆる「ｍｅｍｐｒｏｔｅｃｔ」操作を実行することによって行うことができる。１つの実施形態によれば、ｍｅｍｐｒｏｔｅｃｔ操作は、「デフォルトセッティング」の一種として、言い換えれば、プログラムの正常な実行の間のセッティングとして使用され、ＧＯＴ（又はＰＬＴ）が読み出し専用に設定される。ライブラリがロードされると、ＧＯＴ又はＰＬＴは、短時間の間、書き込み可能に設定されて、その中のポインタの設定を可能にし、その後で再び読み出し専用に設定される。ｍｅｍｐｒｏｔｅｃｔコールは、メモリ区域を、読み出し専用から読み書き可能へ、及びこの逆へ、設定することができる。
【００８４】
これは、ライブラリがロードされるたびに、負担のかかるｍｅｍｐｒｏｔｅｃｔコールが実行されねばならない欠点を有するが、幸いなことに、アプリケーションのライフタイムの間に頻繁に起こらない。この場合、ＰＬＴ／ＧＯＴコード内で余分のＡＮＤ操作を省略できるという利点がある（全てのライブラリコールが少し早くなる）。
【００８５】
結果として、バッファをオーバーフローさせるとき、攻撃者はＧＯＴ（又はＰＬＴ）を修正することができない。というのは、それは書き込み保護され、注入されたコードを攻撃者は実行できないからである。攻撃者はｍｅｍｐｒｏｔｅｃｔコールも実行できない。
【００８６】
ここで、攻撃者がある特定のレジスタを制御できる場合に対処することができる更なる実施形態を説明する。
そのような場合、攻撃者は課された制限をうまく避けることができる。対策として、ライブラリ関数へのコールを、次のように変更した場合について考える。
［copy address of library function to register（ライブラリ関数のアドレスをレジスタへコピーする）］
［mask register（レジスタをマスクする）］
［jump to address in register（レジスタ内のアドレスへジャンプする）］
【００８７】
攻撃者がこのレジスタの内容をある程度制御できるならば、攻撃者は、リターン値を上書きして、［jump to address in register（レジスタ内のアドレスへジャンプする）］をポイントすることができる。この問題を解決する１つの方法は、メソッドコール及び計算されたジャンプを奇数アドレスに整列させることである。メソッドは、通常、関数を呼び出すその親メソッドの命令の直後に戻るので、これは常に偶数アドレスになる。その結果、マスクの最下位ビットは、常に０になるように選択され得る。これは、攻撃者が偶数アドレスへのみリターンすることを確実にする。計算されたジャンプは、奇数アドレスに整列するから、攻撃者は、ジャンプの前の命令（これはマスキング命令である）又はジャンプの後の命令へのみジャンプし得る。言い換えれば、攻撃者は、ジャンプ命令が置かれているメモリ場所へ直接ジャンプすることによってマスキング操作を迂回できない。
【００８８】
この方法は、コール及び計算されたジャンプが１００のビットマスクへ整列することを確実にすることによって、全ての命令が４バイト整列で記憶されるＲＩＳＣアーキテクチャへも拡張され得る。対策マスクの３つの最下位ビットは、０００へ設定され、１００のビットマスクに整列した命令へのリターンを妨げる。これは、アーキテクチャのデフォルト整列に依存して、任意に拡張され得る。
【００８９】
より一般的には、メソッドコール及び計算されたジャンプは、ある一定の区間又はこの区間のある倍数だけ分離されるアドレスで整列され得る。このようにして、ジャンプ命令の場所は、メモリアドレス空間内においてある特定のパターンに従っている。その特定のパターンは、マスクを決定するために使用されて、マスクをジャンプの目標アドレスへ適用するとき、ジャンプ命令が置かれているメモリ場所を排除する目標アドレスが得られるようにする。
【００９０】
代替の解決法は、ライブラリコールについて特別にレジスタを予約することである。これは、攻撃者がこのレジスタの内容に影響を及ぼすことができないことを確実にする。この解決法のインパクトは、プロセッサごとに異なる。というのは、これは、レジスタ圧力（register pressure）を増加させるからである。
【００９１】
上記で説明されたアプローチは、上書きされたリターンアドレスを用いて攻撃者が有用な何かを実行しようとするのを、既に厳しく妨げている。しかしながら、（バッファオーバーフローを用いるメソッドで使用されるマスクの精密度に依存して）システムコール又はライブラリコールを呼び出すコードメモリ内の場所を、リターンアドレスにポイントすることが依然として可能である。この問題を更に緩和するための１つのプラットフォーム特有のやり方は、プロセッサ特有の特徴、例えば、ＡＲＭプロセッサの条件付き実行を利用することである。ＡＲＭプロセッサについては、非特許文献５に記載されている。
【００９２】
このアプローチは、ＡＲＭプロセッサのアーキテクチャの特有の特徴、即ち、条件付き実行を使用する。「キャリー（carry）」ビットがセットされていれば、ある特定の命令のみが実行可能であり、「キャリー」ビットがセットされていなければ、全ての他の命令が実行可能であるという処理を行うことによって、追加の保護が与えられる。
【００９３】
この実施形態において、キャリーがセットされていないか（キャリークリア−ｃｃ）、セットされていれば（キャリーセット−ｃｓ）、全ての命令は、条件付き実行可能としてマークされていることになる（命令名のサフィックスとしての「ｃｃ」又は「ｃｓ」）。リターンアドレスのマスキングを行う命令（下記のコード例では操作０３）は、キャリービットをセットする（命令名のサフィックス「ｓ」は、キャリー・ビット・セットを得る）。呼び出す関数へのリターン分岐と、関数をコールした後の命令（例示的コードの命令０４及び０８）は、キャリービットがセットされていれば（「ｃｓ」のサフィックス）実行される。
【００９４】
ここで、攻撃者がリターンアドレスを上書きできれば、目標アドレスをマスクする（正規の）マスキング命令は、前の実施形態と関連して説明されたように、プログラムコードが１で終了することについて対処する。追加の副次的効果として、キャリービットは操作０３によってセットされる。このようにして、条件付き実行可能パラメータが「キャリー・ビット・セット」であるようにマークされた命令でのみプログラムフローが進行することを保証し得る。これは、関数コールからのリターン処理を実行する命令（下記のコードでは命令０４）及びリターンに後続する命令（下記のコードでは命令０８）の場合である。
【００９５】
このようにして、たとえ攻撃者がリターンアドレスを修正できたとしても、修正されたリターンアドレスに置かれた命令は、依然として実行されない。なぜなら、この命令は、パラメータ「キャリー・フラグ・セット」で条件付き実行可能としてマークされていないからである。
【００９６】
アプローチは、ここで幾分異なる語句によって説明される。
最初のステップにおいて、全ての命令は、例えば、キャリーがクリアされるとき、条件付きでのみ実行するようにマークされなければならない。次いで、リターンアドレスをマスクする命令が選択され、キャリーフラグをセットするように修正される（下記で与えられるコード例では命令０３）。メソッドから戻るために使用される次のジャンプは、この命令の「ｃｓ」サフィックスから分かるように、キャリーフラグがセットされるならば、条件付きで実行される。更に、リターンが向けられる命令（下記のコードの命令０８）は、キャリーフラグがセットされるならば、条件付きで実行される。したがって、たとえ攻撃者が、リターン命令（下記のコードの命令０４）がジャンプする場所に影響を与えることができたとしても、攻撃者は、キャリーがセットされているときに実行する命令があるアドレスへ制限される。これは、ライブラリ関数を呼び出す命令を含めて、アプリケーション全体のほとんど全ての命令を排除する。したがって、このアプローチは攻撃者を更に妨げる。というのは、攻撃者は、メソッドコール（ライブラリメソッドコールを除いて）が戻る正常な命令へのみにしかジャンプできないからである。
【００９７】
次の例を考える。
ｓｕｍ：＃パラメータａ及びｂを加算して，結果を戻す
＃この命令は、
＃キャリーフラグがクリアされている場合にのみ実行する
０１：        ａｄｄｃｃ  ｒ０，ｒ０，ｒ１
＃リターン；結果はｒ０の中にある
＃ｒ１０を０ｘＦＦＦＦＦＦへセットする
０２：        ｍｏｖｃｃ  ｒ１０，＃−１
＃リターンアドレス（「ｌｒ」の中にある）をマスクする
＃０ｘ００００ＦＦＦＦを用いる。更に
＃キャリーを再びセットする
０３：        ｂｉｃｃｃｓ  ｌｒ，ｒ１０，ＬＳＬ  ＃１６
＃キャリーは現在セットされている。コール側へ戻る
０４：        ｂｘｃｓ  ｌｒ
親：＜他の命令＞
０５：        ｍｏｖｃｃ  ｒ０，＃１
０６：        ｍｏｖｃｃ  ｒ１，＃１
０７：        ｂｌｃｃ  ｓｕｍ
＃キャリーをクリアする
０８：        ｍｏｖｃｓｓ  ｒ１０，ｐｃ，ＬＳＲ  ＃１
＃キャリーフラグは現在クリアされている
０９：        ｌｄｒｃｃ  ｒ０，Ｌ０
１０：        ｂｌｃｃ  ｐｒｉｎｔｆ
＜他の命令＞
【００９８】
この例において、攻撃者が関数「ｓｕｍ」の中でリターンアドレスを変更できるならば、攻撃者は命令０４及び命令０８へのみジャンプできる。というのは、これらの命令はキャリーフラグがセットされている場合のみ実行可能な命令だからである。全ての他の命令はアクセス不可能である。なぜなら、それらの命令はキャリーフラグがクリアされることを必要とするからである。
【００９９】
言い換えれば、マスキングは、プログラムフローの「条件付き実行可能」パラメータ、ここではキャリーフラグを変更することによって、更に向上される。プログラム全体の命令について、「条件付き実行可能」パラメータがセットされていない場合にのみ命令が実行されるように、これらの命令の設定が行われる。しかしながら、マスキングの後でジャンプを実際に実行する操作については、及びジャンプの後で実行されるべき操作については、条件付き実行可能パラメータがセットされている場合にのみ操作が実行されるように設定が行われる。このようにして、ジャンプに続く正しい操作を除く全ての他の操作が阻止される。
【０１００】
これまで説明された実施形態は、ハードウェア、ソフトウェア、又はソフトウェアとハードウェアとの組み合わせによって実装され得ることが、当業者によって理解される。本発明の実施形態と関連して説明されたモジュール及び機能は、全体的又は部分的に、マイクロプロセッサ又はコンピュータによって実装され得る。これらのマイクロプロセッサ又はコンピュータは、本発明の実施形態と関連して説明された方法に従って動作するように適切にプログラムされる。本発明の実施形態を実装する装置は、例えば、コンピューティングデバイス又は移動電話又は任意のモバイルデバイス又は移動局、又は本発明の実施形態で説明された方法を実行し得るように適切にプログラムされるノードで構成される。
【０１０１】
本発明の実施形態によれば、コンピュータプログラムが提供される。このコンピュータプログラムは、データキャリアに記憶されるか、ある物理手段、例えば、記録メディア又は伝送リンクによって具現化された他のやり方で記憶される。また、このコンピュータプログラムは、コンピュータ上で実行するときに、これまでに説明された本発明の実施形態に従ってコンピュータを動作させるものである。
【図１】
2011008778.tif 000003
【図２】
2011008778.tif 000004
【外国語明細書】
2011008778.tif 000005
2011008778.tif 000006
2011008778.tif 000007
2011008778.tif 000008
2011008778.tif 000009
2011008778.tif 000010
2011008778.tif 000011
2011008778.tif 000012
2011008778.tif 000013
2011008778.tif 000014
2011008778.tif 000015
2011008778.tif 000016
2011008778.tif 000017
2011008778.tif 000018
2011008778.tif 000019
2011008778.tif 000020
2011008778.tif 000021
2011008778.tif 000022
2011008778.tif 000023
2011008778.tif 000024
2011008778.tif 000025
2011008778.tif 000026
2011008778.tif 000027
2011008778.tif 000028
2011008778.tif 000029
2011008778.tif 000030
2011008778.tif 000031
2011008778.tif 000032
2011008778.tif 000033
2011008778.tif 000034
2011008778.tif 000035
2011008778.tif 000036