(57)【特許請求の範囲】
【請求項１】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させる、
ことを特徴とするプログラム。
【請求項２】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
前記仮想マシン上での前記代替コードの実行から前記ネイティブ環境における前記保護済みプログラム中の前記代替コードの次の部分の実行に戻る時点で、この時点での前記仮想文脈の少なくとも一部を前記ネイティブ環境の文脈に書き戻す書き戻し手段、
として機能させることを特徴とするプログラム。
【請求項３】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させるためのものであり、
前記仮想マシンは、前記保護対象部分中の、前記ネイティブ環境上で実行されるネイティブ実行コードを呼び出す呼び出し命令を実行する場合に、当該呼び出し命令の実行直前の時点での前記仮想マシンの前記仮想文脈を前記ネイティブ環境の前記文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記呼び出し命令を実行する、ことを特徴とするプログラム。
【請求項４】
前記仮想マシンは、前記ネイティブ実行コードから前記保護対象部分に戻る戻り命令を受けた場合に、当該戻り命令の実行直前の時点での前記ネイティブ環境の前記文脈を前記仮想マシンの前記仮想文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記戻り命令を実行する、ことを特徴とする請求項３に記載のプログラム。
【請求項５】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させるためのものであり、
前記仮想マシンは、前記ネイティブ環境の命令コード体系である第１の命令コード体系とは異なる第２の命令コード体系を用いるものであり、
前記保護前プログラムは前記第１の命令コード体系で記述されており、
前記移動配置手段は、前記保護前プログラム中の前記保護対象部分の前記第１の命令コード体系での記述を、前記第２の命令コード体系での記述に変換し、この変換を行った後の保護対象部分を前記第２の配置場所に移動して配置する、
ことを特徴とするプログラム。
【請求項６】
前記移動配置手段は、前記第２の命令コード体系に変換を行った後の保護対象部分を暗号化し、暗号化済みの保護対象部分を、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードと共に、前記第２の配置場所に配置する、
ことを特徴とする請求項５に記載のプログラム。
【請求項７】
前記移動配置手段は、前記第２の命令コード体系に変換を行った後の保護対象部分を暗号化し、この暗号化済みの保護対象部分を前記第２の配置場所に配置し、
前記代替コードは、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードを含む、
ことを特徴とする請求項５に記載のプログラム。
【請求項８】
前記代替コードは、前記ネイティブ環境を、
デバッガにより前記保護済みプログラムの解析が行われているか否かを判定する手段、
前記デバッガにより前記保護済みプログラムの解析が行われていないと判定される場合には、前記暗号化の後の保護対象部分を正しく復号できる第１の復号鍵を、前記デバッガにより前記保護済みプログラムの解析が行われていると判定される場合には、前記暗号化の後の保護対象部分を正しく復号できない第２の復号鍵を生成する鍵生成手段、
として機能させ、
前記復号コードは、前記ネイティブ環境を、前記第１の復号鍵及び前記第２の復号鍵のうち前記鍵生成手段が生成したものを用いて前記ネイティブ環境に前記暗号化の保護対象部分を復号させる、
ことを特徴とする請求項６又は７に記載のプログラム。
【請求項９】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させるためのものであり、
前記移動配置手段は、前記保護対象部分を暗号化し、この暗号化済みの保護対象部分を、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードと共に、前記第２の配置場所に配置する、
ことを特徴とするプログラム。
【請求項１０】
コンピュータを、
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、
として機能させることで保護済みプログラムを生成するためのプログラムであって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させるためのものであり、
前記移動配置手段は、前記保護対象部分を暗号化し、この暗号化済みの保護対象部分を前記第２の配置場所に配置し、
前記代替コードは、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードを含む、
ことを特徴とするプログラム。
【請求項１１】
保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段と、
前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段と、
前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段と、
を有し、前記保護前プログラムから保護済みプログラムを生成するプログラム保護装置であって、
前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させる、
ことを特徴とするプログラム保護装置。
【請求項１２】
保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、
前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させる、
ことを特徴とする保護済みプログラム。
【請求項１３】
保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、
前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
前記仮想マシン上での前記代替コードの実行から前記ネイティブ環境における前記保護前プログラム中の前記代替コードの次の部分の実行に戻る時点で、この時点での前記仮想文脈の少なくとも一部を前記ネイティブ環境の文脈に書き戻す書き戻し手段、
として機能させることを特徴とする保護済みプログラム。
【請求項１４】
保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、
前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、
前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、
前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、
として機能させるためのものであり、
前記仮想マシンは、前記保護対象部分中の、前記ネイティブ環境上で実行されるネイティブ実行コードを呼び出す呼び出し命令を実行する場合に、当該呼び出し命令の実行直前の時点での前記仮想マシンの前記仮想文脈を前記ネイティブ環境の前記文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記呼び出し命令を実行する、ことを特徴とする保護済みプログラム。
【請求項１５】
前記仮想マシンは、前記ネイティブ実行コードから前記保護対象部分に戻る戻り命令を受けた場合に、当該戻り命令の実行直前の時点での前記ネイティブ環境の前記文脈を前記仮想マシンの前記仮想文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記戻り命令を実行する、ことを特徴とする請求項１４に記載の保護済みプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラム、及びプログラム保護装置に関する。
【背景技術】
【０００２】
コンピュータで実行されるコード内に含まれる秘密を秘匿するため、または、コードを改竄されないために、そのコードを独自の仮想マシン（仮想のＣＰＵ）の命令で記述する方式が知られている。この方式では、仮想マシンの命令で記述したコードを実際のコンピュータ（ネイティブ環境）でエミュレーション実行することで、コード解析を難しくする。
【０００３】
例えば、特許文献１及び２には、仮想マシン（以下「ＶＭ」と略す。ＶＭはVirtual Machineの略）上で動作する(例えばJava（登録商標）で記述された)コードを暗号化しておき、実際のコンピュータでの実行前にそのコードを復号してから実行する技術が開示されている。これらの文献では、各ＶＭ上の閉じた環境で動作するコードを暗号化する方法を示すのみである。
【０００４】
また、非特許文献１には、保護したいコードを、開示されていない独自のコードで表現するか、或いはその独自のコードにコンパイルしておき、その独自のコードを実行する独自のＶＭとともに配布することで、コードを難読化する手法が開示されている。この手法では、解析者からみると、独自のコード体系を理解するという手間が増大するため、解析が困難になる。
【０００５】
このように、保護対象のプログラムを独自コードで記述することで保護する方式では、プログラマがその独自の仮想マシン用にコードを記述するか、又は高級言語で記述したコードをその仮想マシン用の命令にコンパイルするコンパイラを作成する必要がある。
【０００６】
独自の仮想マシン用のコードを実際のコンピュータ（ネイティブ環境）上でエミュレーション実行する場合、その実行速度は、そのコンピュータ用のネイティブコードの実行速度よりはるかに遅い。このため、大規模な実行プログラムの全体を仮にその独自コードで記述してエミュレーション実行したのでは、実行速度が著しく遅くなってしまう。
【０００７】
またＪＮＩ（Java（登録商標） Native Interface）のように、ＶＭ上でエミュレーション実行されているコードから、ネイティブ環境のＣＰＵで実行されるライブラリを呼び出し、エミュレーション実行とネイティブ環境で実行するプログラムを混在させる技術も存在する。この技術では、プログラムを記述する人は、そのライブラリ呼び出し用にプログラムコードを記述する必要があり、プログラムの作成に付加的な知識と作業が必要になる。
【先行技術文献】
【特許文献】
【０００８】
【特許文献１】特開平１０−３０１７７２号公報
【特許文献２】特許第４４３１４０９号明細書
【特許文献３】特開２００７−１４８５７５号公報
【非特許文献】
【０００９】
【非特許文献１】「C/C++セキュアプログラミングクックブック」Volume.1, page 131, John Viega， Matt Messier著, オライリージャパン,初版, 2004年9月
【発明の概要】
【発明が解決しようとする課題】
【００１０】
本発明は、プログラムのうち保護対象とする部分について仮想マシン上での実行による保護を図りつつも、残りの部分についてはネイティブ環境での実行による高速化を図ることと目的とする。
【課題を解決するための手段】
【００１１】
請求項１に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させる、ことを特徴とするプログラムである。
【００１２】
請求項２に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、前記仮想マシン上での前記代替コードの実行から前記ネイティブ環境における前記保護済みプログラム中の前記代替コードの次の部分の実行に戻る時点で、この時点での前記仮想文脈の少なくとも一部を前記ネイティブ環境の文脈に書き戻す書き戻し手段、として機能させることを特徴とするプログラムである。
【００１３】
請求項３に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させるためのものであり、前記仮想マシンは、前記保護対象部分中の、前記ネイティブ環境上で実行されるネイティブ実行コードを呼び出す呼び出し命令を実行する場合に、当該呼び出し命令の実行直前の時点での前記仮想マシンの前記仮想文脈を前記ネイティブ環境の前記文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記呼び出し命令を実行する、ことを特徴とするプログラムである。
【００１４】
請求項４に係る発明は、前記仮想マシンは、前記ネイティブ実行コードから前記保護対象部分に戻る戻り命令を受けた場合に、当該戻り命令の実行直前の時点での前記ネイティブ環境の前記文脈を前記仮想マシンの前記仮想文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記戻り命令を実行する、ことを特徴とする請求項３に記載のプログラムである。
【００１５】
請求項５に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させるためのものであり、前記仮想マシンは、前記ネイティブ環境の命令コード体系である第１の命令コード体系とは異なる第２の命令コード体系を用いるものであり、前記保護前プログラムは前記第１の命令コード体系で記述されており、前記移動配置手段は、前記保護前プログラム中の前記保護対象部分の前記第１の命令コード体系での記述を、前記第２の命令コード体系での記述に変換し、この変換を行った後の保護対象部分を前記第２の配置場所に移動して配置する、ことを特徴とするプログラムである。
【００１６】
請求項６に係る発明は、前記移動配置手段は、前記第２の命令コード体系に変換を行った後の保護対象部分を暗号化し、この暗号化済みの保護対象部分を、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードと共に、前記第２の配置場所に配置する、ことを特徴とする請求項５に記載のプログラムである。
【００１７】
請求項７に係る発明は、前記移動配置手段は、前記第２の命令コード体系に変換を行った後の保護対象部分を暗号化し、この暗号化済みの保護対象部分を前記第２の配置場所に配置し、前記代替コードは、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードを含む、ことを特徴とする請求項５に記載のプログラムである。
【００１８】
請求項８に係る発明は、前記代替コードは、前記ネイティブ環境を、デバッガにより前記保護済みプログラムの解析が行われているか否かを判定する手段、前記デバッガにより前記保護済みプログラムの解析が行われていないと判定される場合には、前記暗号化の後の保護対象部分を正しく復号できる第１の復号鍵を、前記デバッガにより前記保護済みプログラムの解析が行われていると判定される場合には、前記暗号化の後の保護対象部分を正しく復号できない第２の復号鍵を生成する鍵生成手段、として機能させ、前記復号コードは、前記ネイティブ環境を、前記第１の復号鍵及び前記第２の復号鍵のうち前記鍵生成手段が生成したものを用いて前記ネイティブ環境に前記暗号化の保護対象部分を復号させる、ことを特徴とする請求項６又は７に記載のプログラムである。
【００１９】
請求項９に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させるためのものであり、前記移動配置手段は、前記保護対象部分を暗号化し、この暗号化済みの保護対象部分を、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードと共に、前記第２の配置場所に配置する、ことを特徴とするプログラムである。
【００２０】
請求項１０に係る発明は、コンピュータを、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段、として機能させることで保護済みプログラムを生成するためのプログラムであって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させるためのものであり、前記移動配置手段は、前記保護対象部分を暗号化し、この暗号化済みの保護対象部分を前記第２の配置場所に配置し、前記代替コードは、前記ネイティブ環境に前記暗号化済みの保護対象部分を復号させるための復号コードを含む、ことを特徴とするプログラムである。
【００２１】
請求項１１に係る発明は、保護前プログラム中の、保護対象とする保護対象部分の指定を受け付ける指定受付手段と、前記保護前プログラム中の前記保護対象部分を、前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に移動して配置する移動配置手段と、前記保護前プログラム中の前記保護対象部分を代替コードに変更する変更手段と、を有し、前記保護前プログラムから保護済みプログラムを生成するプログラム保護装置であって、前記代替コードは、前記保護済みプログラムを実行するコンピュータ上に実現されたネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させる、ことを特徴とするプログラム保護装置である。
請求項１２に係る発明は、保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内の、前記保護済みプログラムを実行するために用いられているメモリ領域内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記メモリ領域を用いて前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させる、ことを特徴とする保護済みプログラムである。
請求項１３に係る発明は、保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、前記仮想マシン上での前記代替コードの実行から前記ネイティブ環境における前記保護前プログラム中の前記代替コードの次の部分の実行に戻る時点で、この時点での前記仮想文脈の少なくとも一部を前記ネイティブ環境の文脈に書き戻す書き戻し手段、として機能させることを特徴とする保護済みプログラムである。
請求項１４に係る発明は、保護前プログラム中の保護対象部分に該当する部分が代替コードに変更されていると共に、前記保護対象部分は前記保護前プログラム中での前記保護対象部分の配置場所である第１の配置場所とは異なる第２の配置場所に配置されている、保護済みプログラムであって、前記代替コードは、コンピュータ上に実現された、前記保護済みプログラムを実行するネイティブ環境を、前記保護済みプログラムを前記代替コードの実行に移行する直前まで実行した時点での前記ネイティブ環境の文脈を、前記ネイティブ環境のメモリ内に、仮想マシン用の仮想文脈として再構築する再構築手段、前記仮想マシンを実行し、前記再構築手段により再構築された前記仮想文脈の前記メモリ内でのアドレスを示す情報を前記仮想マシンに渡すことで、前記仮想マシンが前記仮想文脈を用いて前記保護対象部分を実行するようにする、仮想マシン実行手段、として機能させるためのものであり、前記仮想マシンは、前記保護対象部分中の、前記ネイティブ環境上で実行されるネイティブ実行コードを呼び出す呼び出し命令を実行する場合に、当該呼び出し命令の実行直前の時点での前記仮想マシンの前記仮想文脈を前記ネイティブ環境の前記文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記呼び出し命令を実行する、ことを特徴とする保護済みプログラムである。
請求項１５に係る発明は、前記仮想マシンは、前記ネイティブ実行コードから前記保護対象部分に戻る戻り命令を受けた場合に、当該戻り命令の実行直前の時点での前記ネイティブ環境の前記文脈を前記仮想マシンの前記仮想文脈に書き戻す処理を実行し、この書き戻しの処理の後に前記戻り命令を実行する、ことを特徴とする請求項１４に記載の保護済みプログラムである。
【発明の効果】
【００２２】
請求項１又は１１に係る発明によれば、プログラムのうち保護対象とする部分について仮想マシン上での実行による保護を図りつつも、残りの部分についてはネイティブ環境での実行による高速化を図ることができる。
【００２３】
請求項２に係る発明によれば、プログラム中の保護対象部分の後の部分をネイティブ環境で正しく実行することができる。
【００２４】
請求項３に係る発明によれば、仮想マシン上での保護対象部分の実行による文脈をネイティブ環境に引き継いで、ネイティブ環境上でネイティブ実行コードを実行することができる。
【００２５】
請求項４に係る発明によれば、ネイティブ実行コードの実行の後、その実行による文脈を引き継いで、仮想マシンに戻って保護対象部分を実行することができる。
【００２６】
請求項５に係る発明によれば、保護対象部分を第１の命令コード体系で記述する場合と比較して、保護対象部分の保護を強化することができる。
【００２７】
請求項６又は７又は９又は１０に係る発明によれば、保護対象部分を暗号化しない場合と比較して、保護対象部分の保護を強化することができる。
【００２８】
請求項８に係る発明によれば、保護対象部分をデバッガによる解析から保護することができる。
【図面の簡単な説明】
【００２９】
【図１】実施形態のプログラムの保護の仕組みを説明するための図である。
【図２】ラップコードの内容の一例を示す図である。
【図３】仮想マシン上で実行される保護対象部分から外部関数を呼び出す処理の手順の一例を示す図である。
【図４】実施形態のプログラム保護装置の一例を示す機能ブロック図である。
【図５】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に保護対象部分の呼び出し時点の状態を示す図である。
【図６】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に文脈維持コードＡを実行後の状態を示す図である。
【図７】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシン呼び出し時点の状態を示す図である。
【図８】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンによる保護対象部分の実行開始時点の状態を示す図である。
【図９】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンによる保護対象部分の実行中の状態を示す図である。
【図１０】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンによる保護対象部分の実行において、スタック内の誤った引数が読み出されるケースを説明するための図である。特に保護対象部分の呼び出し時点の状態を示す図である。
【図１１】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンで実行中の保護対象部分から外部関数を呼び出す時点の状態を示す図である。
【図１２】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に外部関数呼び出しの前に文脈維持コードが実行された時点の状態を示す図である。
【図１３】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に外部関数の呼び出し直後の時点の状態を示す図である。
【図１４】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に呼び出した外部関数を実行中の状態を示す図である。
【図１５】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に呼び出した外部関数から保護対象部分に戻る時点の状態を示す図である。
【図１６】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に呼び出した外部関数から保護対象部分に戻る際の文脈維持コードが実行された時点の状態を示す図である。
【図１７】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンによる保護対象部分の実行が完了した時点の状態を示す図である。
【図１８】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に保護対象部分の実行からラップコードの実行に戻った時点の状態を示す図である。
【図１９】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンからネイティブ環境に戻った後の文脈維持コードＣの実行後の状態を示す図である。
【図２０】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に文脈維持コードＣの実行後、非保護対象部分の実行に処理が戻った時点の状態を示す図である。
【図２１】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンに対して正しい引数を渡すために引数コピー方式を用いた場合の、仮想マシンによる保護対象部分の実行開始時点の状態を示す図である。
【図２２】実施形態の装置により保護されたプログラムを実行する際の、ネイティブ環境の実スタック及び実レジスタ群の状態を示す図であり、特に仮想マシンに対して正しい引数を渡すために引数コピー方式を用いた場合の、仮想マシンによる保護対象部分の実行中の状態を示す図である。
【図２３】保護対象関数を暗号化する場合のオブジェクトコードのデータ構造の一例を示す図である。
【発明を実施するための形態】
【００３０】
本実施形態では、プログラムの一部（「保護対象部分」と呼ぶ。プログラム中に複数の保護対象部分が存在してもよい）を、メモリ上の、実行可能なプログラムコードが通常置かれる場所（テキスト領域又はコード領域と呼ばれる）とは異なる場所に移動し、仮想マシン上で実行することにより、例えば、保護対象部分の保護（秘密漏洩や改竄等を受ける可能性の低減）を図る。
【００３１】
一方、プログラムのうち保護対象部分以外の部分（「非保護対象部分」と呼ぶ）は、ネイティブ環境で直接実行することで、（エミュレーション実行、すなわち仮想マシン上での実行、よりもはるかに）高速な処理を実現する。
【００３２】
ネイティブ環境とは、典型的には、物理的なＣＰＵ（中央演算装置）上でプログラムを実行する実行環境のことである。ただし、物理的なＣＰＵ上でエミュレートされる第１の仮想マシン上で、第２の仮想マシンをエミュレートする場合も考えられ、そのような場合、第１の仮想マシンは第２の仮想マシンにとってのネイティブ環境である。例えば、第１の仮想マシン上で実行されるプログラムの一部（保護対象部分）を、別の仮想マシンである第２の仮想マシン用のコードに変換することで保護する場合もあり得る。
【００３３】
これに対して、仮想マシンは、ネイティブ環境上でエミュレートされる仮想的なコンピュータ（ＣＰＵ：中央演算装置）である。すなわち、仮想マシンの動作を記述したエミュレーションプログラムをネイティブ環境で実行することにより、仮想マシンが構築され、この仮想マシンが、仮想マシン用のプログラム（本実施形態では「保護対象部分」のプログラムコード）を実行する。
【００３４】
このようなプログラムの部分的なエミュレーション実行のために、本実施形態では、プログラムの実行環境がネイティブ環境と仮想環境（仮想マシン）との間で切り替わる際に、両環境間で文脈（コンテキスト）を維持する仕組みをそのプログラムに組み込む。ここでいう文脈とは、プログラムを実行している環境（ネイティブ環境又は仮想環境）の状態のことであり、マルチタスク処理でのタスク（プロセス）切り替え時に行われるコンテキストスイッチ処理において保存されたり復元されたりする、タスクのコンテキストと同様のものである。具体的には、文脈は、プログラム実行中の当該環境内のレジスタ等の値のことである。
【００３５】
このような保護の枠組みを、図１及び図２を参照して更に詳しく説明する。
【００３６】
図１の左側に模式的に示すオブジェクトコード（オブジェクトファイル）１００は、部分保護の対象であるプログラムのソースコードをコンパイルしたものであり、本実施形態の保護処理を受ける前の状態のものである。オブジェクトコード１００には、テキスト領域１１０やデータ領域１２０等のセクションが含まれる。テキスト領域１１０は、コード領域とも呼ばれ、プログラムのネイティブコード１１２（ネイティブ環境が直接実行できる機械語等で記述されている）が配置される領域である。データ領域１２０は、プログラムが用いるデータ（例えば初期値のある変数等）がおかれる領域である。プログラム実行の際、オブジェクトコード１００中のテキスト領域１１０にあるネイティブコードは、ネイティブ環境（一般にはそのプログラムを実行するコンピュータ）のメモリ（一次記憶）内の実行可能なメモリ領域（テキスト領域又はコード領域と呼ばれる）にロードされ、データ領域１２０にあるデータはネイティブ環境のメモリ内の書き込み可能なメモリ領域（データ領域と呼ばれる）にロードされる。
【００３７】
本実施形態では、ユーザ（プログラマ等）がプログラムのうち、保護したい保護対象部分１１４を指定する。保護対象部分１１４は、例えば関数を単位としたもの（１以上の関数の集まり）と指定される。ただし、これは一例に過ぎない。本実施形態の実行環境（ネイティブと仮想マシン）切り替えにおける文脈維持機構は、プログラムのどの場所で環境を切り替えても動作するので、切り替えの界面（すなわち保護対象部分１１４と非保護対象部分の境目）は関数に限らない。
【００３８】
また、図１の右側に示すオブジェクトコード２００は、オブジェクトコード１００に対して、本実施形態の保護処理を施した結果生成されるオブジェクトコードである。
【００３９】
本実施形態の保護処理では、指定された保護対象部分１１４のコードを、リロケーションデータ等と共に、オブジェクトコード２００のデータ領域２２０に移動する（保護対象部分２２２）。これにより、保護対象部分２２２は、ネイティブ環境のメモリにロードされる際、そのメモリ内のコード領域ではなくデータ領域にロードされることになる。攻撃者が実行中のプログラムを解析する場合、コード領域内のプログラムコードを解析することから手を付けることが多いので、データ領域にある保護対象部分２２２はコード領域内の非保護対象部分よりも解析される可能性が低い。
【００４０】
一方、テキスト領域１１０内のネイティブコード１１２のうちの保護対象部分１１４は、ラップコード２１４（その内容は後述）に変更する。また、ネイティブコード１１２のうち非保護対象部分（保護対象部分１１４以外の部分）は変更しない。これにより、保護処理済みのオブジェクトコード２００のテキスト領域２１０内には、保護対象部分１１４がラップコード２１４に変更されたネイティブコード２１２が配置されることとなる。
【００４１】
なお、保護対象部分１１４のラップコード２１４への変更では、前者よりも後者の方がコードサイズが大きければ、単にネイティブコード１１２から前者を削除し、この削除により空いた場所（アドレス空間）に後者を挿入するという処理でよい。逆に前者よりも後者の方がコードサイズが小さければ、後者すなわちラップコード２１４をテキスト領域２１０内の空いている場所に配置すると共に、前者すなわち保護対象部分１１４の削除により空いた場所にはそのラップコードを呼び出す命令を配置する等の処置を行えばよい。
【００４２】
図２に、ラップコード２１４のコード内容を模式的に示す。図示のように、ラップコード２１４内には、文脈維持コードＡ、仮想マシン呼び出しコードＢ、及び文脈維持コードＣが含まれる。
【００４３】
文脈維持コードＡは、仮想マシンの実行の直前に実行され、ネイティブ環境から仮想マシンへの実行環境の切り替えの際の文脈の維持のための処理を記述したコードである。すなわち、文脈維持コードＡは、メモリ上（例えばスタック又は書き込み可能なデータ領域）に仮想マシン用の文脈を保持する領域（仮想文脈領域と呼ぶ）を確保し、その領域に対し、ネイティブコード２１２の非保護対象部分のうち保護対象部分１１４の直前まで実行した時点での文脈（例えばＣＰＵのレジスタの値）を格納するという処理を、ネイティブ環境に実行させるためのネイティブコードである。仮想文脈領域には、例えば、レジスタの状態を引き継ぐための仮想レジスタ領域がある。ネイティブ環境によるネイティブコード２１２の実行がラップコード２１４まで達すると、まずこの文脈維持コードＡが実行される。
【００４４】
仮想マシン呼び出しコードＢは、仮想マシンをエミュレートするためのエミュレーション関数を呼び出すコードである。文脈維持コードＡの実行の後、この仮想マシン呼び出しコードＢが実行される。
【００４５】
エミュレーション関数は、（ａ）データ領域２２０内にある保護対象部分２２２のコードを指すアドレスの情報、を引数としており、呼び出されネイティブ環境で実行されたエミュレーション関数（すなわち仮想マシン）は、この引数を用いてメモリのデータ領域にロードされた保護対象部分２２２にアクセスし、その保護対象部分２２２を実行する。なお、保護対象部分２２２の大きさがエミュレーション関数にとって既知でない場合は、その（ｂ）保護対象部分２２２の大きさ、の情報を引数としてエミュレーション関数に渡せばよい。また、実行されたエミュレーション関数（すなわち仮想マシン）は、仮想レジスタ領域をレジスタとして用いて演算処理を実行するので、エミュレーション関数には、文脈維持コードＡが確保した（ｃ）仮想レジスタ領域へのポインタ、を引数として渡す。なお、仮想レジスタ領域の大きさがエミュレーション関数にとって既知である場合（例えば元のプログラムが、使用するレジスタの数等に対する取り決めに従っている場合など）は、仮想レジスタ領域へのポインタは渡す必要がない。また、エミュレーション関数（仮想マシン）は、エミュレーション関数呼び出しまでのネイティブ環境でのネイティブコード２１２の実行により積まれたスタック（レジスタ以外で渡される引数や関数の戻りアドレスが格納されている）の情報を文脈として用いて演算処理を進めるので、エミュレーション関数には、（ｄ）その呼び出しの時点でのメモリ上のスタックの先頭へのポインタ、を引数として渡す。なお、呼び出し元で使用しているスタックの深さがエミュレーション関数にとって既知の場合(例えば文脈維持コードを含むラップコードが使用するスタックの大きさが前もって定まっている場合)には、スタックの先頭へのポインタを引数として渡す必要がない。
【００４６】
ネイティブ環境で実行されるエミュレーション関数（仮想マシン）は、当該関数の前処理(プロローグ)において、関数の呼び出し規約上破壊してはいけないレジスタの値をスタック上に確保した退避領域に退避した後に、エミュレーション実行で必要となる自動変更領域をスタックに確保する。そして、まだ使用されていないスタック(例えばその時点のスタックの先頭)の先頭アドレスを、当該仮想マシンが保護対象部分２２２の実行で使用するスタックの先頭を示すポインタとして、文脈維持コードＡの実行により確保された仮想レジスタ領域内の特定のレジスタｓｐ（スタックポインタ)に書き込み、エミュレーションを開始する。
【００４７】
ネイティブ環境上でエミュレートされる仮想マシン（エミュレーション関数）は、引数で渡されたアドレスを用いてデータ領域内の保護対象部分２２２を読み、その部分２２２に示される命令の指示に従って、メモリ上の仮想レジスタ領域、スタック及び、通常のデータ領域を用いて処理を逐時進めていく。そして、エミュレーション実行が、エミュレーション関数内の戻り命令(ret命令)に到達した所で、ラップコード２１４に処理が戻る。
【００４８】
エミュレーション関数からラップコード２１４に処理が戻る際には、当該関数の後処理(エピローグ)の時に、プロローグ時に退避しておいた破壊できないレジスタの値がネイティブ環境のレジスタに書き戻されている。この状態で、ラップコード２１４内の文脈維持コードＣがネイティブ環境により実行される。
【００４９】
文脈維持コードＣが実行される時点で、保護対象部分からの戻り値が仮想レジスタ領域に置かれているので、文脈維持コードＣは、その戻り値を、実際の戻り値を格納するネイティブ環境のレジスタに複写する。また、スタックポインタの値を、ラップコード２１４が最初に呼び出された時点での呼び出し元への戻りアドレスが格納されている位置を示すように設定する。これにより、ラップコード２１４から呼び出し元のネイティブコード２１２の実行に戻って、継続してそのネイティブコード２１２を実行できる状態となる。この状態で、ネイティブ環境はネイティブコード２１２の続きを実行する。
【００５０】
以上、ネイティブコード２１２の非保護対象部分から保護対象部分２２２へと処理を移行する際の文脈維持の仕組みについて説明したが、本実施形態は、更に、仮想マシン上で実行される保護対象部分２２２から、その保護対象部分２２２の外部にある外部関数を実行する仕組みも提供する。ここで外部関数は、例えば、ネイティブコード２１２内の非保護対象部分に含まれる関数、又はネイティブ環境に用意されているライブラリ等である。この仕組みは、仮想マシン（エミュレーション関数）に実装される。図３に、本実施形態の仮想マシンの動作を示す。
【００５１】
図３の手順では、仮想マシンは、保護対象部分２２２の実行による命令を受け取る毎に、その命令が外部関数を呼び出す関数呼び出し命令か否かを判定する（Ｓ１０）。受け取った命令が関数呼び出し命令でなければ、仮想マシンは単にその命令を実行する（Ｓ１２）。
【００５２】
一方、受け取った命令が関数呼び出し命令であれば、仮想マシンは、その命令を実行する前に、仮想マシン上の文脈をネイティブ環境に引き継ぐ文脈維持処理を実行する（Ｓ１４）。すなわち、保護対象部分２２２が仮想マシン上で実行されるのに対し、外部関数はネイティブ環境で実行されるので、保護対象部分２２２の実行によりその関数呼び出しまでに仮想マシン上に形成された仮想文脈（外部関数への引数等が含まれる）を、外部関数を実行するネイティブ環境の文脈に引き継ぐのである。また、ネイティブ環境は、外部関数の呼び出しまでは、仮想マシン（エミュレーション関数）をエミュレーション実行しているので、外部関数の終了後にそのエミュレーション実行に戻れるような文脈の維持（例えばエミュレーション実行のために用いるスタックポインタの退避等）も行う。
【００５３】
このような文脈維持の後、その外部関数を呼び出す関数呼び出し命令を実行する（Ｓ１６）。この外部関数の呼び出しの後、外部関数から保護対象部分２２２への戻りを示す戻り命令を待つ（Ｓ１８）。
【００５４】
外部関数からの戻り命令を受け取ると、仮想マシンは、それまで外部関数を実行していたネイティブ環境の文脈（外部関数からの戻り値等が含まれる）を仮想マシンに引き継ぐ文脈維持処理を実行する（Ｓ２０）。すなわち、戻り命令の時点でのネイティブ環境の文脈には、外部関数からの戻り値やその外部関数の実行に用いていたスタックへのポインタが含まれており、戻り後の保護対象部分２２２がそれら戻り値等を用いて演算を続行できるように、Ｓ２０ではネイティブ環境の文脈を仮想マシンの仮想文脈に引き継ぐ。また、戻り命令の後は、ネイティブ環境は仮想マシンのエミュレーション実行に戻るので、Ｓ２０では、Ｓ１４で退避した外部関数呼び出し前のスタックポインタをネイティブ環境に書き戻すという文脈維持も行う。このような文脈維持により、ネイティブ環境は外部関数の実行のためにいったん中断していた仮想マシンのエミュレーション実行を再開し、再開した仮想マシンは外部関数からの戻り値を受け取って保護対象部分２２２の続きを実行する。
【００５５】
以上、本実施形態におけるプログラムの部分的な仮想マシンでの実行による保護、及び部分的に保護された部分から外部関数の呼び出しの仕組みについて説明した。次に、図４を参照して、本実施形態におけるプログラムの部分的保護のための装置構成の例を説明する。
【００５６】
この例では、プログラムのソースコード３００（例えば高級言語で記述されたもの）が、コンパイラ１０及び保護対象部分指定部１２に入力される。コンパイラ１０は、そのソースコード３００をコンパイルし、オブジェクトコード１００を出力する。このオブジェクトコード１００は、図１に示したように、保護処理前のものである。
【００５７】
保護対象部分指定部１２は、一つの例では、ソースコード３００をそのまま画面表示し、表示したソースコード３００のうち保護対象とする部分の範囲指定操作をユーザから受け付ける。保護対象部分は、１つの例では関数単位の部分（１以上の関数の集まり）であるが、これに限らない。例えば１つの関数内の一部分を保護対象部分としてもよい。
【００５８】
また、保護対象部分が関数単位である場合には、保護対象部分指定部１２は、ソースコード３００のうち保護対象とする１以上の関数の関数名の入力をユーザから受け付けるものであってもよい。
【００５９】
保護対象部分指定部１２は、このようなユーザの指定に基づき、オブジェクトコード１００内の保護対象部分１１４（図１参照）を特定する。この特定結果は、コード書き換え部１４及び保護対象部分抽出部１６に渡される。
【００６０】
コード書き換え部１４は、オブジェクトコード１００のうち、保護対象部分指定部１２により特定された保護対象部分１１４を、ラップコード２１４に変更するという書き替え処理を実行する。書き換えの対象である保護対象部分１１４は、オブジェクトコード１００内のテキスト（コード）領域１１０に含まれるネイティブコード１１２の一部であり、これをラップコード２１４に変更することで、保護対象部分１１４の代わりにラップコード２１４を含んだ変更済みのテキスト領域２１０が得られる。
【００６１】
保護対象部分抽出部１６は、オブジェクトコード１００の中から保護対象部分指定部１２により特定された保護対象部分１１４のコードを取り出す。そして、取り出された保護対象部分１１４のコードを、保護対象部分移動部１８がオブジェクトコード２００のうちのデータ領域２２０に移動して配置する。これにより保護対象部分１１４は、データ領域２２０内の保護対象部分２２２となる。
【００６２】
なお、コード書き換え部１４と保護対象部分移動部１８とは、データ領域２２０内の保護対象部分２２２の配置場所（アドレス）の情報を共有する。この共有は、保護対象部分移動部１８が保護対象部分２２２の移動先のデータ領域２２０内でのアドレスをコード書き換え部１４に通知する形で実現してもよいし、その逆にコード書き換え部１４が保護対象部分２２２の移動先のアドレスを保護対象部分移動部１８に指示する形で実現してもよい。コード書き換え部１４は、この保護対象部分２２２のアドレス情報を、ラップコード２１４内の仮想マシン呼び出しコードＢ（図２参照）の引数にセットする。
【００６３】
以上の構成により、保護対象部分２２２が仮想マシンで実行され、その他の部分（非保護対象部分）がネイティブ環境で実行されるオブジェクトコード２００が作成される。
【００６４】
以上に説明した装置により生成された保護済プログラム（オブジェクトコード２００）をネイティブ環境で実行した場合の処理の流れの例を、以下に説明する。
【００６５】
この例では、エミュレーションの単位は関数であるとする。すなわち、仮想マシン上で実行される保護対象部分２２２は、１つ又は複数の関数である（すなわちネイティブ環境と仮想マシン環境の切り替えの界面は関数）であるとする。以下の例では、繁雑さを避けるため、保護対象部分２２２は１つの関数である（このように仮定しても一般性は損なわれない）とし、保護対象部分２２２が表す関数のことを「保護対象関数」と呼ぶこととする。以下の例では、呼び出し元の関数の先頭の２個までの引数をレジスタに入れ、残りの２つの引数をスタックに入れて呼び出し先の関数に渡し、呼び出し先の関数からの戻り先のアドレスをスタック先頭に入れて呼び出し先関数に渡すアーキテクャのプログラムに本技術を適用する例を用いて説明する。
【００６６】
以下では、このようなアーキテクチャのプログラムに対して本実施形態の保護処理を適用し、保護処理後のプログラム（オブジェクトコード２００）をネイティブ環境で実行した場合の処理の流れ、ネイティブ環境において使用されるスタックとレジスタの状態を図示しながら説明する。
【００６７】
図５が示しているのは、呼び出し元の関数（ネイティブコード）から、保護対象関数を呼び出した時点（より厳密に言えばネイティブコード２１２において、その保護対象関数に置き換えられたラップコード２１４を呼び出した時点）の、ネイティブ環境のスタック５０及実レジスタ群６０の状態である。なお、後で説明する仮想マシンが使用する仮想的なスタック及びレジスタとの区別のために、ネイティブ環境が使用するスタック５０及レジスタ群６０のことを「実スタック」５０及び「実レジスタ」群６０と呼ぶこととする。
【００６８】
この例では、保護対象関数を４つの引数（引数１，２，３，４と呼ぶ）と共に呼び出している。この時点では、実スタック５０の先頭（トップ）には、呼び出し元への戻りアドレスの値が置かれ、その次に引数３及び引数４がこの順に置かれている。また、この時点では、ネイティブ環境が使用している実レジスタ群６０の中の、あらかじめ定められたスタックポインタ用のレジスタｓｐには上述の戻りアドレスが置かれたスタック位置を示すアドレス値が置かれている。また、番号０のレジスタ（「レジスタ０」と呼ぶ）には引数１が、番号１のレジスタ（「レジスタ１」と呼ぶ）には引数２が、それぞれに置かれている。インストラクションポインタ(ｉｐ)又はプログラムカウンタ(ｐｃ)と呼ばれるレジスタは、保護対象関数に置きかえられているラップコード２１４の先頭を示しているがここでは重要でないため図示していない。
【００６９】
図６は、ラップコード２１４内の文脈維持コードＡ（図２参照）が実行された直後の実スタック５０及び実レジスタ群６０の状態を示す。実行される文脈維持コードＡは、まず仮想マシンがレジスタとして用いる仮想レジスタ領域５２を格納する領域を確保するため、実レジスタ群６０内のスタックポインタｓｐを必要な大きさ（この大きさは既知である）だけ減算する。この例は、仮想レジスタ領域５２をネイティブ環境のメモリ内の実スタック５０に確保する例である。その後、実行される文脈維持コードＡは、引数が格納されたレジスタの値、この例では引数１及び引数２が保持されているレジスタ０及び１の値を、確保した仮想レジスタ領域５２内のそれら引数のレジスタに対応する領域（これら領域が仮想レジスタ０及び１となる）に書き込む。
【００７０】
図７は、実行されたラップコード２１４中の仮想マシン呼び出しコードＢが、エミュレーション関数（＝仮想マシン）を呼び出した時点の実スタック５０及び実レジスタ群６０の状態を示す。この時点では、実レジスタ群６０のレジスタ０には、メモリ空間内のデータ領域（データを置くための書き込み可能な領域）のうちの、エミュレーション実行の対象である保護対象関数（保護対象部分２２２）を格納した場所へのポインタが、エミュレーション関数に渡す引数１として設定される。また、レジスタ１には、その保護対象関数の大きさ（コードサイズ）が、エミュレーション関数に渡す引数２として設定されている。そして、その仮想マシン呼び出しコードＢの実行の結果として、ラップコード２１４への戻りアドレスが実スタック５０の先頭に格納される。
【００７１】
図８は、エミュレーション関数（仮想マシン）の前処理部(プロローグ)の実行が終了した時点の実スタック５０と実レジスタ群６０を示す。プロローグの実行により、実レジスタ群６０内のそのエミュレーション関数の実行で用いられるレジスタ のうち、関数の呼び出し規約上破壊してはいけないレジスタの値がスタック６０上に退避され、更に、エミュレーション関数の実行で用いられる自動変数の領域の確保のために、実レジスタ群６０内のスタックポインタｓｐの値が必要な値だけ減算される（この例では、実スタック５０はアドレスが小さい方に成長するとする）。この前処理の中で、引数として渡された保護対象関数（保護対象部分２２２）のアドレス値とコードサイズも、実レジスタ群６０から、確保された自動変数領域内の対応する変数領域に設定される。この後、実スタック５０でまだ使用されていない場所、例えば実スタック５０の先頭等、のアドレスが仮想スタックの先頭として設定される。すなわち、そのアドレスが仮想レジスタ領域５２内のスタックポインタｓｐに対応する領域に設定される。なお、仮想スタックは、仮想マシン（エミュレーション関数）がスタックとして使用する領域であり、実スタック５０内に確保される。
【００７２】
図９は、エミュレーション関数の処理により、保護対象関数をエミュレーション実行している最中の実スタック５０及び実レジスタ群６０の状態を示す。ネイティブ環境上で実行されるエミュレーション関数（すなわち仮想マシン）は、保護対象関数の命令コードを一つずつ読みとり、その命令に応じた処理を、仮想レジスタ領域５２と仮想スタックを用いて実行する。このような仮想マシン上での保護対象関数の実行、すなわちエミュレーション処理では、最初に保護対象関数の前処理部(プロローグ)を実行し、これにより、仮想スタック上にレジスタ（この場合は仮想レジスタ領域 ）を退避したり、仮想スタック上に当該保護対象関数が利用する自動変数の領域を確保するため、仮想スタックポインタ(仮想ｓｐ)の値を減算したり、レジスタ経由で渡された引数を、自動変数の初期値として退避する。この後、保護対象関数の本体の処理が仮想マシンにより実行される。なお、このとき、ネイティブ環境は、実スタック５０内に確保されたエミュレーション関数の自動変数の領域を用いてエミュレーション関数を実行しており、実レジスタ群６０のスタックポインタｓｐはその自動変数の領域の先頭を指している。 
【００７３】
さて、エミュレーション実行される（すなわち仮想マシンが実行する）保護対象関数は、ネイティブコード１１２（２１２）における保護対象関数の呼び出し元の関数から渡される引数３及び４を用いて処理を実行しなければならない。これら引数３及び４は、実スタック５０内の、保護対象関数（より正確にはその保護対象関数に置き換わったラップコード２１４）の呼び出し時点のスタック先頭（図１０にて矢印ａで指し示すアドレス。すなわち「呼び出し元への戻りアドレス」の値が格納されているアドレス）よりも奥（図では下側）に格納されている。仮に本実施形態のプログラム保護を行わずにネイティブ環境でそのまま保護対象関数を実行するのであれば、矢印ａで示す基準位置に対して１つ下（引数３が格納される）及び２つ下（引数４が格納される）の位置からそれぞれ値を読み取るという命令、を実行することなる。
【００７４】
ところが、仮想マシン上で保護対象関数を実行する場合、保護対象関数内の引数３及び４を読む命令は、仮想マシンが用いる仮想スタック内のアドレス、より詳しくは仮想マシンが呼び出された時点でのスタック先頭（図１０にて矢印ｂで指し示す「ラップコードへの戻りアドレス」の値が格納されているアドレス）から１つ下及び２つ下の位置を読み出すことになる。これらの位置は、文脈維持コードＡが仮想レジスタ領域５２として確保した領域内の仮想レジスタ０及び１であり、これらの位置から読み出されるデータは引数３及び４とは異なるものである。
【００７５】
このようなことを避けて、仮想マシン上で実行される保護対象関数が実スタック５０内の引数３及び４を正しく読み取れるようにするために、本実施形態では、仮想マシンに読み出し先アドレスの読み替え機能を持たせる。すなわち、仮想マシンは、保護対象関数内の命令が当該仮想マシンの呼び出し時点でのスタック先頭（矢印ｂの指すアドレス）より奥（すなわちアドレス値が大きい側、図１０では下側）のアドレスを読み出す命令である場合、その命令を、その対象アドレスよりも図１０のアドレスａとｂの差分（ａ−ｂ）だけ「奥」すなわち「大きい」アドレスのデータを読み出す命令に読み替えて実行する。なお、保護対象関数内の命令がアドレスｂより浅い（すなわち小さい）アドレスを読み出す命令である場合には、仮想マシンはそのようなアドレス読み替えを行わずにその命令を実行する。
【００７６】
このようなアドレス読み替えを可能とするために、１つの例では、そのアドレス差分（ａ−ｂ）、又は保護対象関数の呼び出し時点でのスタック先頭のアドレスａを、引数としてエミュレーション関数（仮想マシン）に渡す。後者の場合、仮想マシンは、仮想マシン呼び出し時点でのスタック先頭アドレスｂは知っているので、引数として受け取ったアドレスａとそのアドレスｂからアドレス差分（ａ−ｂ）を計算すればよい。また、別の例として、ラップコード（及びその中の文脈維持コード）が処理のために用いるスタックの量（すなわちアドレス差分（ａ−ｂ））をあらかじめ定めておき、仮想マシンにそのスタック量の値を持たせておいてもよい。
【００７７】
図１１に、保護対象関数から外部関数を呼び出す直前の実スタック５０と実レジスタ群６０の状態を示す。ここでいう外部関数は、保護対象関数にとっての「外部」の関数という意味であり、ネイティブ環境で直接実行される関数のことである。例えばネイティブコード２１２内の非保護対象の関数、あるいは、ネイティブ環境が提供するライブラリ等がその一例である。
【００７８】
エミュレーションを実行する中で外部関数を呼び出す命令に達するまでに、外部関数呼び出しの際に必要となる引数は、仮想レジスタ領域５２（引数１及び２）、及び仮想スタック（仮想スタックのトップ（先頭）の引数３及び４）上に設定されている。
【００７９】
エミュレータ（すなわち仮想マシン＝実行されているエミュレーション関数）は、外部関数を呼び出す命令を受け取ると、図３にて説明したように外部関数への移行のための文脈維持処理（Ｓ１４）を実行する。この文脈維持処理により、図１２に示すように、仮想レジスタ領域５２内の引数１及び２が実際の実レジスタ群６０のレジスタ０及び１に書き込まれる。これにより、仮想マシン環境の文脈の一部である引数１及び２がネイティブ環境に引き継がれる。また、この文脈維持処理により、実レジスタ群６０内のスタックポインタｓｐと、仮想レジスタ領域５２内の仮想スタックポインタ（仮想ｓｐ）の値とが入れ替えられる。この入れ替えの結果、ネイティブ環境の実レジスタ群６０内のスタックポインタｓｐが仮想スタックの先頭（「外部関数への引数３」が格納されている）を指すことになるので、呼びされた外部関数が仮想スタック内の引数３及び４を正しく受け取るようになると共に、後の外部関数からの復帰時にエミュレーションを再開する際に実レジスタ群６０内のスタックポインタに復帰させるべき値が、仮想レジスタ領域５２内の仮想ｓｐ（仮想スタックポインタ）上に退避されることとなる。なお、この実レジスタ群６０のスタックポインタｓｐの退避は、必ずしも仮想ｓｐに行う必要はない。この代わりに、エミュレーション関数の自動変数領域内や、実レジスタ群６０内の関数の呼び出し規約上破壊されないレジスタ等、に退避してもよい。
【００８０】
その後、ネイティブ環境で外部関数の命令を実行することで、実スタック５０の先頭にエミュレーション関数仮想マシンへの戻りアドレスが置かれ、スタックポインタｓｐが一つ分減算され、外部関数に処理が移る(図１３)。また、この外部関数の前処理で、実レジスタ群６０のうち関数の呼び出し規約上破壊してはいけないレジスタの値の退避が行われる。 
【００８１】
そして、実行される外部関数は、実スタック５０、実レジスタ群６０の状態を受け取り、通常の処理を実行する(ネイティブ環境での外部関数の直接実行。図１４参照)。このとき、実スタック５０の先頭には、外部関数が利用するスタック領域が積まれている。
【００８２】
また、図１５に示すように、ネイティブ環境の処理が外部関数から仮想マシン（エミュレーション関数）に戻る時には、実レジスタ群６０のうち外部関数の前処理部でレジスタ退避を行ったレジスタについては、退避した値が書き戻される。また、実レジスタ群６０のうち関数の戻り値を入れるレジスタ（図１５ではレジスタ０）には、外部関数からの戻り値が入る。この状態で、仮想マシンに処理が戻る。
【００８３】
外部関数から処理が戻ると（図３のＳ１８の判定結果がＹｅｓ）、仮想マシンは、外部関数からの戻り時の文脈維持処理を実行する（図３のＳ２０）。この処理では、実レジスタ群６０内の関数の戻り値の入ったレジスタ内の値を、仮想レジスタ領域５２内の対応する領域に書き込み、実レジスタ群６０内の実際のスタックポインタｓｐの値と、仮想レジスタ領域５２内の仮想スタックポインタの値を入れ替える(図１６参照)。なお、スタックポインタを、自動変数領域や実レジスタ群６０内の関数呼び出し規約上破壊されないレジスタに退避していた場合は、その退避先から実スタックポインタへと値を復帰させる。これにより、仮想マシンは、外部関数の結果を受けとりエミュレーションを継続することとなる。
【００８４】
図１７は、これまでに説明した保護対象関数の実行が終了し、保護対象関数から処理が戻る命令に仮想マシンの処理が達した時点での実スタック５０及び実レジスタ群６０の状態を示している。この時点では、保護対象関数で用いていたスタックは無くなっており、実レジスタ群６０内のスタックポインタｓｐは、図８に示したエミュレーション開始時点と同様のアドレスを指している。また、仮想レジスタ領域５２内の仮想スタックポインタも同じアドレスを指している。
【００８５】
この後、エミュレーション関数（仮想マシン）の実行で使用した自動変数の領域を開放するため、実レジスタ群６０内の実スタックポインタｓｐの値が自動変数領域等のサイズだけ増やされ、スタックに退避しておいた破壊できないレジスタの値が実レジスタ群６０に戻され、実スタック５０内のその退避値の領域が開放される（図１８参照）。この状態で、実レジスタ群６０中のスタックポインタｓｐは、実スタック５０内のラップコードヘの戻りアドレスの入ったスタック位置を指し示しているので、ネイティブ環境はエミュレーション関数からの戻り命令を実行し、処理をラップコード２１４に戻す。
【００８６】
ラップコード２１４に処理が戻ると、仮想マシン環境からネイティブ環境への戻り時の文脈維持処理を記述した文脈維持コードＣ（図２参照）が、ネイティブ環境により実行される。この実行により、図１９に示すように、仮想レジスタ領域５２内の、保護対象関数からの戻り値を入れるレジスタの値が、実レジスタ群６０に書き込まれる。最後に、文脈維持コードＣは、仮想レジスタ領域５２を開放するため、実レジスタ群６０内のスタックポインタｓｐの値に、仮想レジスタ領域５２のサイズを加算する。なお、保護対象関数からの戻り値を実レジスタ群６０に書き込むのは、このスタックポインタｓｐの加算のタイミングでもよい。
【００８７】
この時点では、図２０に示すように、実レジスタ群６０内のスタックポインタｓｐは、保護対象関数（より正確にはラップコード２１４）の呼び出し元への戻りアドレス（ネイティブコード２１２中の非保護対象部分）を示している。したがって、ネイティブ環境は、関数からの戻り命令を実行することで、保護対象関数からの戻り値を受け取り、呼び出し元のネイティブコード２１２の実行を継続する。
【００８８】
以上説明したような流れで文脈維持を図ることで、ネイティブコード２１２の非保護対象部分から保護対象部分のエミュレーション実行への移行、エミュレーション実行される保護対象部分からの外部関数のネイティブ実行への移行が実現される。
【００８９】
さて、以上の方式では、図１０を用いて説明したように、仮想マシンは、保護対象関数の実行の際に、アドレスの読み替えにより、アドレスａより奥に積まれた引数３及び４を読み出すようにしていた。しかし、これは一例に過ぎない。別の方法として、図２１に示すように、エミュレーション関数の前処理部(プロローグ)を実行し終えたところで、保護対象関数の呼び出し前に実スタック５０に積まれた引数３及び４を仮想スタックの底の部分にコピーしてもよい。この場合、呼び出し元への戻りアドレスを更にコピーしてもよい。このためには、エミュレーション関数に複写すべき引数の数(大きさ)を引数として渡しておくか、決められた大きさを自動的に複写するようにし、それ以上の大きさの引数を渡さないようにプログラムの制約を定めておく方法も考えられる。この方法では、図２２に示すように、保護対象関数を実行する仮想マシンは、仮想スタックの先頭から引数３及び４を取り出して処理を実行するという通常の動作を行えばよい。
【００９０】
以上、本実施形態におけるプログラムの部分的保護の仕組み、及びこの部分的保護が施されたプログラムがネイティブ環境（及びその上で実行される仮想マシン）でどのように実行されるかを説明した。
【００９１】
以上の仕組みを実現するには、仮想マシンは、ネイティブ環境との間で文脈を互いに変換できるものである必要がある。一例として、仮想マシンとしては、ネイティブ環境と同一のアーキテクチャ（例えば、使用するレジスタやスタック等の構成が共通など）のものを用いればよい。ここで、仮想マシンを、ネイティブ環境と同一アーキテクチャであるものの、命令のバイナリエンコードが異なる独自の命令コード体系を用いるものとしてもよい。
【００９２】
このように独自の命令コード体系（ネイティブ環境の命令コード体系と異なるもの）を用いる仮想マシンを用いる場合には、保護対象部分抽出部１６がオブジェクトコード１００から抽出した保護対象部分１１４のコード（これはネイティブ環境用のコードで記述されている）を、仮想マシン用の独自のコード体系に変換し、変換後の保護対象部分２２２を保護対象部分移動部１８によりオブジェクトコード２００のデータ領域２２０に書き込む。この方式では、仮に攻撃者がメモリのデータ領域にある保護対象部分２２２のコードに気づいた場合でも、攻撃者が保護対象部分２２２の内容を分析するのに、（保護対象部分２２２がネイティブ環境用のコード体系で記述されている場合よりも）時間や手間がかかる。
【００９３】
また、変形例として、オブジェクトコード２００内に置かれる保護対象部分２２２を、暗号化されたものとしてもよい。この場合、一つの例では、保護済みのオブジェクトコード２００のデータ領域２２０に置かれる保護対象部分２２２ａには、保護対象部分１１４（又はこれを仮想マシン用の独自コード体系に変換したもの）の暗号化結果とともに、その暗号化結果を復号するための復号コードが含まれる。この例では、ネイティブ環境で仮想マシン呼び出しコードＢが実行されると、まず復号コードが実行され、その復号コードの実行により保護対象部分の暗号化結果が復号され、復号された保護対象部分が仮想マシンにより実行されるように、保護対象部分２２２ａが構成される。このような保護対象部分２２２ａは、特許文献３（特に図５を用いて説明した部分）に示されるのと同様の方法で作成すればよい。なお、復号コードは、保護対象部分２２２ａではなく、ラップコード２１４内（例えば文脈維持コードＡの後、且つ仮想マシン呼び出しコードＢの前、に呼び出される位置）に配置してもよい。
【００９４】
保護対象部分２２２ａは、メモリ上のデータ領域（書き込み可能な領域）に置かれるので、保護対象部分の暗号化結果を復号コードで復号したものをデータ領域に書き込んで、実行するようにすればよい。
【００９５】
また、復号した保護対象部分の実行から、ネイティブコード２１２内の非保護対象部分の実行に戻る際に、データ領域内に展開された復号済みの保護対象部分のコードを再暗号化（復号コードで復号できるような暗号化）するようにしてもよい。これには、例えば、保護対象部分２２２ａ内又はラップコード２１４内に、再暗号化処理を記述したコードを含めておけばよい。再暗号化のための仕組みは、特許文献３の段落００４３に示されるのと同様でよい。
【００９６】
また、特許文献３（特に図９を用いて説明される部分）に示されるように、保護対象部分のコードの暗号化を多重にすることで、強い保護を図ってもよい。
【００９７】
また、別の変形例として、ラップコード２１４に、デバッガ解析対策用のコードを含めてもよい。このデバッガ解析対策用のコードは、例えば、デバッガツールによる解析が行われていることを検知すると、直ちに、又はエラーなどの警告表示を行った後に、ネイティブコード２１２の実行を停止する処理を記述したものである。このデバッガ解析対策用のコードは、仮想マシン呼び出しコードＢの実行前に実行されるような形で、ラップコード２１４内に含めておけばよい。デバッガ解析対策用のコードの実行により、保護対象部分２２２がデバッガにより解析されることが防がれる。
【００９８】
また、デバッガ解析対策の別の例として、ネイティブコード２１２に対してデバッガツールによる解析が行われていることが検知されると、データ領域内にある保護対象部分の暗号化結果が正しく復号できないようにする方式もある。例えば、復号コード（図２３等参照）が用いる復号鍵を、デバッガの検出結果に応じて生成するようにし、デバッガが検出されなかった場合には正しい復号鍵が得られ、検出された場合には誤った復号鍵が得られるようにすればよい。このようなデバッガ検出及び復号鍵生成のためのコードを、仮想マシン呼び出しコードＢが実行される前に実行される形で、ラップコード２１４に組み込めばよい。この例では、ネイティブコード２１２に対してデバッガツールによる解析が行われていると、保護対象部分の呼び出し時に誤った復号鍵が生成されるので、その復号鍵による保護対象部分の復号結果は誤ったものとなる。デバッガによる解析を検出した後処理を続行すると、誤った復号結果が実行されることとなり、仮想マシン（及びそれを実行するネイティブ環境）が暴走する。
【００９９】
図４に例示したプログラムの部分的な保護のための装置は、例えば、汎用のコンピュータに上述の各機能モジュールの処理を表すプログラムを実行させることにより実現される。ここで、コンピュータは、例えば、ハードウエアとして、ＣＰＵ等のマイクロプロセッサ、ランダムアクセスメモリ（ＲＡＭ）およびリードオンリメモリ（ＲＯＭ）等のメモリ（一次記憶）、ＨＤＤ（ハードディスクドライブ）を制御するＨＤＤコントローラ、各種Ｉ／Ｏ（入出力）インタフェース、ローカルエリアネットワークなどのネットワークとの接続のための制御を行うネットワークインタフェース等が、たとえばバスを介して接続された回路構成を有する。また、そのバスに対し、例えばＩ／Ｏインタフェース経由で、ＣＤやＤＶＤなどの可搬型ディスク記録媒体に対する読み取り及び／又は書き込みのためのディスクドライブ、フラッシュメモリなどの各種規格の可搬型の不揮発性記録媒体に対する読み取り及び／又は書き込みのためのメモリリーダライタ、などが接続されてもよい。上に例示した各機能モジュールの処理内容が記述されたプログラムがＣＤやＤＶＤ等の記録媒体を経由して、又はネットワーク等の通信手段経由で、ハードディスクドライブ等の固定記憶装置に保存され、コンピュータにインストールされる。固定記憶装置に記憶されたプログラムがＲＡＭに読み出されＣＰＵ等のマイクロプロセッサにより実行されることにより、上に例示した機能モジュール群が実現される。
【０１００】
なお、図４に例示した装置と、この装置で実行される保護済みのプログラム（オブジェクトコード２００）を実行するネイティブ環境とは、物理的に同一のコンピュータであってもよいし、別のコンピュータであってもよい。
【符号の説明】
【０１０１】
５０  実スタック、５２  仮想レジスタ領域、６０  実レジスタ群、１００，２００  オブジェクトコード、１１０，２１０  テキスト領域、１１２，２１２  ネイティブコード、１１４，２２２  保護対象部分、１２０，２２０  データ領域、２１４  ラップコード、２２２，２２２ａ  保護対象部分、３００  ソースコード。
【図１】
0005953867.tif 000002
【図２】
0005953867.tif 000003
【図３】
0005953867.tif 000004
【図４】
0005953867.tif 000005
【図５】
0005953867.tif 000006
【図６】
0005953867.tif 000007
【図７】
0005953867.tif 000008
【図８】
0005953867.tif 000009
【図９】
0005953867.tif 000010
【図１０】
0005953867.tif 000011
【図１１】
0005953867.tif 000012
【図１２】
0005953867.tif 000013
【図１３】
0005953867.tif 000014
【図１４】
0005953867.tif 000015
【図１５】
0005953867.tif 000016
【図１６】
0005953867.tif 000017
【図１７】
0005953867.tif 000018
【図１８】
0005953867.tif 000019
【図１９】
0005953867.tif 000020
【図２０】
0005953867.tif 000021
【図２１】
0005953867.tif 000022
【図２２】
0005953867.tif 000023
【図２３】
0005953867.tif 000024