(57)【要約】【課題】通常のリンカでリンクを行っても、外部オブジェクトを参照する原プログラムコードを符号化した符号化プログラムコードを正しく復号できるようにする。【解決手段】オブジェクトファイル１００は、原プログラムコードの符号化結果である符号化プログラムコード１３２と、符号化プログラムコードを復号して原プログラムコードを復元するための復号コード１２４と、原プログラムコード中で参照される外部オブジェクトのアドレスを表す外部参照テーブル１４２と、外部プログラムからの呼び出しに応じて、復号プログラムコードにより復元された原プログラムコードを、外部参照テーブルのアドレスを引数として呼び出すための呼び出しコード１２８と、を備え、原プログラムコードは、外部参照テーブルのアドレスにアクセスして外部オブジェクトのアドレスを取得し、そのアドレスを用いて外部オブジェクトを参照する。【選択図】図１
2010231477.tif 000002
【特許請求の範囲】
【請求項１】
原プログラムコードの符号化結果である符号化プログラムコードと、
前記符号化プログラムコードを復号して前記原プログラムコードを復元する処理を前記コンピュータに実行させるための復号プログラムコードと、
前記原プログラムコード中で参照される外部オブジェクトのアドレスを表す外部参照情報と、
外部プログラムからの呼び出しに応じて、前記復号プログラムコードにより復元された前記原プログラムコードを、前記外部参照情報のアドレスを引数として呼び出す処理を、前記コンピュータに実行させるための呼び出しプログラムコードと、
を備え、
前記原プログラムコードは、前記外部参照情報のアドレスにアクセスして前記外部オブジェクトのアドレスを取得し、取得したアドレスを用いて前記外部オブジェクトを参照する処理を前記コンピュータに実行させる、
ことを特徴とするプログラム。
【請求項２】
前記原プログラムコード中で参照される外部オブジェクトのアドレスを取得し、前記外部参照情報として、取得したアドレスを含んだ情報を生成するための処理を前記コンピュータに実行させるための外部参照情報作成プログラムコード、
を更に備えることを特徴とする請求項１記載のプログラム。
【請求項３】
前記プログラムは、
読み出し、書き込み、及び実行が可能なメモリ領域を前記コンピュータのメモリ上に確保する処理を前記コンピュータに実行させるためのプログラムコード、
を更に含み、
前記復号プログラムコードは、復号の結果である前記原プログラムコードを前記確保されたメモリ領域に書き込むための処理を前記コンピュータに実行させる、
ことを特徴とする請求項１記載のプログラム。
【請求項４】
前記コンピュータを、
前記復号プログラムコードが既実行か未実行かを表すフラグを記憶するフラグ記憶手段、
前記呼び出しプログラムコードが呼び出された場合に、前記フラグ記憶手段に記憶された前記フラグが未実行を表す場合には前記復号プログラムコードを実行して前記フラグを既実行に変更し、前記フラグが既実行を表す場合には前記復号プログラムコードを実行しないように制御する制御手段、
として更に機能させることを特徴とする請求項１記載のプログラム。
【請求項５】
原プログラムコードの符号化結果である符号化プログラムコードを復号して前記原プログラムコードを復元する復号手段と、
前記原プログラムコード中で参照される外部オブジェクトのアドレスを表す外部参照情報を記憶する外部参照情報記憶手段と、
外部プログラムからの呼び出しに応じて、前記復号プログラムコードにより復元された前記原プログラムコードを、前記外部参照情報のアドレスを引数として呼び出す呼び出し手段と、
前記呼び出し手段により呼び出された前記原プログラムコードを実行する実行手段と、
を備え、
前記原プログラムコードは、前記外部オブジェクトを参照する場合に、前記外部参照情報のアドレスにアクセスして前記外部オブジェクトのアドレスを取得し、取得したアドレスを用いて前記外部オブジェクトを参照する処理を前記実行手段に実行させる、
ことを特徴とするプログラム実行装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラム及びプログラム実行装置に関する。
【背景技術】
【０００２】
コードの配布方法は、完成されたプログラムの形式だけでない。開発者に対しては、自ら生成したプログラムから配布されたコードを呼び出せるように、ライブラリという形式で渡される方法は、広く用いられている。このライブラリに含まれるコードの形態は、Ｃ言語を始めとする一般的なコンパイラ言語においては、オブジェクトコードと呼ばれるコンパイル後でリンク前の中間状態のコードとなっている。
【０００３】
またコード内に含まれる秘密を秘匿するためにコードの一部を暗号化しておきたいという要求が存在するが、このオブジェクトコードに対しても、暗号化により、コード内の情報を秘匿したいという要求は存在する。
【０００４】
リンク時に各オブジェクトが割り当てられるアドレスが決定する(アドレス解決)ため、このオブジェクトコードに対して符号化を行おうとした場合には、符号化されたコードに対して、リンク時のアドレス解決の結果としてコードの書き換えが発生し、アドレス解決の結果が正しく実施できない。加えて、符号化されたコードが変更された結果として、復号が正しく行えなくなるという問題を持つ。
【０００５】
アドレス解決が不要になる様にコードを作成すると、前記問題は発生しないが、外部のデータやコードを利用する機能を記述できないため、実現できる機能が強く限定されてしまい、実用的な機能は提供できない。
【０００６】
また、実行形式のコードでは、位置独立コード(PIC)と呼ばれるアドレス解決によるコードの書き換えが発生しない方式が用いられているが、この方式はリンク後の実行形式のコードに対する技術であり、オブジェクトコードの段階でこの様なコードを生成する機構は存在しない。
【０００７】
特許文献１（特に図１）及び２には、オブジェクトファイルを暗号化して配布し、他のコードとのリンク時に復号して、リンクし、その後再び暗号化を行う方法により、オブジェクトファイル内のコードをディスアセンブルされるのを防ぐ方法が開示されている。当該技術によって作成されたオブジェクトファイルは、リンク作業時に、リンクする直前に、復号部が暗号化されたオブジェクトコードを復号し、リンク後に、復号したコードを再び暗号化するという手順で動作する。
【０００８】
また、特許文献３（特に図２）には、実行形式のプログラム、ダイナミックリンクライブラリのコードにおいて、実行中に符号化されたコードを実行する前に、対象コードを復号し、その復号後かつ対象コードを実行する前に、対象コード内のアドレス変更が必要なコードの書き換えを行う方法により、コード内の一部のコードを符号化しておく技術を開示している。
【先行技術文献】
【特許文献】
【０００９】
【特許文献１】特開平４−２６８９２４号公報
【特許文献２】特開平４−３１０１２８号公報
【特許文献３】特許第３０３３５６２号明細書
【発明の概要】
【発明が解決しようとする課題】
【００１０】
本発明は、通常のリンカでリンクを行っても、外部オブジェクトを参照する原プログラムコードを符号化した符号化プログラムコードを正しく復号できるようにすることを目的とする。
【課題を解決するための手段】
【００１１】
請求項１に係る発明は、原プログラムコードの符号化結果である符号化プログラムコードと、前記符号化プログラムコードを復号して前記原プログラムコードを復元する処理を前記コンピュータに実行させるための復号プログラムコードと、前記原プログラムコード中で参照される外部オブジェクトのアドレスを表す外部参照情報と、外部プログラムからの呼び出しに応じて、前記復号プログラムコードにより復元された前記原プログラムコードを、前記外部参照情報のアドレスを引数として呼び出す処理を、前記コンピュータに実行させるための呼び出しプログラムコードと、を備え、前記原プログラムコードは、前記外部参照情報のアドレスにアクセスして前記外部オブジェクトのアドレスを取得し、取得したアドレスを用いて前記外部オブジェクトを参照する処理を前記コンピュータに実行させる、ことを特徴とするプログラムである。
【００１２】
請求項２に係る発明は、請求項１に係る発明において、前記原プログラムコード中で参照される外部オブジェクトのアドレスを取得し、前記外部参照情報として、取得したアドレスを含んだ情報を生成するための処理を前記コンピュータに実行させるための外部参照情報作成プログラムコード、を更に備えることを特徴とする。
【００１３】
請求項３に係る発明は、請求項１に係る発明において、前記プログラムは、読み出し、書き込み、及び実行が可能なメモリ領域を前記コンピュータのメモリ上に確保する処理を前記コンピュータに実行させるためのプログラムコード、を更に含み、前記復号プログラムコードは、復号の結果である前記原プログラムコードを前記確保されたメモリ領域に書き込むための処理を前記コンピュータに実行させる、ことを特徴とする。
【００１４】
請求項４に係る発明は、請求項１に係る発明において、前記コンピュータを、前記復号プログラムコードが既実行か未実行かを表すフラグを記憶するフラグ記憶手段、前記呼び出しプログラムコードが呼び出された場合に、前記フラグ記憶手段に記憶された前記フラグが未実行を表す場合には前記復号プログラムコードを実行して前記フラグを既実行に変更し、前記フラグが既実行を表す場合には前記復号プログラムコードを実行しないように制御する制御手段、として更に機能させることを特徴とする。
【００１５】
請求項５に係る発明は、原プログラムコードの符号化結果である符号化プログラムコードを復号して前記原プログラムコードを復元する復号手段と、前記原プログラムコード中で参照される外部オブジェクトのアドレスを表す外部参照情報を記憶する外部参照情報記憶手段と、外部プログラムからの呼び出しに応じて、前記復号プログラムコードにより復元された前記原プログラムコードを、前記外部参照情報のアドレスを引数として呼び出す呼び出し手段と、前記呼び出し手段により呼び出された前記原プログラムコードを実行する実行手段と、を備え、前記原プログラムコードは、前記外部オブジェクトを参照する場合に、前記外部参照情報のアドレスにアクセスして前記外部オブジェクトのアドレスを取得し、取得したアドレスを用いて前記外部オブジェクトを参照する処理を前記実行手段に実行させる、ことを特徴とするプログラム実行装置である。
【発明の効果】
【００１６】
請求項１又は５に係る発明によれば、通常のリンカでリンクを行っても、外部オブジェクトを参照する原プログラムコードを符号化した符号化プログラムコードを正しく復号できる。
【００１７】
請求項２に係る発明によれば、外部オブジェクトのアドレスが実行時に動的に決定される場合でも、符号化プログラムコードの復号結果である原プログラムコードからその外部オブジェクトにアクセスすることができる。
【００１８】
請求項３に係る発明によれば、符号化プログラムコードの復号結果の原プログラムコードを、コンピュータが実行できるようにすることができる。
【００１９】
請求項４に係る発明によれば、外部プログラムが復号コードと呼び出しコードをそれぞれ個別に呼び出す必要をなくすことができる。
【図面の簡単な説明】
【００２０】
【図１】実施の形態のオブジェクトファイルのデータ構造の例を示す図である。
【図２】外部参照テーブルのデータ構造の例を示す図である。
【図３】実施の形態のオブジェクトファイルの生成及び利用の流れを説明するための図である。
【図４】コンパイルによる外部参照テーブルの内容変遷の例を示す図である。
【図５】リンク及びロード・実行による外部参照テーブルの内容変遷の例を示す図である。
【図６】コンピュータのハードウエア構成の一例を示す図である。
【図７】リンク後の実行可能プログラムが実行される際の処理の流れの一例を示す図である。
【図８】オブジェクトファイルの実行によりコンピュータが実現するプログラム実行装置の機能的構成の例を示すブロック図である。
【発明を実施するための形態】
【００２１】
以下、図面を参照して本発明の実施の形態を説明する。まず、図１を参照して、実施の形態のオブジェクトファイル１００のデータ構造の一例を説明する。このオブジェクトファイル１００は、例えばライブラリ関数又はライブラリファイルとして用いられる。
【００２２】
図１に例示するように、オブジェクトファイル１００は、オブジェクトヘッダ１１０、コードセクション１２０、独自セクション１３０及びデータセクション１４０を含んでいる。これら各セクションは、ＣＰＵ（中央演算ユニット）等のマイクロプロセッサが実行できる機械語で記述されている。
【００２３】
オブジェクトヘッダ１１０は、当該ファイル１００のヘッダ情報を記述したセクションである。また、コードセクション１２０はプログラムコードが含まれるセクションであり、データセクション１４０はプログラムコードの実行において用いられるデータが含まれるセクションである。これらオブジェクトヘッダ１１０、コードセクション１２０及びデータセクション１４０は、一般的なオブジェクトファイル形式にも存在する。
【００２４】
これに対し、独自セクション１３０は、この実施の形態のオブジェクトファイル独自のものである。独自セクション１３０は、読み出し、書き込み及び実行が可能なセクションである。独自セクション１３０には、符号化（例えば暗号化）対象のプログラムコード（原プログラムコードと呼ぶ）の符号化結果である符号化プログラムコード１３２が置かれる。ここで、原プログラムコードは、このオブジェクトファイル１００が他のプログラムに対して提供する機能を記述したプログラムコードである。
【００２５】
なお、独自セクション１３０に符号化プログラムコード１３２が置かれるのは、オブジェクトファイル１００が符号化による保護を受けた後の段階（例えば配布時）でのことであり、符号化の前の段階では独自セクション１３０には原プログラムコードが置かれる。
【００２６】
一般的なオブジェクトファイルでは原プログラムコードはコードセクション１２０に置かれるのに対し、この実施の形態では、以上のように、原プログラムコードを符号化した符号化プログラムコード１３２はコードセクション１２０ではなく独自セクション１３０に置かれる。
【００２７】
一方、この実施の形態のコードセクション１２０には、独自セクション１３０に置かれた符号化プログラムコード１３２を実行するためのプログラムコードが置かれる。すなわち、この例では、コードセクション１２０には初期化関数１２２と呼び出しコード１２８とが置かれる。
【００２８】
初期化関数１２２は、ライブラリ（オブジェクトファイル１００）の初期化処理を表すプログラムである。初期化処理には、符号化プログラムコード１３２の復号処理と、外部参照テーブル１４２の作成処理とが含まれる。前者をマイクロプロセッサに実行させるためのプログラムコードが復号コード１２４であり、後者を実行させるためのプログラムコードが外部参照テーブル作成コード１２６である。初期化関数１２２は、例えば、このライブラリを利用するリンク元コード（すなわち外部プログラム）から呼び出される。
【００２９】
ここで、外部参照テーブル１４２は、符号化プログラムコード１３２の復号結果である原プログラムコードが参照する外部オブジェクトのアドレス情報を保持するためのテーブルである。ここで、外部オブジェクトは、例えば、セクション外の関数呼び出しや、スタック外に置かれる静的データなどである。なお、ここで言うセクションは、復号結果の原プログラムコードがロードされた独自セクションのことであり、スタックは、オブジェクトファイル１００がメモリにロードされた場合にデータセクションに作成されるスタック領域のことである。
【００３０】
外部参照テーブル１４２は、実行時には、図２に概念的に示すように、各外部オブジェクトの実行時のアドレスの配列となる。図では、便宜上、各外部オブジェクトを名前で特定し、その名前に対応づけてアドレスの値を示しているが、実際には、図５に示したメインメモリ上の外部参照テーブルのイメージ例５０のように、メインメモリ上での外部参照テーブル１４２のアドレス範囲内の各アドレス（これらがそれぞれ外部オブジェクトに対応する）に、当該外部オブジェクトの実行時アドレスの値を記憶したものとなる（詳細は後述）。なお、以上に説明した外部参照テーブル１４２の状態は、当該オブジェクトファイル１００が外部プログラムとリンクされ、実行される状態となったときのものである。このような外部参照テーブル１４２がどのように作成されるかについては、後で図４及び図５を参照して詳しく説明する。
【００３１】
外部参照テーブル作成コード１２６は、外部参照テーブル１４２の中で、実行時に動的に作成される部分を作成するための処理を記述したプログラムコードである。外部参照テーブル１４２のうち、静的な部分のデータは、あらかじめプログラマにより記述されている。すなわち、プログラマが記述した静的な部分の記述がコンパイルにより機械語に変換されるとともに、後のリンク時にリンカがデータセクション１４０の外部参照テーブル１４２を構成できるように、再配置情報（例えばリロケーションテーブル）が生成される。オブジェクトファイル１００が使用されて、外部プログラムの中にリンクされることにより生成された実行可能ファイルがファイルシステムに保存されている段階では、オブジェクトファイル１００のデータセクション１４０内の外部参照テーブル１４２には、静的な外部参照情報、すなわちアドレスが静的に定まっている外部オブジェクトについてのアドレス情報のみが含まれている。そして、実行時にならないとアドレスが決まらない外部オブジェクトのアドレス情報は、初期化関数１２２による初期化処理時に、外部参照テーブル作成コード１２６の実行により作成される。
【００３２】
復号コード１２４は、符号化されたコードをマイクロプロセッサが実行可能なコードに復号する処理を記述したプログラムコードである。
【００３３】
呼び出しコード１２８は、符号化プログラムコード１３２を復号して得られた原プログラムコードを呼び出す機能を記述したプログラムコードである。呼び出しコード１２８は、復号コード１２４が符号化プログラムコード１３２を復号した後かつ、外部参照テーブル作成コード１２６が外部参照テーブル１４２を完成させた後に、外部参照テーブル１４２のアドレス（例えば先頭アドレス）を、スタックないしレジスタを介して、原プログラムコードに渡し、その原プログラムコードを呼び出す機能を記述している。
【００３４】
復号結果の原プログラムコードは、呼び出しコード１２８からの呼び出しに応じて、渡された外部参照テーブル１４２を用いて外部オブジェクトを利用しながら、外部のプログラム（例えば、後述するリンク元プログラム）に提供する所定の処理を行う機能を持つ。すなわち、原プログラムコードでは、外部オブジェクトの呼び出しの記述は、当該オブジェクトの名前で直接指し示す代わりに、外部参照テーブル１４２における当該オブジェクトのエントリを指し示す形で記述される。
【００３５】
以下に、オブジェクトファイル１００の元になるライブラリのソースコードの具体例を示す。なお、これは外部オブジェクト参照についての本実施の形態の特徴を示す目的の例であり、原プログラムコードの処理内容については特段の意味はない。
【００３６】
// Microsoft社のVisual Studio（登録商標）によりコンパイルされる例
#include <windows.h>
// 独自セクションの作成
#pragma section(".mysect", write, execute )
bool g_isInitialized = false;
char BaseData[1024];
// 外部参照テーブル
struct ExternalObjectReferenceTable {
HANDLE hHeap;
char* pData;
DWORD (WINAPI * pGetLastError)(VOID);
LPVOID (WINAPI * pHeapAlloc)(HANDLE, DWORD, SIZE_T);
BOOL (WINAPI * pHeapFree)(HANDLE, DWORD, LPVOID);
} g_table = { NULL, BaseData, NULL, NULL, NULL };
// 静的に外部参照テーブルを作成する場合には、ここで行う
extern bool DoDecrypt(unsigned char*, BYTE*, BYTE*);
// 初期化関数
int initialize(void)
{
if (g_isInitialized) return 0;
// 復号コード
static unsigned char key[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
BYTE* pFuncTop = reinterpret_cast<BYTE*>(topFunc);
BYTE* pFuncTail= reinterpret_cast<BYTE*>(tailFunc);
if (DoDecrypt(key, pFuncTop, pFuncTail)) return -6;
// 外部参照テーブル作成コード
g_table.hHeap = GetProcessHeap();
if (g_table.hHeap == NULL) return -1;
HINSTANCE hKERNEL32 = LoadLibrary("kernel32.dll");
if (hKERNEL32 == NULL) return -2;
// kernel32.dll
g_table.pGetLastError = (DWORD (WINAPI * )(VOID))
GetProcAddress(hKERNEL32, "GetLastError");
if (g_table.pGetLastError == NULL) return -3;
g_table.pHeapAlloc = (LPVOID (WINAPI *)(HANDLE, DWORD, SIZE_T))
GetProcAddress(hKERNEL32, "HeapAlloc");
if (g_table.pHeapAlloc == NULL) return -4;
g_table.pHeapFree = (BOOL (WINAPI *)(HANDLE, DWORD, LPVOID))
GetProcAddress(hKERNEL32, "HeapFree");
if (g_table.pHeapFree == NULL) return -5;
g_isInitialized = true;
return 0;
}
// 呼び出しコード
int callTopFunc ( unsigned char* x, unsigned int y) {
if (false == g_isInitialized)  return -1;
return topFunc(x, y, &g_table);
}
#pragma code_seg(".mysect")
// 原プログラムコード開始
int topFunc(unsigned char* x, unsigned int y,
// 引数(スタックまたはレジスタ経由)で外部参照テーブルのアドレスを渡す例
struct ExternalObjectReferenceTable& pTable) {
// 原プログラムコード内から外部オブジェクトを参照する例
unsigned char* pBuffer = (unsigned char*)(*pTable->pHeapAlloc)(pTable->hHeap, 0, y);
// 機能の提供
// 原プログラムコード内から外部オブジェクトを参照する例
if (pBuffer != NULL) (*pTable->pHeapFree)(pTable->hHeap, 0, pBuffer);
return 0;
}
int tailFunc(int a){ return a; }
// 符号化対象コード終了
#pragma code_seg()
【００３７】
以上の例は、Microsoft社のVisual Studio（登録商標）のC/C++コンパイラによりコンパイルされることを想定したソースコードである。また、この例は、符号化（暗号化）する関数を指定した指定情報が、オブジェクトコードとは別に生成される関数リストである場合の例である。
【００３８】
上記コード例には、まず独自セクション１３０を作成するためのコードが記述されている。Microsoft社のVisual StudioのC/C++コンパイラであれば、[#pragma section(“名前”, アトリビュート)]という記述で当該セクションを作成することができる。上述の例では、”.mysect”という名前の独自セクションを作成し、このセクションを書き込み可能かつ実行可能なセクションとして設定している。そして、ソースコード中で、関数定義された関数を[#pragma code_seg(“名前”)]と[#pragma code_seg()]とで挟むことで、その関数を作成した独自セクションに置くことができる（上述のコード例の末尾の原プログラムコードの記述を参照）。また、GNUのGCCコンパイラを用いてコンパイルする場合は、関数の定義に[__attribute__ ((section (“名前”)))]のアトリビュートを付加することで、その関数を設置するセクションを指定できる。
【００３９】
上述のコード例では、独自セクションの作成を指示するコードの次に外部参照テーブル１４２（”g_table”）が定義されている。
【００４０】
外部参照テーブル１４２の定義の後に、外部参照テーブル１４２の静的な部分を記述してもよい。すなわち、外部参照テーブル１４２のうちラベル名などにより静的に生成可能なデータは、ラベル名を用いてテーブルのエントリを生成し、リンカがそのラベル名に対応するアドレスを解決するようにする。
【００４１】
また、外部参照テーブル１４２についての記述の後に、初期化関数１２２のコードが記述される。この初期化関数１２２のコード中には、まず復号コード１２４が記述され、その次に外部参照テーブル作成コード１２６が記述されている。
【００４２】
上述の例の復号コード１２４では、復号に用いる情報のうち復号対象とするセクション（すなわち独自セクション１３０、とくに原プログラムコード）の範囲を示す情報として、当該セクションの先頭アドレスと終了アドレスと、を取得している。ただし、これは一例に過ぎない。この代わりに、先頭アドレスとセクションのサイズとを取得してもよい。また、別の例としてセクションの先頭と末尾にラベルを付与し、これらラベルからセクションの範囲を取得してもよい。また、セクションの先頭と末尾とに、定義した関数（上述のコード例におけるtopFuncとtailFunc）を用いることで、復号コード１２４がセクションの範囲を取得するようにしてもよい。また、復号コード１２４が行う処理が暗文復号であれば復号鍵が必要となるが、復号鍵としてはあらかじめ定めておいた値を用いるようにしてもよい。
【００４３】
また、初期化関数のうちの外部参照テーブル作成コード１２６は、原プログラムコードが参照する外部オブジェクトのうち実行時にアドレスを解決するべきオブジェクトについて、動的に実行時にアドレスを取得し、取得したアドレスを外部参照テーブル１４２に設定する処理を記述している。例えば、Windows（登録商標）オペレーティングシステムにおいては、GetProcAddressというAPI関数により、外部関数のアドレスが取得できる。例えば、上記コード例では、当該ライブラリ（オブジェクトファイル１００）を呼び出すリンク元プログラムのプロセスヒープのアドレスを取得して外部参照テーブルに登録している（g_table.hHeap = GetProcessHeap()）。このプロセスヒープは、原プログラムコードにおいて参照される。また、上述のコード例では、原プログラムコードは、例えば、”kernel32.dll”というライブラリファイルに含まれる関数HeapAllocなどを外部オブジェクトとして参照するが、それら外部オブジェクトのメモリ上でのアドレスをGetProcAddress関数により取得し、取得したアドレスを外部参照テーブルg_tableのメンバ（例えばpHeapAlloc）に代入している。
【００４４】
なお、原プログラムコードが用いるデータによっては、当該データを含んだ外部オブジェクトのアドレスでなく当該オブジェクト中の当該データを直接、外部参照テーブルに設定してもよい。
【００４５】
初期化関数１２２の記述の後には、復号結果の原プログラムコードを呼び出すための呼び出しコード１２８が記述される。呼び出しコード１２８は、上述の例では、外部参照テーブルの初期化（作成）が完了していれば(フラグg_isInitializedがtrue）、原プログラムコード中の関数topFuncを呼び出す記述となっている。ここで、関数topFuncは外部参照テーブル構造体のポインタを引数の１つとしており、呼び出しコード１２８では、その引数に対し、外部参照テーブル作成コードにより完成したテーブルg_tableのアドレスをセットしている。これにより、呼び出された原プログラムコードの関数topFuncが、外部参照テーブルを参照可能となる。
【００４６】
また、上述のコード例では、呼び出しコード１２８の後に記述された原プログラムコード中の関数topFuncは、引数として外部参照テーブルのアドレス（p_table）を受け取る。また、この関数は、外部オブジェクト（例えば関数HeapAlloc）をその名前で参照するのではなく、外部参照テーブル中の当該オブジェクトに対応するメンバが示すアドレス(p_table->pHeapAlloc）を介してそのオブジェクトを参照する。また、その関数は、呼び出し側の外部関数のプロセスヒープを、外部参照テーブルのメンバpTable->pHeapを介して参照している。
【００４７】
上述のコード例では、原プログラムコード中には機能を提供する関数が１つしかなかったが、原プログラムコード中にそのような関数が複数含まれていてもよい。また、この場合、それら関数を個別に呼び出せるように、関数毎に当該関数を呼び出す呼び出しコード１２８を用意するようにしてもよい。
【００４８】
このようなライブラリのソースコードは、例えば次の流れで作成すればよい。すなわち、まず、原プログラムコードを、上述のコード例のように、外部オブジェクトへのアクセスが外部参照テーブルを介して行われる形で記述する。また、原プログラムコードの関数を、独自セクションに置くようにコンパイラに指定するためのコードを記述する。また、独自セクションを復号するための復号コードを実装する。また、外部参照テーブルを定義し、そのうちラベル名などにより静的に生成可能なデータについてはラベル名を用いてテーブルの内容を記述する。また、実行時にアドレスを解決するべき外部オブジェクトについての情報を外部参照テーブルに登録する処理を記述した外部参照テーブル生成コードを実装する。また、外部参照テーブルを引数として原プログラムコード中の関数を呼び出す呼び出しコードを記述する。
【００４９】
次に図３を参照して、この実施の形態のオブジェクトファイル１００がライブラリとして作成され、配布されて利用される場合の流れの例を説明する。
【００５０】
この流れでは、まずライブラリ開発者が、自分のコンピュータ２００にて、以上のようにしてライブラリのソースコード１５０を作成した後、次にそのソースコード１５０をコンパイラにコンパイルさせる。これによりライブラリのオブジェクトファイル１００Ａが生成される。このオブジェクトファイル１００Ａの独自セクション１３０内は、この時点では符号化されていない。次に、オブジェクトファイル１００Ａのうちの独自セクション１３０を符号化プログラムにより符号化する。これにより、符号化プログラムコード１３２を含んだ配布版のオブジェクトファイル１００Ｂが完成する。完成したオブジェクトファイル１００Ｂが、ライブラリを利用する利用者側に配布される。
【００５１】
なお、以上の処理の流れにおいて、独自セクション１３０の符号化前に、独自セクション１３０中に外部オブジェクトを直接参照するコードがないか確認し、存在する場合には、コードを修正するように警告する処理を行うようにしてもよい。外部オブジェクトを直接参照するコードがあるかは、例えば、独自セクション１３０についてのリロケーションテーブルの存在の有無および、エントリ数が１以上であるかによって判定すればよい。すなわち、コンパイラはソースコードをコンパイルする際に、後のリンク又はロードなどの処理のためのリロケーションテーブルを作成するが、独自セクション１３０についてこのリロケーションテーブルが作成されており、且つこのテーブルの中に１以上のエントリがあれば、独自セクション１３０中に外部オブジェクトを直接参照するコードがあると判定する。そして、独自セクション１３０中に外部オブジェクトを直接参照するコードがあると判定した場合には、リロケーションテーブルより参照しているオブジェクトのラベル名、及び、対象コードの位置(デバッグ情報が含まれる場合には、ソースコード上の場所まで)を判別し、判別した情報を警告と共に表示するようにしてもよい。
【００５２】
配布版のライブラリ（オブジェクトファイル１００Ｂ）の提供を受けた利用者のコンピュータ２１０では、以下のような作業が行われる。
【００５３】
すなわち、まずライブラリ利用者は、そのライブラリを利用するリンク元コードをプログラミングする。リンク元コードは、被提供者側がマイクロプロセッサに実行させたい機能を記述するプログラムコードである。リンク元コードは、そのライブラリが提供する機能（複数あってもよい）を呼び出す記述を含む。ここで、リンク元コードは、ライブラリが提供する機能の呼び出しのすべてに先んじて、そのライブラリの初期化関数１２２を呼び出すようにプログラミングしておく。ここまでが、被提供者による一般のコーディング作業である。
【００５４】
利用者は、作成したリンク元コードをコンパイルしてオブジェクトコード形式のリンク元コード１５５を生成する。そして、このリンク元コード１５５をライブラリのオブジェクトファイル１００Ｂとリンカにリンクさせる。これにより、実行可能ファイル１６０が生成される。この実行可能ファイル１６０が、利用者のコンピュータ２１０のメモリにロードされ、実行される（１７０）。なお、このリンクは、静的リンクでも動的リンクでもよい。
【００５５】
次に、図４及び図５を参照して、外部参照テーブル１４２の内容変遷の例を説明する。この例では、まず図４に示すように、ソースコード中では外部参照テーブルはコード例１０のように記述されているとする。すなわち、このコード例１０では、メンバとしてpData、pfunc、pfunc2等を有する外部参照テーブルg_tableが定義され、そのテーブルの第２のメンバが関数funcとして静的に記述されている。また、そのコード例１０は、外部参照テーブル作成コード１２６の例として、外部参照テーブルg_tableのメンバpFunc2に対し、関数func2（のアドレス）を代入するという命令を含んでいる。
【００５６】
このようなコード例１０を含むソースコードをコンパイルすると、コード例２０のようなオブジェクトコードを含んだオブジェクトファイルが得られる。この例では、ソースコード中の前述の外部参照テーブル作成コードは、オブジェクトファイル中ではコードセクション内のオフセット１３００の位置にある「０番地の８バイト目（これは外部参照テーブル中のpfuncのエントリのアドレス）に、０と記入せよ」という命令（図では便宜上文章で説明したが、実際には当然ながら機械語命令である）へと変換されている。なお、その命令の２つの「０」の箇所には、後で適切なアドレス値がセットされる。また、データセクションのオフセット４１００以降には、外部参照テーブルの各エントリが確保されている。ここでオフセット４１０４の位置には、後のリンク処理の際に関数funcのアドレスがセットされるが、この時点では場所の確保がなされるのみであり、値は０となっている。また、コード例２０中のリロケーションセクションには、再配置情報であるリロケーションテーブルの内容が記入されている。リロケーションテーブルの内容は、例えば、コードのどの部分にどのシンボルのアドレスを入れるかを規定している。また、コード中のシンボルセクションには、コード中に現れるg_table等の各シンボルの情報が含まれる。シンボルの情報は、例えば名前、内容（データか、関数名かなど）、及び定義場所（このオブジェクトファイルの中か外か）を含んでいる。
【００５７】
このようなコード例２０を含んだオブジェクトファイルが、外部プログラム（リンク元コード）とリンクされると、図５に例示するコード例３０を含んだ実行可能ファイルが生成される。このコード例３０では、外部プログラムとのリンクにより、オフセット値がオブジェクトファイルの時点から変化している。リンクにより、各オブジェクトのアドレス（この時点ではファイル上にあるのでオフセット値）が決まる。例えば、外部参照テーブルg_table、関数func及びfunc2のアドレスが６１００、４８００及び４９４０と決まるので、それらアドレスがコード中の対応する位置にセットされる。
【００５８】
例えば、関数funcのアドレスは、オフセット６１００以降に位置するg_table中の当該関数funcの位置にセットされる。これは、外部参照テーブル１４２のうちの静的な部分の例である。すなわち、リンクの際、リンカは、オブジェクトファイルのシンボルセクションとリロケーションセクションを参照して、関数funcに対応するシンボルＣがオフセット４１０４に位置することを知ると共に、そのオフセット４１０４がリンクによりオフセット６１０４に移動したことを知り、これらに基づきオフセット６１０４に関数funcのアドレス４８００をセットする。
【００５９】
また、関数func2のアドレス４８００は、リンクによりオフセット３３００に位置することとなった外部参照テーブル作成コード中にセットされる。この例では、外部参照テーブル作成コードの内容は、外部参照テーブルg_tableの先頭アドレス６１００からみて８バイト目に、関数func2のアドレス４９４０をセットせよと言う命令となる。これは、外部参照テーブルのエントリのアドレスが、外部参照テーブル作成コードの実行により動的にセットされる例である。
【００６０】
なお、データセクション中の外部参照テーブルにあるpData及びfunc2は、まだアドレスがセットされておらず、０のままである。
【００６１】
このような実行可能ファイルがメインメモリにロードされ起動されると、外部参照テーブル作成コードの内の一部が実行される。ここでは、実行可能ファイルがメインメモリの０番地にロードされたとする。この場合、コード例４０に示すように、データセクション中の外部参照テーブルは、オフセットと同じ値の番地（アドレス）に書き込まれることになる。この例では、コードセクションもデータセクションもロードにより内容は変化しない。
【００６２】
そして、外部参照テーブル作成コードが実行されると、例えば３３００番地のコードの実行により、６１０８番地に値４９４０がセットされることとなる。これにより、外部参照テーブルが完成する。
【００６３】
なお、図４及び図５の例では、リンクの時点で判明するfunc2のアドレスを外部参照テーブル作成コードにより、メモリ上の外部参照テーブル中での当該関数のアドレスにセットしたが、これは説明のための便宜的な例に過ぎない。外部参照テーブル作成コードは、典型的には、実行時に動的にアドレスが決定されるようなオブジェクトに対して利用すればよい。
【００６４】
このようにしてメインメモリ上に構成された外部参照テーブルのアドレス（典型的には先頭アドレス）は、復号後の原プログラムコードを実行するマイクロプロセッサ３００に対し、呼び出しコード１２８の実行により引数として（例えばスタックやレジスタを介して）渡される。マイクロプロセッサ３００は、その引数の値を用いて、原プログラムコード中の外部オブジェクトへの参照を、メインメモリ上の外部参照テーブル中での当該オブジェクトのエントリのアドレスへと変換する。そして、そのアドレスにアクセスすることで、その外部オブジェクトの実行時アドレスを知り、その外部オブジェクトへとアクセスする。
【００６５】
開発者及び利用者が用いるコンピュータ２００及び２１０は、図６に例示するような一般的なハードウエア構成を持つものでよい。すなわち、図６に例示するコンピュータは、例えば、ＣＰＵ等のマイクロプロセッサ３００、ランダムアクセスメモリ（ＲＡＭ）３０２およびリードオンリメモリ（ＲＯＭ）３０４等のメモリ（一次記憶）、ＨＤＤ（ハードディスクドライブ）コントローラ３０８を経由して接続されたＨＤＤ３０６、各種Ｉ／Ｏ（入出力）インタフェース３１０等が、たとえばバス３１４を介して接続された回路構成を有する。バス３１４には、ローカルエリアネットワーク等のネットワークに接続するためのネットワークインタフェース３１２が接続されていてもよい。また、そのバス３１４に対し、例えばＩ／Ｏインタフェース３１０経由で、ＣＤやＤＶＤなどの可搬型ディスク記録媒体に対する読み取り及び／又は書き込みのためのディスクドライブ３１６、フラッシュメモリなどの各種規格の可搬型の不揮発性記録媒体に対する読み取り及び／又は書き込みのためのメモリリーダライタ３１８などが接続されてもよい。ＲＡＭ３０２は、コンピュータ２００又は２１０のメインメモリとして使用される。
【００６６】
マイクロプロセッサ３００が、ロードされた実行可能ファイル１６０を実行する処理手順を、図７及び図８を参照して説明する。
【００６７】
利用者によりリンク元コードが起動されると、コンピュータ２１０のメモリ４００（図３のＲＡＭ３０２に対応）に実行可能ファイル１６０がロードされる。図８には、メモリ４００にロードされた実行可能イメージのうちライブラリに由来する部分を示している。そして、その実行可能イメージのうちのリンク元コードがマイクロプロセッサ３００により実行される。ここで、リンク元コード中にはライブラリの初期化関数１２２を呼び出すコードが含まれている。マイクロプロセッサ３００がこのコードを実行すると（Ｓ１０）、初期化関数１２２が呼び出される。すると、マイクロプロセッサ３００により復号コード１２４及び外部参照テーブル作成コード１２６が実行される。これにより、コンピュータ２１０は、復号部４１０及び外部参照テーブル作成部４２０として機能する。
【００６８】
復号部４１０は、独自セクション１３０の符号化プログラムコード１３２を復号する（Ｓ１２）。ここで、独自セクション１３０は書き込み可能及び実行可能なセクションなので、復号部４１０はそのセクション１３０内のコード１３２の復号結果（すなわち原プログラムコード）をそのセクション１３０内に書き戻すことができる。
【００６９】
また、外部参照テーブル作成部４２０は、動的にアドレスを解決する必要のある各外部オブジェクトのアドレスを（例えばＡＰＩ関数を用いてオペレーティングシステムから）取得し、外部参照テーブル１４２に登録する。これにより、外部参照テーブル１４２が完成する（Ｓ１４）。
【００７０】
初期化関数１２２の実行が完了すると、リンク元コード側に制御が戻る。マイクロプロセッサ３００は、リンク元コードの末尾に達するまで（Ｓ１６）、リンク元コード内の命令を順番に実行する。この処理の中で、マイクロプロセッサ３００で実行されるコードが呼び出しコード１２８に達すると（Ｓ１８）、マイクロプロセッサ３００は呼び出しコード１２８を実行する（Ｓ２０）。これにより、コンピュータ２１０は呼び出し部４３０として機能する。呼び出し部４３０は、独自セクション１３０内の原プログラムコード中の、当該呼び出しコード１２８に対応する関数を呼び出す。この呼び出しの際、外部参照テーブル１４２のアドレスが引数として原プログラムコード側に渡される。
【００７１】
この呼び出しに応じて、マイクロプロセッサ３００は、原プログラムコード内の呼び出された関数を実行する（Ｓ２２）。この実行により、コンピュータ２１０は、その関数が表す機能を提供する機能実行部４４０として機能する。機能実行部４４０は、呼び出された関数中で参照される外部オブジェクトにアクセスする際に、外部参照テーブル１４２を介してアクセスする。すなわち、引数として渡された外部参照テーブル１４２のアドレス（先頭アドレス）をもとに、その外部参照テーブル１４２内での当該外部オブジェクトのエントリのアドレスにアクセスし、アクセスしたアドレスにある値（すなわち当該外部オブジェクトの実行時アドレス）を用いて当該外部オブジェクトにアクセスする。
【００７２】
呼び出された関数の実行が完了すると、処理がリンク元コード側に戻される。そして、リンク元コードの末尾に達するまで（Ｓ１６）、Ｓ１８〜Ｓ２２の処理が繰り返される。
【００７３】
以上、この実施の形態のオブジェクトファイル１００の構成とその利用について説明した。以上の説明から理解されるように、この実施の形態の原プログラムコードには、外部オブジェクトを直接参照する記述は含まれない。この代わりに、原プログラムコード中では、外部オブジェクトへの参照は、呼び出しコード１２８から引数（上述のコード例ではp_table）として渡される外部参照テーブル１４２中のエントリを用いる間接参照の形で記述される。引数は、コンパイルの結果生成されるシンボルテーブルにも再配置情報（これらはオブジェクトファイル１００内に含まれ、リンクやロードの際に参照される）にも登録されないので、上述のコード例でも、独自セクション１３０の原プログラムコード内のp_table->pHeapAllocやp_table->pHeapなどといった引数p_tableを介した参照はシンボルテーブルや再配置情報に登録されない。したがって、オブジェクトファイル１００がリンク元コードとリンクされる際のアドレス解決処理において、独自セクション１３０内のシンボル又はアドレスが書き換えられることがない。リンクの時点では、独自セクション１３０内のコードは符号化されているため（符号化プログラムコード１３２）、アドレス解決のためにそのコードの一部が書き換えられると復号ができなくなるが、この実施の形態では独自セクション１３０はアドレス解決時に書き換えられないので、そのような不具合は生じない。すなわち、この実施の形態のオブジェクトファイル１００の構成を用いれば、通常のコンパイラ及びリンカを用いた場合でも、符号化プログラムコード１３２がリンク時に破壊されることが防がれる。
【００７４】
なお、独自セクション１３０がリンク時のアドレス解決の際に書き換えられることが防止されるという点は、外部参照テーブル１４２のエントリが静的に記述されたもの（すなわち静的にアドレスが決まっている外部オブジェクトについてのもの）のみである場合にも成り立つ。
【００７５】
＜変形例１＞
上述の実施の形態では、復号コード１２４と外部参照テーブル作成コード１２６とを含む初期化関数１２２を、リンク元コードから明示的に呼び出す構成を説明したが、これは一例に過ぎない。リンク元コードから初期化関数１２２を明示的に呼び出す代わりに、リンク元コードから呼び出しコード１２８が最初に呼び出された際に、初期化関数１２２を実行するようにしてもよい。このために、ライブラリの初期化が既に実行されたか未実行であるかを示すフラグを例えばデータセクション１４０などに用意しておき、呼び出しコード１２８が呼ばれる毎にそのフラグを確認して、最初の呼び出しであれば、初期化関数１２２を呼び出す構成にすればよい。フラグが既実行を示す場合には、初期化関数１２２を呼び出さない。この例では、リンク元コードがライブラリの初期化関数１２２を呼ぶ手間が省かれる。
【００７６】
＜変形例２＞
上述の実施の形態では、原プログラムコードから外部オブジェクトへの参照のために外部参照テーブルを用いたが、外部参照のためのデータがテーブルである必要はなく、外部参照に必要な情報が原プログラムコードに渡すことができるものであればどのような方法を用いてもよい。例えば、個々の外部オブジェクト毎に当該オブジェクトのメモリ４００上でのアドレスを示す外部参照情報をデータセクション１４０上に記述又は生成し、外部オブジェクトを参照する関数に対し、そのオブジェクトに対応する外部参照情報のアドレスを引数として渡すようにしてもよい。すなわち、複数の外部オブジェクトのアドレス情報をテーブルの形で一括して原プログラムコードに渡すのではなく、個々の外部オブジェクトのアドレス情報を個別に原プログラムコード中の関数に渡してもよい。特に、原プログラムコードが複数のインタフェースを持つ場合には、すべてのインタフェースに同一の情報（外部参照テーブル）を渡すのではなく、インタフェース毎に、それぞれ必要な外部参照情報を渡すという方法も取れる。
【００７７】
＜変形例３＞
上述の実施の形態では、符号化プログラムコード１３２の復号結果である原プログラムコードを、独自セクション１３０に格納する例を説明したが、これは一例に過ぎない。実施の形態の手法は、原プログラムコードは外部参照テーブルを介して外部オブジェクトにアクセスするため、原プログラムコードがメモリ４００のメモリ空間のどこに置かれても正しく動作する。したがって、変形例として、復号コード１２４の実行により実現された復号部４１０が、必要な大きさの、書き込み、読み出し及び実行のすべてが可能なメモリ領域をメモリ４００のメモリ空間内に確保し、そのメモリ領域上に復号結果の原プログラムコードを置く構成としてもよい。この場合には、呼び出しコード１２８が、確保されたメモリ領域上の原プログラムコードを呼び出せるように、アドレス解決を行う必要がある。この場合には、復号部４１０は、原プログラムコードを置いたメモリ領域のアドレスを知っているので、呼び出しコード１２８に、関数ポインタを用いるなどの方法で、そのアドレスを原プログラムコード中の関数に渡すことで、そのアドレス解決を実現すればよい。
【００７８】
＜変形例４＞
上述の実施の形態では、原プログラムコードを一括して符号化する構成を説明したが、原プログラムコードが複数の機能を提供する場合、機能毎に分割して符号化するようにしてもよい。個々の機能は、それぞれ１つ又は複数の関数により提供される。この場合には、機能を提供するコード毎に当該コードがオブジェクトファイル中のどこに置かれたかの情報を、符号化プログラムと復号コード１２４（復号部４１０）が把握する必要がある。この情報は、ライブラリのラベル名を用いれば取得することができる。例えば、原プログラムコード中において複数の対象関数をひとかたまりとして符号化する場合を考える（原プログラムコード中には、そのようなかたまりが１以上存在する）。この場合、ひとかたまりとして符号化する対象関数群のうち最初に置かれた関数の関数名をシンボルとするコード位置から、その符号化する対象関数群の直後に置かれた関数名をシンボルとするコード位置の直前までが、ひとかたまりの符号化対象のコード（すなわち原プログラムコード）であると判断される。また、符号化したい対象となる関数が一つの場合（すなわち符号化の単位が１関数）は、その関数の先頭から次の関数の先頭の直前までが、一単位の符号化対象のコードと認識される。また関数の終了位置がシンボルとして定義されるようなコンパイラを用いる場合の別の方法としては、符号化する対象関数(群)で最初に置かれた関数名をシンボルとするコード位置を開始位置として、符号化する対象関数(群)の最後の関数の終了シンボルのコード位置までを、符号化対象のコードであると判断する方法である。関数の置かれる順番は、ソースコード上の定義の順番であることが一般的である。また、関数を置く順番を外から指定できるコンパイラも存在する。これにより符号化対象の関数を置く順番を制御することができる。別の方法では、一般のリンカではその出力情報の一つとして、生成した実行ファイルのどの位置にどのシンボルの関数を置いたかを示す情報（マップ情報と呼ばれる）を出力させることができる。このマップ情報を参照することで、符号化対象のコードがファイル内のどの位置に置かれたかを知ることができる。このように機能単位で符号化すれば、実行時に必要なコードだけ復号するといった使い方が可能となる。
【００７９】
＜変形例５＞
上述の実施の形態では、一度復号した原プログラムコードは実行されるだけであるが、実行された後に再び符号化する構成としてもよい。符号化の目的が暗号化の様に情報の秘匿である場合には、このように再符号化すれば、原プログラムコードがメモリ上に存在する時間を減らすことで、より強固に情報を秘匿することが期待できる。これには、例えば呼び出しコード１２８を呼び出す直前に復号コード１２６を実行し、呼び出しコード１２８の実行終了後に符号化のためのコードを実行して符号化結果を独自セクション１３０に上書きするようにプログラミングすればよい。
【００８０】
特に、変形例４と組み合せることが考えられる。この場合、個々の機能毎に、当該機能が実行される前に復号し、機能の実行後に再び符号化し、符号化結果を原プログラムコードに上書きすればよい。
【符号の説明】
【００８１】
１００  オブジェクトファイル、１１０  オブジェクトヘッダ、１２０  コードセクション、１２２  初期化関数、１２４  復号コード、１２６  外部参照テーブル作成コード、１２８  呼び出しコード、１３０  独自セクション、１３２  符号化プログラムコード、１４０  データセクション、１４２  外部参照テーブル。
【図１】
2010231477.tif 000003
【図２】
2010231477.tif 000004
【図３】
2010231477.tif 000005
【図４】
2010231477.tif 000006
【図５】
2010231477.tif 000007
【図６】
2010231477.tif 000008
【図７】
2010231477.tif 000009
【図８】
2010231477.tif 000010