(57)【要約】【課題】  プログラムの解析や改ざんをさらに困難にすることが可能な技術を提供する。【解決手段】  情報処理装置は、処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定し、対象インストラクションに対応する偽装インストラクションを生成し、生成された偽装インストラクションを、対応する対象インストラクションに復元するための復元命令を生成し、処理対象のプログラムに含まれる対象インストラクションを生成された偽装インストラクションで書き換え、該プログラムに復元命令を追加する。ここで、復元命令は、処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、対象インストラクションの該プログラムにおける位置、あるいは、対象インストラクションを特定して、復元を行う。【選択図】  図１
2009104589.tif 000002
【特許請求の範囲】
【請求項１】
処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定手段と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成手段と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成手段と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する手段と、
を備え、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とする情報処理装置。
【請求項２】
前記復元命令は、
前記処理対象のプログラム中の固定値を算出する処理命令の算出値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの前記位置、あるいは、前記対象インストラクションを特定する
ことを特徴とする請求項１に記載の情報処理装置。
【請求項３】
前記決定手段は、前記対象インストラクションを、前記処理対象のプログラムに含まれる条件ジャンプに係るインストラクションから無作為に決定する
ことを特徴とする請求項２に記載の情報処理装置。
【請求項４】
前記偽装インストラクション生成手段は、前記対象インストラクションと異なる条件分岐を行うインストラクションを前記偽装インストラクションとして生成する
ことを特徴とする請求項３に記載の情報処理装置。
【請求項５】
コンピュータに処理対象のプログラムの書き換えを実行させるプログラムであって、
コンピュータを、
前記処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定手段と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成手段と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成手段と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する手段と、
として機能させ、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とするプログラム。
【請求項６】
前記復元命令は、
前記処理対象のプログラム中の固定値を算出する処理命令の算出値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの前記位置、あるいは、前記対象インストラクションを特定する
ことを特徴とする請求項５に記載のプログラム。
【請求項７】
前記決定手段は、前記対象インストラクションを、前記処理対象のプログラムに含まれる条件ジャンプに係るインストラクションから無作為に決定する
ことを特徴とする請求項６に記載のプログラム。
【請求項８】
前記偽装インストラクション生成手段は、前記対象インストラクションと異なる条件分岐を行うインストラクションを前記偽装インストラクションとして生成する
ことを特徴とする請求項７に記載のプログラム。
【請求項９】
処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定工程と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成工程と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成工程と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する工程と、
を有し、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とする情報処理方法。
【請求項１０】
請求項５に記載のプログラムを格納したコンピュータ読み取り可能な記録媒体。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は情報処理装置及びその方法、プログラム、記録媒体に関し、特に、プログラムの解析や改ざんを困難にする技術に関する。
【背景技術】
【０００２】
著作権保護や暗号化処理の鍵の保護のために、解析や改ざんの困難なプログラムを作成する技術が求められている。このため、従来より、プログラムを暗号化する技術、プログラムを難読化する技術が知られている。非特許文献１にはこれらの技術の特徴が記載されており、これらの技術とは異なる技術として、自己書き換え処理を行うプログラムを作成する構成が提案されている。
【非特許文献１】神崎雄一郎、門田暁人、中村匡秀、松本健一、“命令のカムフラージュによるソフトウェア保護方法、”電子情報通信学会誌, Vol.J87−A, No.6, pp.755-767, June 2004
【発明の開示】
【発明が解決しようとする課題】
【０００３】
しかしながら、非特許文献１の構成では自己書き換え処理を利用してプログラムの真の命令コードを偽装する構成が開示されているが、解析に対して十分な強さを持っているとは言えなかった。つまり、非特許文献１は、プログラムを実行することなく解析を行う静的解析に対して、従来より耐性を持たせたものであるが、十分な静的解析を行えば、解析可能であるという課題があった。
【０００４】
本発明は上記問題に鑑みなされたものであり、プログラムの解析や改ざんをさらに困難にすることが可能な技術を提供することを目的とする。
【課題を解決するための手段】
【０００５】
本発明によれば、
処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定手段と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成手段と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成手段と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する手段と、
を備え、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とする情報処理装置が提供される。
【０００６】
また、本発明によれば、コンピュータに処理対象のプログラムの書き換えを実行させるプログラムであって、
コンピュータを、
前記処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定手段と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成手段と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成手段と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する手段と、
として機能させ、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とするプログラムが提供される。
【０００７】
また、本発明によれば、
処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する決定工程と、
前記対象インストラクションに対応する偽装インストラクションを生成する偽装インストラクション生成工程と、
前記生成された偽装インストラクションを、対応する前記対象インストラクションに復元するための復元命令を生成する復元命令生成工程と、
前記処理対象のプログラムに含まれる前記対象インストラクションを前記生成された偽装インストラクションで書き換え、該プログラムに前記復元命令を追加する工程と、
を有し、
前記復元命令は、
前記処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて、前記対象インストラクションの該プログラムにおける位置、あるいは、前記対象インストラクションを特定して、前記復元を行う
ことを特徴とする情報処理方法が提供される。
【発明の効果】
【０００８】
本発明によれば、プログラムの解析や改ざんをさらに困難にすることが可能な技術を提供することができる。
【発明を実施するための最良の形態】
【０００９】
以下、添付図面を参照して本発明に係る実施の形態を詳細に説明する。ただし、この実施の形態に記載されている構成要素はあくまでも例示であり、本発明の範囲をそれらのみに限定する趣旨のものではない。また、本実施の形態で説明されている特徴の組み合わせの全てが発明の解決手段に必須のものとは限らない。
【００１０】
＜＜第１の実施形態＞＞
（コンピュータ装置の構成）
本実施形態におけるコンピュータ装置（情報処理装置）の内部構成について、図3を参照して説明する。図3は、コンピュータ装置の内部構成を示すブロック図である。この内部構成は、本明細書の全ての実施形態に共通とする。
【００１１】
図3のように、コンピュータ装置300は、ネットワーク・インタフェース301、外部媒体読み書き装置302、CPU303、ROM304、RAM305、ハードディスク306を備える。また、電源307、指示入力装置インタフェース308、モニタ・インタフェース309、バス310等を備える。
【００１２】
ネットワーク・インタフェース301は、外部装置と通信するための通信インタフェースであり、例えば、LANインタフェース、無線LANインタフェース等により実現される。外部媒体読み書き装置302は、外部媒体からデータを読み出したり、外部媒体にデータを書き込んだりする装置である。外部媒体読み書き装置302がデータを読み書きする外部媒体には、例えば、フレキシブルディスクやCD-RやDVD、USB等が含まれる。
【００１３】
CPU303は、コンピュータ装置300全体の動作を制御する中央演算処理装置である。ROM304は読み出し専用メモリであり、基本プログラム、基本データ等が格納されている。RAM305は書き込み可能メモリであり、CPU303による演算のワークエリア等として使用される。
【００１４】
ハードディスク（以下、HD）306は大容量の外部記憶装置であり、演算前後のデータ等が記憶される。電源307はコンピュータ装置300に電力を供給する。
指示入力装置インタフェース308は指示入力装置とのインタフェースであり、ユーザは当該指示入力装置を介して指示命令を入力する。指示入力装置インタフェース308に接続される指示入力装置には、例えば、キーボード/ポインティングデバイス等の装置が含まれる。
【００１５】
モニタ・インタフェース309はモニタとのインタフェースであり、接続されたモニタに演算結果等を示す画面を出力する。バス310はコンピュータ装置300の構成要素間を接続し、信号を伝達する。
【００１６】
なお、コンピュータ装置300は、パーソナルコンピュータ（PC）やワークステーション（WS）、携帯情報端末（PDA）等により実現される。
【００１７】
以下の処理内容(手順)は、プログラム（ソフトウェア）もしくはモジュール（ハードウェア）として実現される。例えば、プログラムとして実現される場合は、そのプログラムはROM304もしくはHD306に格納され、そのプログラムをCPU303が読み込む。そして必要に応じてRAM305を計算のための空間（ワークエリア）として利用しながら、バス310を介してHD306に記録されたデータを読んだり、HD306にデータを書いたりして処理を実行する。
【００１８】
モジュールとして実現される場合は、プログラムによる動作と同等の動作を実行する実体が、例えばLSIとして実現され、コンピュータ装置300に組み込まれている。この場合、装置のCPU303からモジュール(LSI)へ指示が発行され、それを契機として各モジュールが動作し、処理を実行する。
【００１９】
以下、解析や改ざんを困難にするために、コンピュータ装置300に、処理対象のプログラムに対するインストラクションの偽装を行わせるためのプログラムを、自己書き換え処理追加プログラムと呼ぶ。自己書き換え処理追加プログラムは、フレキシブルディスク、CD-ROM、DVD等の外部媒体から外部媒体読み書き装置302を経由してコンピュータ装置300にインストールすることにより、HD306に格納される。あるいは、ネットワーク・インタフェース301を経由してHD306に格納してもよい。
【００２０】
（自己書き換え処理）
本実施形態では、ソース・プログラムをコンパイルしてアセンブリ・プログラムを生成し、当該アセンブリ・プログラムの、条件ジャンプに係る命令コードを含むインストラクションに対して自己書き換えを行うことで、プログラムの解析や改ざんを困難にする。ここで、条件ジャンプとは一定の条件が満たされたか否かに応じて処理を分岐する命令をいう。また、自己書き換えとは、書き換え対象のインストラクションを他のインストラクションで書き換えることをいう。本来実行されるインストラクションを別のインストラクションに変更しておくことを偽装すると呼ぶ。
【００２１】
図1は、本実施形態における自己書き換え処理追加プログラムに基づくCPU303の処理の流れを示すフローチャートである。自己書き換え処理追加プログラムの処理対象となる保護すべきプログラムは、例えば、C言語で記述されたソース・プログラムとして、RAM305に記録されているものとする。
【００２２】
図2は、Cのソース・プログラムの例を示す図である。図2の例では、jの値と関数func(,)の内容に応じて変数iの値が定まり、変数iが3であるか否か、および変数jが1であるか否かに応じて、4つの処理のいずれかが行なわれる。具体的には、以下のとおりである。
・変数iが3であり、変数jが1でない場合は、変数jを10増加する（201）。
・変数iが3であり、変数jが1である場合は、変数jを20増加する（202）。
・変数iが3でなく、変数jが1である場合は、変数jを30増加する（203）。
・変数iが3でなく、変数jが1でない場合は、変数jを40増加する（204）。
【００２３】
ステップS101において、CPU303はRAM305に記憶されたソース・プログラムをコンパイルしてアセンブリ・プログラムを生成する。図4は、図2のソース・プログラムをコンパイルして生成したアセンブリ・プログラムの一部分を示す図である。
【００２４】
ステップS102において、CPU303は自己書き換えの対象となりうるインストラクションが、対象のアセンブリ・プログラムに存在するか否かを判定する。即ち、アセンブリ・プログラムの中に、条件ジャンプに係る命令コードを含むインストラクションであって、まだステップS103〜S109の処理をされていないものが存在するか否かを判定する。なお、条件ジャンプに係る命令コードには、例えば、je、jz、jnz、jne、jb、jc、jnae、jl、jnge、ja、jnbe、jg、jnle、jbe、jna、jle、jng、jnb、jae、jnc、jge、jnlが含まれる。なお、条件ジャンプはプロセッサによってインストラクションも命令コードも異なるので、ここにあげたものだけに限定されるわけではない。
【００２５】
後述するように、CPU303は、自己書き換え対象に決定したインストラクションをRAM305に記録するため、ステップS102では、このRAM305の記録を参照して判定を行う。ステップS102において、未処理の分岐命令（条件ジャンプに係る命令コード）が存在する場合はステップS103に進み、存在しない場合はステップS110に進む。
【００２６】
本実施形態では、アセンブリ・プログラム中の、条件ジャンプに係る命令コードを含むインストラクションであって未処理のものの各々についてステップS103以下の処理を行う。
【００２７】
ステップS103では、CPU303が、処理対象のインストラクションを自己書き換えの対象とするか否かをランダムに決定する。なお、本実施形態では、アセンブリ・プログラムの一行が一つのインストラクションに相当する。そこで、ステップS103では、アセンブリ・プログラムの未処理の行の中から一つの行を処理対象として選択し、当該行のインストラクションを偽装するか否かをランダムに決定する。ここで、異なるインストラクションYで偽装する位置（例えば、アドレス、行番号）をP(Y)とする。
また、偽装する位置P(Y)は、アセンブリ・プログラムをアセンブルして生成される機械語プログラムにおいて決定してもよい。具体的には、次のようにしてもよい。即ち、アセンブリ・プログラムをアセンブルして、機械語プログラムを求める。機械語プログラムはインストラクションの系列であり、CPU303は機械語プログラムを読み込み、各インストラクションとそれらの区切りを認識することができる。この認識の結果、機械語プログラムからインストラクションを一つ決定し、それに対応するアセンブリ・プログラムのインストラクションの位置を自己書き換えの対象位置P(Y)としてもよい。
【００２８】
ここでは、図4において、「je L5」を対象インストラクションyと定め、偽装すると決定したとする。CPU303は、どのインストラクションが自己書き換えの対象として決定されたかをRAM305に記憶する。
【００２９】
このようにして、ステップS102、S103では、処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する。特に、本実施形態では、対象インストラクションを、処理対象のプログラムに含まれる条件ジャンプに係るインストラクションから無作為に決定している。
【００３０】
次に、ステップS104において、CPU303は偽装インストラクションYを決定する。本実施形態では、元のインストラクションyと逆の条件に分岐するような条件ジャンプを含むインストラクションを、偽装インストラクションYとして決定する。即ち、対象インストラクションyと異なる条件分岐を行うインストラクションを偽装インストラクションYとして生成する。図4の例では、対象インストラクションは「je L5」である。したがって、「je」と逆の制御フローとなる「jne L5」を偽装インストラクションYとして決定する。これらの処理は、コンピュータ装置300上に実現される、偽装インストラクション生成unitとしての機能要素により実行される。
【００３１】
以下、ステップS105〜S108では、偽装インストラクションYを真のインストラクションyで書き換える（復元する）ためのルーチンX（復元命令）を生成する。これらの処理は、コンピュータ装置300上に実現される、復元命令生成unitとしての機能要素により実行される。そして、ステップS109では、ルーチンXを処理対象のアセンブリ・プログラムに挿入し、真のインストラクションyを偽装インストラクションYで書き換える。
【００３２】
本実施形態では、ルーチンXが、偽装インストラクションYで偽装する位置P(Y)を以下の３つの値に基づいて算出し、当該位置P(Y)のインストラクションを偽装インストラクションYで書き換えるように、ルーチンXを構成する。
・アセンブリ・プログラムにおける所定の位置（以下、BASE位置）。
・アセンブリ・プログラム中の固定値を算出する予め定められた処理（以下、基準値算出処理）の算出値（以下、基準値）。
・P(Y)−BASE位置−基準値（以下、マスク値）
ルーチンXは、基準値＋BASE位置＋マスク値を計算することによって、偽装位置P(Y)を算出する。ここで、ルーチンXにおいて、基準値は、アセンブリ・プログラム中の基準値算出処理の処理結果が格納されたメモリを参照することにより取得される。即ち、ルーチンXは、処理対象のプログラム中に含まれる処理命令（基準値算出処理）の出力値が格納されるメモリを参照し、参照された値に基づいてインストラクションyのプログラムにおける位置を特定して、真のインストラクションyを復元する。このため、攻撃者は、アセンブリ・プログラムのルーチンXに相当する箇所を閲覧しても基準値を知ることが困難である。したがって、アセンブリ・プログラムのどの部分が偽装されているか否かを判別することが困難なため、攻撃者は、アセンブリ・プログラムの動作を解析したり、所望の動作をするように改ざんしたりすることが困難である。
【００３３】
なお、本実施形態では、基準値算出処理の出力値（基準値）は固定値であるため、マスク値を容易に決定することができる。
【００３４】
以下、各ステップの詳細を説明する。ステップS105において、CPU303は、アセンブリ・プログラムにおける基準値算出処理とその位置、及び、P(X)を決定する。上述のように、ルーチンXは、真のインストラクションyをP(Y)に書き込む処理を行なうが、P(X)はルーチンXを挿入する位置を示す。P(X)は、基準値算出処理の位置からP(Y)までの制御フローのいずれかの箇所に決定する。図4においては、「call _cont」「movl %eax, -12(%ebp)」を基準値算出処理、「je L5」を自己書き換え対象のインストラクションとして決定し、基準値算出処理の次の行をP(X)と決定した例を示している。
【００３５】
なお、基準値算出処理は、プログラムの中で行なわれる様々な処理を利用することができる。例えば、背景技術で説明した、プログラムが改ざんされていないことをプログラムが実行中に確認する方法における、観測値を算出する処理である。本実施形態では、理解を容易にするために図2の関数cont(,)を基準値算出処理として説明するが、Cのソース・プログラムには存在せず、アセンブリ・プログラムにのみ存在する処理であってもよい。なお、上述のように基準値は、基準値算出処理の処理結果である。また、基準値算出処理は、確定的な値を計算する処理である。つまり、処理の実行結果として固定値が出力される。
【００３６】
次に、CPU303は、ステップS106において基準値の決定、ステップS107においてマスク値の決定、ステップS108においてルーチンXの生成を行う。これらのステップは、詳細には以下のように行なわれる。
【００３７】
ルーチンXにおいては、自己書き換え対象とする偽装インストラクションYの位置P(Y)が必要である。このため、CPU303は、「P(Y)＝プログラム上のある位置＋基準値＋マスク値」の関係を満たすようにP(Y)とプログラム上のある位置と基準値とからマスク値を計算・決定する。
【００３８】
図4の例では、ステップS103において、偽装インストラクションYの位置P(Y)は「je L5」の位置と決定されている。基準値算出処理は、図4における「call _cont」であり、それによって計算された出力はその次のインストラクション「movl %eax, -12(%ebp)」によって「-12(%ebp)」に格納されている。上述のように基準値算出処理「call _cont」は、図2におけるcont(,)に対応しており、関数main(,)中のcont(,)の算出値はcont(l,45)＝cont(50,45)＝50-45＝5である。したがって、CPU303はその計算結果の「5」をあらかじめ計算しておくことができる。以下では、図4のアセンブリ・プログラムから、図5に示す、自己書き換え処理を追加した結果のアセンブリプログラムを作成する手順を述べる。
【００３９】
まず、CPU303はプログラム中の任意の位置（BASE位置）を決める。ここでは、図4の「jne L8」が選択されたとする。そのインストラクションのアドレスを「BASEのアドレス」と呼ぶことにする。アセンブリ・プログラム上では「jne L8」の前に「BASE:」を挿入する。
【００４０】
ここで、自己書き換えを行なう対象の偽装インストラクションYは「jne L5」である。以下、P(Y)を「TARGETのアドレス」と呼ぶ。
【００４１】
上述のように、「P(Y)＝BASE位置（アドレス）＋基準値＋マスク値」の関係が成立している。これより、「マスク値＝P(Y)−BASEのアドレス−基準値」である。上記の例のように、基準値＝5の場合は「マスク値＝TARGETのアドレス−BASEのアドレス−5」となる。ここでの例では、BASEよりP(Y)の方が小さいアドレスを有しているため、マスク値の絶対値を求め、それをBASEから引き算すればよい。従って、最終的なマスク値（の絶対値）は、「BASEのアドレス−TARGETのアドレス＋5」となる。この計算は、図4のアセンブリ・プログラムから（必要であれば、一度その機械語プログラムを求め、そのインストラクション系列を利用して）行うことができる。
【００４２】
次に、図5の自己書き換えルーチンXを参照しながら、その処理内容を生成する方法を説明する。ルーチンXは、P(Y)に真のインストラクションを書き込むことが目的なので、まずP(Y)を求める。他の処理に影響を与えないために、レジスタedxをP(Y)の計算に用いる。
【００４３】
最初にCPU303は「movl $BASE, %edx」を生成する。これは、BASEのアドレス、$BASE、をレジスタedxに代入するインストラクションである。
【００４４】
次に、CPU303は「addl -12(%ebp), %edx」を生成する。これは、-12(%ebp)をレジスタedxに加えるインストラクションである。ここで、-12(%ebp)には、基準値算出処理の結果が格納されており、その値は5である。よって、レジスタedxにはBASEのアドレスに5を加算した値が格納される。その値は、図5においては、BASEよりも5バイト下の位置を示すことになる。
【００４５】
そして、CPU303は「subl $0x21, %edx」を生成する。これは、レジスタedxにP(Y)を格納するために、前述のマスク値（の絶対値）を引き算するインストラクションである。マスク値は$0x21なので、16進数の21(10進数の33)がレジスタedxから減算される。その値は、図5においては、BASEよりも5バイト下の位置から33バイト上の位置P(Y)を示す。
【００４６】
最後に、CPU303は「movb $0x74, (%edx)」を生成する。ここで、レジスタedxに格納されているアドレス(%edx)がP(Y)である。従って、「movb $0x74, (%edx)」は、偽装インストラクション「jne L5」を真のインストラクション「je L5」に書き換えるために、$0x74を(%edx)に代入するインストラクションである。ただし、jneの機械語は0x75なので、P(Y)に書かれている1バイトの0x75が0x74に書き換えられる。
【００４７】
このようにして、図5の上部の四角で囲ったルーチンXが生成される。このようなルーチンXは、一例である。例えば、BASEとして別の位置を採用してもよく、その場合はマスク値は異なる値になる。図5におけるP(Y)を計算するために、プログラム上のアドレス計算をしていることに注意する。
【００４８】
次に、ステップS109において、上記のルーチンXをP(X)に挿入する。ここでは、図4の基準値算出処理の次の行の位置に上記ルーチンXを挿入する。また、自己書き換え対象のインストラクションYとして偽のインストラクション「jne L5」をP(Y)に書き込む。この結果、図4のアセンブリ・プログラムは図5のアセンブリプログラムに変更される。
【００４９】
次に、ステップS102に戻り、CPU303は自己書き換えの対象となるインストラクションが存在するか否かを判定し、ステップS103において偽装するか否かをランダムに決定する。偽装する場合は、ステップS104からステップS109の処理を繰り返し、偽装しない場合はステップS102に戻る。書き換え対象インストラクションが存在しない場合はステップS110に進む。
【００５０】
ステップS110においては、CPU303は自己書き換えプログラムをアセンブルして機械語プログラムを生成する。必要であれば機械語プログラムをリンクして、実行可能プログラムを生成する。また、CPU303は、実行可能プログラムに対して、プログラムのコード領域への書き込みを許可するフラグを立てるなどの処理を施し、そのプログラムが実行時に自らのコード領域に書き込みできるようにする。
【００５１】
（自己書き換えプログラムの動作）
次に、自己書き換えプログラムの機械語プログラムがCPU303によって実行される様子を説明する。機械語プログラムはアセンブリ・プログラムとほぼ対応しており、制御フローの観点から違いはないと言えるため、図5を参照しながら説明する。
【００５２】
まず、プログラムの中のインストラクションが、機械語プログラムの先頭から順にCPU303によって解釈され、メモリの読み書き、レジスターへの読み書きが行なわれる。実行箇所がP(X)に到達すると、ルーチンXが実行される。その処理の結果、P(Y)に存在する偽装されたインストラクションY(「jne L5」)が真のインストラクションy(「je L5」)に書き換えられる。機械語プログラム上は0x75が0x74に書き換えられる。そして、ルーチンXを終了し、その次に続くインストラクションが解釈、実行され、P(Y)に到達する。P(Y)のインストラクションは真のインストラクションyに書き換えられているため、yが解釈、実行されることになる。
【００５３】
（自己書き換えプログラムの安全性）
次に、本実施形態の自己書き換え処理追加プログラムによって生成されたプログラムの安全性について述べる。図5のプログラムを解析する場合を考える。前述のように、機械語プログラムはアセンブリ・プログラムとほぼ対応しており、制御フローの観点から違いはないと言えるため、機械語をディスアセンブルして図5相当のアセンブリ・プログラムを得たとする。
【００５４】
図5では、ルーチンXの位置P(X)と偽装ルーチンYの位置P(Y)が近い位置に配置されているが、実際のプログラムではこれらの距離は近いとは限らない。したがって、アセンブリ・プログラムを見るだけで偽装ルーチンXと自己書き換え対象P(Y)の関係を突き止めることは困難である。
【００５５】
次に、アセンブリ・プログラムの動作をプログラムを読んで理解しながら解析する場合を考える。ルーチンXの処理内容はプログラム上のある位置（BASE位置）と基準値算出処理の出力値（基準値）とマスク値の3つの値によって定められるが、基準値をプログラムを実行せずに読むだけで求めることは困難である。
【００５６】
プログラムが改ざんされていないことをプログラムが実行中に確認する構成において、プログラム実行中に計算される観測値を求める処理は、その観測を行う処理自体が容易に突き止められにくいように実装される。本実施形態でも、基準値算出処理として上記実装を用いることによって、基準値算出処理を容易に突き止められないようにすることができる。さらに、ルーチンXの処理は複数のインストラクションから構成されるので、それらを一箇所にまとめずに、離れた位置に配置することによっても、容易に突き止められないようにすることができる。したがって、P(Y)の値を判別することは困難である。
【００５７】
一方、本実施形態の手法を知っている解析者は、プログラムの中の条件ジャンプが書き換えられている可能性があることを知っている。図5の場合は、中央から下部の四角で囲った部分に条件分岐が存在することは見るだけでわかるので、この部分をデコンパイルして図6のようなC言語のソース・プログラムだと解釈できる可能性がある。ところが、P(Y)が特定できなければ条件ジャンプのどれが書き換えられているのかを突き止めることができないので、本当のプログラムがどれであるかを一意に判定することはできず、とり得る可能性を列挙して検討せざるを得ない。図2と図6を比較すると、図2のコードを実行した結果は図7の出力になるが、図6のコードを実行した結果は図8の出力になるので、解析者が図6のプログラムだと判定すると、プログラムを誤って解析したことになる。従って、攻撃者は、所望の動作を行なうように改ざんを行うこともできない。
【００５８】
以上の考察を踏まえて、本実施形態に係る構成の効果について、図9のフローチャートを参照してさらに説明する。図9は、図2のプログラムに対応するフローチャートでもある。図9の分岐Cが図2のif(i==3)に対応し、図9の分岐Eが図2のif(j!=1)に対応し、図9の分岐Iが図2のif(j==1)に対応する。
【００５９】
図9のフローチャートで表されるプログラムの場合は、比較による分岐が2段、合計3つ存在する。したがって、アセンブリ・プログラムの中に条件ジャンプが3つ存在する。これは、図4の中に「jne L4」と「je L5」と「jne L8」が存在することから確認できる。このプログラムに対して、本実施形態を適用すると、3つの条件ジャンプはランダムに偽装される。どの条件ジャンプが偽装されているかを突き止めることは困難であるので、取り得る可能性を列挙して解析を行なう必要がある。図9のフローチャートの分岐Eが偽装されたとすると図10のフローチャートが真のフローチャートである可能性がある。同様にして、図9の分岐Iが偽装されたとすると図11のフローチャートが真のフローチャートである可能性がある。同様にして、図2の分岐Cが偽装されたとすると図12のフローチャートが真のフローチャートである可能性がある。
【００６０】
以上から、偽装対象の条件ジャンプが1箇所あると、とり得るフローチャートは2つに増える。したがって、条件ジャンプがn箇所あると、とり得るフローチャートは2のn乗個に増える。よって、解析対象の個数が、プログラムの中の条件ジャンプの個数の指数関数のオーダーで定められることになるので、計算量的な解析の困難さを有するといえる。
【００６１】
自己書き換え処理を利用してプログラムの真の命令コードを偽装する従来の構成では、解析の困難さを定量的に見積もることができないという課題があった。これに対して本実施形態の構成では、プログラムを読んで理解しながら解析する攻撃者がプログラム内部の条件ジャンプの個数の指数関数のオーダーの個数の制御フローを解析対象とする必要がある。従って、本実施形態の構成によれば、条件ジャンプの個数によって解析の困難さを定量的に見積もることができる。
【００６２】
また、プログラムが改ざんされていないことをプログラムが実行中に確認する構成においては、観測を行う処理自体は容易に突き止められにくいとしても観測値の比較処理を発見されてしまい、比較処理を無効化される恐れがあった。更に、複数の改ざん検出ルーチンが設けられる構成の場合に、それらの依存関係をどのように構成すれば、どのような攻撃に対してどの程度の強さを持つのか、その効果を数値で示すことができないという課題があった。
【００６３】
これに対して、本実施形態では、基準値算出処理の結果（基準値）を用いて、プログラムが改ざんされていないことをプログラムが実行中に確認する。即ち、処理対象のプログラム中に含まれる処理命令の出力値が格納されるメモリを参照し、当該参照された値に基づいて対象インストラクションのプログラムにおける位置を特定する。
【００６４】
このため、比較処理はアドレス計算処理として実現され、その処理結果が正しいときは自己書き換え処理が成功するという動作をする。比較処理と比べるとアドレス計算処理は複数のインストラクションから構成されるので、それらのインストラクションを分散化することによって攻撃者が発見する可能性を低くすることができ、無効化に対する安全性を高めることができる。
【００６５】
また、従来の改ざん自己検出処理における比較処理1回は、本実施形態における自己書き換え処理の1回に相当する。従来の改ざん自己検出処理における比較処理がk回の場合、本実施形態によって生成されるプログラムの解析対象としなければならない制御フローの個数は2のk乗になる。従って、プログラムを読んで理解しながら解析する攻撃者は、改ざん自己検出処理における比較処理の回数の指数関数のオーダーの個数の制御フローを解析対象とする必要がある。従って、本実施形態の構成によれば、比較処理の個数によって解析の困難さを定量的に見積もることができる。さらに、改ざん自己検出処理の改ざん検出ルーチンの依存関係とは関係なく、解析の困難さを定量的に見積もることができる。
＜＜第２の実施形態＞＞
第１の実施形態では、ルーチンXが、偽装インストラクションYで偽装する位置P(Y)をBASE位置、基準値、マスク値に基づき算出し、当該位置P(Y)のインストラクションを偽装インストラクションYで書き換えるように、ルーチンXを構成した。本実施形態では、ルーチンXが、偽装インストラクションYのオペコードあるいはオペランドを基準値とマスク値の2つの値に基づいて算出し、インストラクションyを偽装インストラクションYで書き換える形態の自己書換え処理追加プログラムを説明する。インストラクションは、命令（オペコード）と命令の対象であるオペランドから構成され、オペランドとしては、レジスタやメモリの内容、数値そのもの等が考えられる。
【００６６】
図13は、図2のソース・プログラムをコンパイルして生成したアセンブリ・プログラムの一部分を示す図である。中央付近に四角で囲ったインストラクション「addl   $0x4,(%eax)」がある。このインストラクションは、「addl」という命令（オペコード）と「$0x4」および「(%eax)」というオペランドから構成され、レジスタ「eax」に数値「4」（16進数）を32ビットのデータとして加算する処理を意味する。addlのlはlong、つまり32ビットを指定する。このインストラクションの機械語プログラムは「83 00 04」（16進数）であり、「addl」および「(%eax)」と「83 00」が対応し、「$0x4」と「04」が対応する。
【００６７】
Intel x86系CPUでは、以下の対応関係が成り立つ。
アセンブリ「addl $0x4, (%eax)」は機械語「83 00 04」(16進数)。
アセンブリ「addl $0x4, (%edx)」は機械語「83 02 04」(16進数)。
アセンブリ「subl $0x4, (%eax)」は機械語「83 28 04」(16進数)。
アセンブリ「sub  $0x4, (%edx)」は機械語「83 EA 04」(16進数)。
アセンブリ「movb $0x4, (%eax)」は機械語「C0 00 04」(16進数)。
アセンブリ「rolb $0x4, (%eax)」は機械語「C6 00 04」(16進数)。
【００６８】
したがって、例えば、インストラクション「addl $0x4,(%eax)」の機械語「83 00 04」(16進数)の最初の1バイトを「C0」に書換えたとする。この場合、書換えられた機械語「C0 00 04」はインストラクション「movb   $0x4,(%eax)」に対応する。同様に、最初の1バイトを「C6」に書換えると書換えられた機械語プログラム「C6 00 04」はインストラクション「rolb   $0x4,(%eax)」に対応する。2バイト目の「00」を「28」に書換えると書換えられた機械語プログラム「83 28 04」はインストラクション「subl  $0x4,(%eax)」に対応する。つまり、機械語プログラムの1バイトを書換えることで、命令（オペコード）を異なる命令（オペコード）に変えることができる。
【００６９】
また、前述のインストラクション「addl   $0x4,(%eax)」の機械語「83 00 04」の2バイト目「00」を「02」に書換えたとする。この場合、書換えられた機械語「83 02 04」はインストラクション「addl  $0x4,(%edx)」に対応する。つまり、機械語プログラムの1バイトを書換えることで、オペランドのレジスタを異なるレジスタに変えることもできる。
【００７０】
最後に、前述のインストラクション「addl   $0x4,(%eax)」の機械語「83 00 04」の3バイト目「04」を「03」に書換えたとする。この場合、書換えられた機械語「83 00 03」はインストラクション「addl  $0x3,(%edx)」に対応する。つまり、機械語プログラムの1バイトを書換えることで、オペランドの数値を異なる数値に変えることもできる。
【００７１】
以上から、偽装対象をオペコード又はオペランドとし、その本来のオペコード又はオペランドを基準値とマスク値に基づいて算出し、当該インストラクションを偽装インストラクションYで書換えるように、ルーチンXを構成することが可能である。
【００７２】
第1の実施形態と同じく図1と図2を参照しながら、本実施形態における自己書き換え処理追加プログラムに基づくCPU303の処理の流れを説明する。自己書き換え処理追加プログラムの処理対象となる保護すべきプログラムは、例えば、C言語で記述されたソース・プログラムとして、RAM305に記録されているものとする。
【００７３】
ステップS101において、CPU303はRAM305に記憶されたソース・プログラムをコンパイルしてアセンブリ・プログラムを生成する。図13は、図2のソース・プログラムをコンパイルして生成したアセンブリ・プログラムの一部分を示す図である。
【００７４】
ステップS102において、CPU303は自己書き換えの対象となりうるインストラクションが、対象のアセンブリ・プログラムに存在するか否かを判定アルゴリズムによって判定する。判定アルゴリズムは簡単なアルゴリズムから複雑なアルゴリズムまでいろいろ考えられるが、ここでは対象のアセンブリプログラムからランダムに1行を選ぶアルゴリズムであるものとして説明する。
【００７５】
後述するように、CPU303は、自己書き換え対象に決定したインストラクションをRAM305に記録するため、ステップS102では、このRAM305の記録を参照して判定を行う。ステップS102において、判定アルゴリズムが、対象が存在すると判定した場合はステップS103に進み、対象が存在しないと判定した場合はステップS110に進む。図13の中央付近の四角で囲まれた「addl $4, (%eax)」を対象インストラクションyとし、対象が存在すると判定したとする。
【００７６】
ステップS103では、CPU303が、処理対象のインストラクションを自己書き換えの対象とするか否かをランダムに決定する。なお、本実施形態では、アセンブリ・プログラムの一行が一つのインストラクションに相当する。そこで、ステップS103では、アセンブリ・プログラムの未処理の行の中から一つの行を処理対象として選択し、当該行のインストラクションを偽装するか否かをランダムに決定する。対象インストラクションy「addl $4, (%eax)」を偽装すると決定したとする。CPU303は、どのインストラクションが自己書き換えの対象として決定されたかをRAM305に記憶する。異なるインストラクションYで偽装する位置（例えば、アドレス、行番号）をP(Y)とする。
【００７７】
このようにして、ステップS102、S103では、処理対象のプログラムに含まれるインストラクションのうち、偽装インストラクションへの書き換え対象となる対象インストラクションを決定する。
【００７８】
次に、ステップS104において、CPU303は偽装インストラクションYを決定する。本実施形態では、元のインストラクションy「addl $4, (%eax)」のオペランドの数値$4と異なる数値$3をオペランドとするインストラクションを偽装インストラクションYとして決定する。これらの処理は、コンピュータ装置300上に実現される、偽装インストラクション生成unitとしての機能要素により実行される。
【００７９】
以下、ステップS105〜S108では、偽装インストラクションYを真のインストラクションyで書き換える（復元する）ためのルーチンX（復元命令）を生成する。これらの処理は、コンピュータ装置300上に実現される、復元命令生成unitとしての機能要素により実行される。そして、ステップS109では、ルーチンXを処理対象のアセンブリ・プログラムに挿入し、真のインストラクションyを偽装インストラクションYで書き換える。
【００８０】
本実施形態では、ルーチンXが、偽装インストラクションYの偽装されたオペランドを本来のオペランドに復元するように、ルーチンXを構成する。具体的には、本来のオペランドを以下の２つの値に基づいて算出し、当該位置P(Y)のインストラクションを偽装インストラクションYで書き換えるように、ルーチンXを構成する。
・アセンブリ・プログラム中の固定値を算出する予め定められた処理（以下、基準値算出処理）の算出値（以下、基準値）。
・本来のオペランドの機械語 XOR 基準値（以下、マスク値）
ルーチンXは、「基準値 XOR マスク値」を計算することによって、本来のオペランドを算出する。ここで、ルーチンXにおいて、基準値は、アセンブリ・プログラム中の基準値算出処理の処理結果が格納されたメモリを参照することにより取得される。即ち、ルーチンXは、処理対象のプログラム中に含まれる処理命令（基準値算出処理）の出力値が格納されるメモリを参照し、参照された値に基づいてインストラクションyのオペランドを特定して、真のインストラクションyを復元する。このため、攻撃者は、アセンブリ・プログラムのルーチンXに相当する箇所を閲覧しても基準値を知ることが困難である。したがって、アセンブリ・プログラムの本来のオペランドを判別することが困難なため、攻撃者は、アセンブリ・プログラムの動作を解析したり、所望の動作をするように改ざんしたりすることが困難である。
【００８１】
なお、本実施形態では、基準値算出処理の出力値（基準値）は固定値であるため、マスク値を容易に決定することができる。
【００８２】
以下、各ステップの詳細を説明する。ステップS105において、CPU303は、アセンブリ・プログラムにおける基準値算出処理とその位置、及び、P(X)を決定する。上述のように、ルーチンXは、真のインストラクションyをP(Y)に書き込む処理を行なうが、P(X)はルーチンXを挿入する位置を示す。P(X)は、基準値算出処理の位置からP(Y)までの制御フローのいずれかの箇所に決定する。図13においては、「call _cont」「movl %eax, -12(%ebp)」を基準値算出処理、「addl $4 (%eax)」を自己書き換え対象のインストラクション、「$4」対象のオペランドとして決定した例を示している。また、図13では、基準値算出処理の次の行をP(X)と決定した例を示している。
【００８３】
なお、基準値算出処理は、プログラムの中で行なわれる様々な処理を利用することができる。例えば、背景技術で説明した、プログラムが改ざんされていないことをプログラムが実行中に確認する方法における、観測値を算出する処理である。本実施形態では、理解を容易にするために図2の関数cont(,)を基準値算出処理として説明するが、Cのソース・プログラムには明示的には存在せず、アセンブリ・プログラムにのみ存在する処理であってもよい。なお、上述のように基準値は、基準値算出処理の処理結果である。また、基準値算出処理は、確定的な値を計算する処理である。つまり、処理の実行結果として固定値が出力される。
【００８４】
次に、CPU303は、ステップS106において基準値の決定、ステップS107においてマスク値の決定、ステップS108においてルーチンXの生成を行う。これらのステップは、詳細には以下のように行なわれる。
【００８５】
ルーチンXにおいては、自己書き換え対象とする偽装インストラクションYの本来のオペランドが必要である。このため、CPU303は、「マスク値＝本来のオペランドの機械語 XOR 基準値」の関係を満たすように本来のオペランドの機械語と基準値とからマスク値を計算・決定する。
【００８６】
図4の例では、ステップS103において、偽装インストラクションYの位置P(Y)は「addl $4, (%eax)」の位置と決定されている。基準値算出処理は、図4における「call _cont」であり、それによって計算された出力はその次のインストラクション「movl %eax, -12(%ebp)」によって「-12(%ebp)」に格納されている。上述のように基準値算出処理「call _cont」は、図2におけるcont(,)に対応しており、関数main(,)中のcont(,)の算出値はcont(l,45)＝cont(50,45)＝50-45＝5である。したがって、CPU303はその計算結果の「5」をあらかじめ計算しておくことができる。以下では、図13のアセンブリ・プログラムから、図14に示す、自己書き換え処理を追加した結果のアセンブリプログラムを作成する手順を述べる。
【００８７】
まず、CPU303はプログラム中の自己書換え対象の位置（LABEL位置）を決める。ここでは、図13の「addl $4, (%eax)」の位置が選択されたとする。そのインストラクションのアドレスを「LABELのアドレス」と呼ぶことにする。アセンブリ・プログラム上では「addl $4, (%eax)」の前に「LABEL:」を挿入する。なお、第1の実施形態のように、自己書換え対象の位置を直接選択せずに他の位置を選択し、その他の位置から計算によって自己書換え対象の位置を間接的に求めることも可能である。
【００８８】
ここで、自己書き換えを行なう対象の偽装インストラクションYは「addl $4, (%eax)」である。以下、P(Y)を「TARGETのアドレス」と呼ぶ。
【００８９】
上述のように、「本来のオペランドの機械語＝基準値 XOR マスク値」の関係が成立している。これより、「マスク値＝本来のオペランドの機械語 XOR 基準値」である。上記の例のように、基準値＝5の場合は「マスク値＝本来のオペランドの機械語 XOR 5」となる。従って、マスク値は、「4 XOR 5」＝「100 XOR 101」(2進数)＝1(2進数)となる。
【００９０】
次に、図14の自己書き換えルーチンXを参照しながら、その処理内容を生成する方法を説明する。ルーチンXは、P(Y)のインストラクションのオペランドに本来のオペランドを書き込むことが目的なので、まず本来のオペランドを求める。他の処理に影響を与えないために、レジスタedxをその計算に用いる。
【００９１】
最初にCPU303は「movl -12(%ebp), %edx」を生成する。これは、-12(%ebp)をレジスタedxに格納するインストラクションである。ここで、-12(%ebp)には、基準値算出処理の結果が格納されており、その値は5である。よって、レジスタedxには値5が格納される。
【００９２】
そして、CPU303は「movl $1, %ecx」を生成する。これは、レジスタecxに値1を格納するインストラクションである。
【００９３】
そして、CPU303は「xorl %ecx, %edx」を生成する。これは、レジスタedxの値とレジスタecxの値のXORを計算し、その結果をedxに格納するインストラクションである。レジスタecxとレジスタedxは32ビットであり、値5と値1のXORをとった結果の値4がレジスタedxに格納される。Intel x86系CPUの場合、16進数の「04 00 00 00 00 00 00 00」がedxに格納される。
【００９４】
次に、CPU303は「movl $LABEL+2, %ebx」を生成する。これは、LABELのアドレス、$LABEL、の2バイト先のアドレス、$LABEL+2、をレジスタebxに代入するインストラクションである。本来のインストラクションy「addl $4, (%eax)」の機械語は「83 00 04」である。従って、$LABEL+2は機械語「04」が存在するアドレスを表し、レジスタebxにはそのアドレスが格納されている。
【００９５】
最後に、CPU303は「movb %dl, (%ebx)」を生成する。ここで、レジスタebxに格納されているアドレス(%ebx)は$LABEL+2である。従って、「movb $dl, (%ebx)」は、偽装インストラクションYを真のインストラクション「addl $4, (%eax)」に書き換えるために、4を(%ebx)に書き込むインストラクションである。ただし、%dlは%edxの上位1バイトであるので、16進数の「04 00 00 00 00 00 00 00」の上位1バイトの「04」である。従って、機械語「04」が$LABEL+2に書き込まれる。
【００９６】
このようにして、図5の実線上部の四角で囲ったルーチンXが生成される。このようなルーチンXは、一例である。例えば、前述のようにLABELとして別の位置を採用してもよく、マスク値を定めるための演算としてXORではなく加算、減算、シフト演算、論理演算を用いることも可能である。
【００９７】
次に、ステップS109において、上記のルーチンXをP(X)に挿入する。ここでは、図13の基準値算出処理の次の行の位置に上記ルーチンXを挿入する。また、自己書き換え対象のインストラクションYとして偽のインストラクションを生成する。本実施形態では、「addl $4, (%eax)」のオペランド$4を$3に偽装するものとし、「addl $3, (%eax)」をP(Y)に書き込む。この結果、図13のアセンブリ・プログラムは図14のアセンブリプログラムに変更される。
【００９８】
次に、ステップS102に戻り、CPU303は自己書き換えの対象となるインストラクションが存在するか否かを判定し、ステップS103において偽装するか否かをランダムに決定する。偽装する場合は、ステップS104からステップS109の処理を繰り返し、偽装しない場合はステップS102に戻る。書き換え対象インストラクションが存在しない場合はステップS110に進む。
【００９９】
ステップS110においては、CPU303は自己書き換えプログラムをアセンブルして機械語プログラムを生成する。必要であれば機械語プログラムをリンクして、実行可能プログラムを生成する。また、CPU303は、実行可能プログラムに対して、プログラムのコード領域への書き込みを許可するフラグを立てるなどの処理を施し、そのプログラムが実行時に自らのコード領域に書き込みできるようにする。
【０１００】
偽装インストラクションYは、それを自己書換えすることで本来のインストラクションyに戻るインストラクションでなければならない。従って、1バイトの自己書換えが行なわれるときは、本来のインストラクションと偽装インストラクションとの差は1バイト以内である必要がある。Intel x86系CPUの場合は、1バイト単位、2バイト単位、4バイト単位の書換えを行なうことができる。従って、本来のインストラクションと偽装インストラクションとの差が最大で4バイト以内であれば、1回の自己書換えで偽装インストラクションを本来のインストラクションに戻すことが可能である。
＜＜第３の実施形態＞＞
第１の実施形態と第２の実施形態を組み合わせることが可能である。第１の実施形態において図5のアセンブリプログラムが生成された。このアセンブリプログラムに対して第２の実施形態で説明した自己書換え処理追加プログラムを適用する。このとき、自己書換え対象インストラクションとして、例えば図5のXの3行目「subl $0x21, %edx」あるいは4行目「movb  $0x74, (%edx)」を選択し偽装すると決定したとする。そのようにして生成された自己書換えプログラムは、より解析や改ざんが困難であることは明らかである。
【０１０１】
さらに、同一のインストラクションの自己書換えが複数回実行されるように構成することも可能である。例えば、1回目の自己書換えでは命令(オペコード)が自己書換えされ、2回目の自己書換えではオペランドの一つが自己書換えされ、3回目の自己書換えでは他のオペランドが自己書換えされるという場合である。
【０１０２】
＜＜その他の実施形態＞＞
本発明の目的は、前述した実施形態の機能を実現するソフトウエアのプログラムコードをシステムあるいは装置で実行することによっても達成されることは言うまでもない。この場合、プログラムコード自体が前述した実施形態の機能を実現することとなり、そのプログラムコードは本発明の技術的範囲に含まれる。
【０１０３】
プログラムコードは、例えば、コンピュータ読み取り可能な記録媒体に記録してシステムあるいは装置に供給することができる。そのシステムあるいは装置のコンピュータ（またはＣＰＵまたはＭＰＵ）は、記録媒体に格納されたプログラムコードを読み出し実行することによっても、本発明の目的を達成することができる。従って、そのプログラムコードを記憶した記録媒体も本発明の技術的範囲に含まれる。
【０１０４】
プログラムコードを供給するための記録媒体としては、例えば、フレキシブルディスク、ハードディスク、光ディスク、光磁気ディスク、ＣＤ−ＲＯＭ、ＣＤ−Ｒ、磁気テープ、不揮発性のメモリカード、ＲＯＭ、ＤＶＤなどを用いることができる。
【０１０５】
なお、プログラムコードは、コンピュータが当該プログラムコードを読み出し実行することにより前述した実施形態の機能を実現するための、全ての要素を備えたものに限られない。即ち、プログラムコードには、コンピュータに組み込まれたソフトウェア及びハードウェアの少なくともいずれかと協働することにより目的を達成するプログラムコードも含まれる。
【０１０６】
例えば、プログラムコードの指示に基づき、コンピュータ上で稼動しているＯＳなどが実際の処理の一部または全部を行い、その処理によって前述した実施形態の機能が実現される場合も、そのプログラムコードは本発明の技術的範囲に含まれる。ただし、ＯＳはオペレーティングシステム（Operating System）の略称である。
【０１０７】
あるいは、例えば、プログラムコードの指示に基づき、コンピュータに挿入又は接続された機能拡張ボードや機能拡張ユニットに備わるＣＰＵなどが実際の処理の一部または全部を行い、その処理によって前述した実施形態の機能が実現される場合がある。このような場合も、そのプログラムコードは本発明の技術的範囲に含まれる。なお、機能拡張ボードや機能拡張ユニットは、それらが備えるメモリにプログラムコードを読み込み、実行することでこのような処理を行うことができる。
【０１０８】
上記のように、本実施形態の構成によれば、保護対象プログラムが実行される時に得られる値に基づいて自己書き換え対象インストラクションのアドレスを決定するルーチンを生成する。そして、対象インストラクションを偽装インストラクションに書き換え、このルーチンを対象インストラクションの実行よりも前に実行される位置に挿入することによって、保護対象プログラムに自己書き換え処理を追加している。この自己書き換え処理を追加された保護対象プログラムを実行すると、上記のルーチンが実行されることにより対象インストラクションのアドレスが求められて自己書き換えが行われ、真のインストラクションに戻され、意図とおりの処理を行う。
【０１０９】
プログラムの解析を行うためには、どのインストラクションが偽装されており、自己書き換えによって書き換えられるのかを知らなければならない。しかし、保護対象プログラムが実行されるときに得られる値はプログラムを読んで解析しようとする攻撃者にとっては不定であるため、偽装インストラクションを定めることはできない。従って、保護対象プログラムの解析および改ざんを困難にすることができる。
【０１１０】
また、条件ジャンプを含むインストラクションがそれとは逆の処理を行うインストラクションに偽装され、実行時に元に戻されるので、攻撃者が解析しなければならない制御フローの個数は条件ジャンプの個数の指数関数となる。従って、保護対象プログラムの解析の困難性を数値で示すことができる。
【図面の簡単な説明】
【０１１１】
【図１】自己書き換え処理追加プログラムに基づく処理の流れを示すフローチャートである。
【図２】Cのソース・プログラムの例を示す図である。
【図３】コンピュータ装置の内部構成を示すブロック図である。
【図４】アセンブリ・プログラムの一例を示す図である。
【図５】自己書き換え処理を追加した結果のアセンブリプログラムの一例を示す図である。
【図６】Cのソース・プログラムの別の例を示す図である。
【図７】図2のコードを実行した結果を示す図である。
【図８】図6のコードを実行した結果を示す図である。
【図９】フローチャート例を示す図である。
【図１０】偽装したフローチャートの例を示す図である。
【図１１】偽装したフローチャートの別の例を示す図である。
【図１２】偽装したフローチャートの別の例を示す図である。
【図１３】アセンブリ・プログラムの一例を示す図である。
【図１４】自己書き換え処理を追加したアセンブリプログラムの一例を示す図である。
【図１】
2009104589.tif 000003
【図２】
2009104589.tif 000004
【図３】
2009104589.tif 000005
【図４】
2009104589.tif 000006
【図５】
2009104589.tif 000007
【図６】
2009104589.tif 000008
【図７】
2009104589.tif 000009
【図８】
2009104589.tif 000010
【図９】
2009104589.tif 000011
【図１０】
2009104589.tif 000012
【図１１】
2009104589.tif 000013
【図１２】
2009104589.tif 000014
【図１３】
2009104589.tif 000015
【図１４】
2009104589.tif 000016