"コンピュータを、所定の関数の呼び出しを検出する呼び出し検出部と、前記関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得するリターンアドレス取得部と、前記検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、前記リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部に記憶する属性変更検出部と、前記リターンアドレスが前記アドレス範囲記憶部に記憶されている前記アドレス範囲内である場合に、不正アクセスが行われていると判定する不正アクセス検出部と、して機能させるためのプログラム。請求項1に記載のプログラムであって、前記リターンアドレス取得部は、前記関数の検出が行われた際に、前記スタック領域に格納されている複数のリターンアドレスを順次取得し、前記属性変更検出部は、前記順次取得されるリターンアドレスのそれぞれについて、前記検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、前記リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲を前記アドレス範囲記憶部に記憶し、前記不正アクセス検出部は、前記順次取得されるリターンアドレスのそれぞれについて、前記リターンアドレスが前記アドレス範囲記憶部に記憶されている前記アドレス範囲内である場合に、不正アクセスが行われていると判定する、プログラム。所定の関数の呼び出しを検出する呼び出し検出部と、前記関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得するリターンアドレス取得部と、前記検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、前記リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部に記憶する属性変更検出部と、前記リターンアドレスが前記アドレス範囲記憶部に記憶されている前記アドレス範囲内である場合に、不正アクセスが行われていると判定する不正アクセス検出部と、を備える情報機器。コンピュータが、所定の関数の呼び出しを検出し、前記関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得し、前記検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、前記リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部に記憶し、前記リターンアドレスが前記アドレス範囲記憶部に記憶されている前記アドレス範囲内である場合に、不正アクセスが行われていると判定する、不正アクセス検出法方法。しかしながら、例えば、正常なプログラムの中には、メモリ上のデータ領域に別のプログラムコードを展開したうえで、当該データ領域に実行属性を付与し、当該プログラムコードを実行するものがある。この場合、当該データ領域には実行属性とともに書き込み属性も付与されているため、特許文献1に開示されている手法を適用すると、不正アクセスであると誤って検出されることとなる。また、正常なプログラムの中には、call命令を用いずに関数呼び出しを行うものもある。そのため、このようなプログラムに特許文献2に開示されている手法を適用すると、不正アクセスであると誤って検出されることとなる。そこで、本発明は、不正アクセスの検出精度を高めることを目的とする。本発明の一側面に係るプログラムは、コンピュータを、所定の関数の呼び出しを検出する呼び出し検出部と、関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得するリターンアドレス取得部と、検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部に記憶する属性変更検出部と、検出された関数のリターンアドレスがアドレス範囲記憶部に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定する不正アクセス検出部と、して機能させるためのものである。さらに、リターンアドレス取得部は、関数の検出が行われた際に、スタック領域に格納されている複数のリターンアドレスを順次取得し、属性変更検出部は、順次取得されるリターンアドレスのそれぞれについて、検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数であり、リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部に記憶し、不正アクセス検出部は、順次取得されるリターンアドレスのそれぞれについて、リターンアドレスがアドレス範囲記憶部に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定することとしてもよい。また、本発明の一側面に係る情報機器は、所定の関数の呼び出しを検出する呼び出し検出部と、関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得するリターンアドレス取得部と、検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数である場合に、当該アドレス範囲をアドレス範囲記憶部に記憶する属性変更検出部と、検出された関数のリターンアドレスがアドレス範囲記憶部に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定する不正アクセス検出部と、を備える。また、本発明の一側面に係る不正アクセス検出方法では、コンピュータが、所定の関数の呼び出しを検出し、関数の検出が行われた際に、スタック領域に格納されているリターンアドレスを取得し、検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数である場合に、当該アドレス範囲をアドレス範囲記憶部に記憶し、検出された関数のリターンアドレスがアドレス範囲記憶部に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定する。なお、本発明において、部とは、単に物理的手段を意味するものではなく、その部が有する機能をソフトウェアによって実現する場合も含む。また、1つの部や装置が有する機能が2つ以上の物理的手段や装置により実現されても、2つ以上の部や装置の機能が1つの物理的手段や装置により実現されてもよい。本発明によれば、不正アクセスの検出精度を高めることができる。以下、図面を参照して本発明の一実施形態について説明する。==構成==まず、本発明の一実施形態である情報機器の構成について説明する。図1は、本発明の一実施形態である情報機器のハードウェア構成の一例を示す図である。図1に示すように、情報機器10は、プロセッサ20、メモリ22、記憶装置24、入力インタフェースI/F26、データインタフェースI/F28、通信インタフェースI/F30、及び表示装置32を含んで構成されている。情報機器10は、例えば、パーソナルコンピュータや携帯情報端末等の情報処理装置である。プロセッサ20は、メモリ22に記憶されているプログラムを実行することにより情報機器10における様々な処理の実行を制御する。なお、図1には示していないが、プロセッサ20は、命令やアドレスを記憶するための各種レジスタを備えている。本実施形態では、プロセッサ20の構成は、インテル登録商標社が開発した32ビットマイクロプロセッサのアーキテクチャであるIA-32を前提として説明する。なお、プロセッサ20の構成はこれに限られず、任意の構成を採用することができる。メモリ22は、例えばRAMRandomAccessMemory等の記憶領域であり、プロセッサ20によって実行されるプログラムのプログラムコードや、プログラムの実行時に必要となるデータを一時的に記憶する。例えば、メモリ22の記憶領域には、プログラムの実行時に必要となるスタック領域が確保される。記憶装置24は、例えばハードディスクやフラッシュメモリ等の記憶領域であり、オペレーティングシステムをはじめとした各種プログラムや、各種データ等が記憶される。記憶装置24に記憶されているプログラムやデータは、必要に応じてメモリ22にロードされ、プロセッサ20により参照される。入力I/F26は、ユーザからの入力を受け付けるためのデバイスであり、例えば、キーボードやマウス、タッチパネル、各種センサ等である。入力I/F26は、例えば、USBUniversalSerialBus等のインタフェースを介して情報機器10の外部に設けられていてもよい。データI/F28は、情報機器10の外部からデータを入力するためのデバイスであり、例えば、各種記憶媒体に記憶されているデータを読み取るためのドライブ装置等である。データI/F28は、USB等のインタフェースを介して情報機器10の外部に設けられていてもよい。通信I/F30は、情報機器10の外部の装置との間でデータ通信を行うためのデバイスであり、例えば、有線または無線によりデータ通信を行うことができる。通信I/F30は、USB等のインタフェースを介して情報機器10の外部に設けられていてもよい。表示装置32は、各種情報を表示するためのデバイスであり、例えば、液晶ディスプレイや有機ELElectro-Luminescenseディスプレイ等である。表示装置32は、ディスプレイケーブル等を介して情報機器10の外部に設けられていてもよい。図2は、情報機器10において実現される機能部の構成例を示す図である。図2に示される機能部は、例えば、メモリ22上の記憶領域を用いたり、メモリ22に記憶されているプログラムをプロセッサ20が実行したりすることにより実現することができる。図2に示すように、情報機器10は、呼び出し検出部40、リターンアドレス取得部42、属性変更検出部44、アドレス範囲記憶部46、及び不正アクセス検出部48を含んで構成することができる。呼び出し検出部40は、情報機器10において、所定のAPIApplicationProgramInterface関数の呼び出しを検出することができる。呼び出し検出部40による関数の呼び出し検出は、例えば、任意の手法によるフックを用いることにより行うことができる。本実施形態では、Windows登録商標におけるAPI関数である、VirtualProtectおよびWinExecをフックする場合を一例として説明する。なお、本実施形態では、検出する関数の一例としてVirtualProtectおよびWinExecを示すが、関数はこれに限られず、不正アクセスに用いられる可能性のある任意の関数を検出対象とすることができる。また、例えば、UNIX登録商標等の他の環境においても同様に、フックによりAPI関数の呼び出しを検出することができる。リターンアドレス取得部42は、呼び出し検出部40により所定のAPI関数の呼び出しが検出された際に、スタック領域に格納されているリターンアドレスを取得する。図3に、スタック領域の構造の一例を示す。図3に示すように、スタック領域には、関数ごとに、スタックフレームという領域が確保されている。そして、図3に示すように、スタック領域におけるポインタとして、スタックポインタesp:ExtendedStackPointerおよびベースポインタebp:ExtendedBasePointerが設けられている。スタックポインタは、スタックの一番上の場所を示すものであり、その値はスタックポインタレジスタに格納されている。また、ベースポインタは、実行中の関数のスタックフレームの底ベースの場所を示すものであり、その値はベースポインタレジスタに格納されている。そして、ベースポインタが指し示す場所には、呼び出し元の関数のスタックフレームにおけるベースのアドレスebpBackupが格納され、その下にはリターンアドレスが格納されている。したがって、リターンアドレス取得部42は、ベースのアドレスを辿ることにより、スタック領域に格納されている複数のリターンアドレスを順次取得することができる。このようにベースのアドレスを辿ることにより複数のリターンアドレスを順次取得する処理は、バックトレースと呼ばれる。ただし、アプリケーションの中にはこの規定に従わない関数が存在し、ebpBackupには不正な値が格納されている可能性がある。そのため、リターンアドレス取得部42は、ebpBackupに格納されたアドレスがスタック領域の範囲外であるか、それが格納されているアドレスよりも小さいアドレスであるときは不正な値であると判断し、バックトレースを終了する。属性変更検出部44は、呼び出し検出部40により検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数である場合に、当該アドレス範囲を、メモリ22上で確保された領域であるアドレス範囲記憶部46に記憶する。本実施形態では、属性変更検出部44は、呼び出し検出部40によってVirtualProtectの呼び出しが検出され、当該関数により、指定されたアドレス範囲の領域に実行属性が付与される場合には、当該アドレス範囲をアドレス範囲記憶部46に記憶する。VirtualProtectは、属性変更の対象領域の先頭のアドレス第1引数、対象領域のサイズ第2引数、変更後の属性第3引数、変更前の属性の保存先第4引数の4つの引数を取る。そのため、属性変更検出部44は、VirtualProtectの呼び出しが検出された際には、第3引数により、実行可能属性を付与するものであるかを判断し、第1引数及び第2引数により、属性変更のアドレス範囲を取得することができる。なお、アドレス範囲記憶部46に記憶されるアドレス範囲の情報の形式は任意である。例えば、アドレス範囲の開始アドレスと最終アドレスが記憶されることとしてもよいし、アドレス範囲の開始アドレスとアドレス範囲のサイズが記憶されることとしてもよい。また、属性変更検出部44は、リターンアドレス取得部42により取得されたリターンアドレスを考慮することができる。具体的には、属性変更検出部44は、VirtualProtectにより、指定されたアドレス範囲の領域に実行属性が付与される場合であって、取得されたリターンアドレスの指し示す先の1つ前の命令がcall命令呼び出し命令でない場合に、当該アドレス範囲をアドレス範囲記憶部46に記憶することができる。リターンアドレス取得部42により複数のリターンアドレスが順次取得される場合、属性変更検出部44は、各リターンアドレスについて当該判定を行うことができる。不正アクセス検出部48は、リターンアドレス取得部42により取得されたリターンアドレスが、アドレス範囲記憶部46に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定する。本実施形態では、不正アクセス検出部48は、例えば、呼び出し検出部40によってWinExecの呼び出しが検出され、リターンアドレス取得部42により取得されたリターンアドレスが、アドレス範囲記憶部46に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定する。リターンアドレス取得部42により複数のリターンアドレスが順次取得される場合、不正アクセス検出部48は、各リターンアドレスについて当該判定を行うことができる。==不正アクセスの検出処理==次に、情報機器10における不正アクセスの検出処理について説明する。図4は、脆弱性のあるプログラムが実行されている際のメモリマップの一例を示す図である。図4に示す例では、0x65300000~0x6547FFFF番地までの1.5MBの領域にプログラムコードが配置され、0x65480000~0x654FFFF番地までの0.5MBの領域に静的データが配置されている。このプログラムには、バッファオーバーフローを引き起こす可能性のある、脆弱性のある関数が含まれている。なお、図4に示すように、プログラム領域の0x65401122番地には0x54が格納され、0x65401123番地には0xC3が格納されている。IA-32において、0x54はpushesp命令、0xC3はret命令である。pushesp命令は、スタックポインタレジスタに記憶されている値をスタック領域にプッシュするための命令である。また、ret命令は、呼び出された関数から呼び出し元の関数へと制御を戻すための命令である。本実施形態では、これらのpushesp命令およびret命令は、不正アクセスを行うための攻撃コードによって利用されることとなる。図5は、図4に示したプログラムにおけるバッファオーバーフローの脆弱性により、スタック領域に上書きされた攻撃コードの一例を示す図である。図5の例では、スタック領域は4バイトダブルワード幅で構成されており、攻撃コードは16進数で示されている。図5に示す例では、攻撃コードはブロックA~ブロックCの3つのブロックにより構成されている。ブロックAは、VirtualProtect関数を呼び出すことにより、データ領域に実行属性を付与するためのROPReturnOrientedProgramminのプログラムコードである。ブロックAのスタック領域の右側には、各ダブルワードの意味が示されている。先頭のダブルワードは、本来であれば、呼び出し元の関数へと戻るためのリターンアドレスが格納される領域であるが、VirtualProtect関数のアドレスに上書きされている。なお、VirtualProtect関数のアドレスはWindows登録商標のバージョンや実行環境により異なるが、図5の例では、0x7C801AD0としている。そして、図5に示すように、ブロックAには、ret命令のドレス0x65401123、VirtualProtect関数の引数、pushesp命令のアドレス0x65401122が格納されている。ブロックBは、VirtualProtect関数により実行属性が付与されたデータ領域に攻撃コード本体をコピーするプログラムコードである。ブロックBのスタック領域の右側には、当該プログラムコードのアセンブリ言語表記が示されている。このブロックBのプログラムコードは、プロセッサ20がこのスタック領域を参照することにより実行される。ブロックCは、ブロックBのプログラムコードによってデータ領域にコピーされる攻撃コード本体である。ブロックCのスタック領域の右側には、当該プログラムコードのアセンブリ言語表記が示されている。このブロックCのプログラムコードは、プロセッサ20がコピー先のデータ領域を参照することにより実行される。なお、図5に示す例では、説明を簡単にするために、攻撃コード本体では、WinExeccalc,1が実行され、電卓アプリケーションが起動されるのみとなっている。実際に用いられる攻撃コードでは、不正アクセスを行うための任意のアプリケーションや関数が起動される。図6~図8を参照して、図5に示した攻撃コードの動作について説明する。図6~図8において、espはスタックポインタ、eipExtendedInstructionPointerは命令ポインタを示している。命令ポインタは、プロセッサ20が次に実行する命令のアドレスを保持するものであり、その値は命令ポインタレジスタに格納されている。図6~図8に示す例では、状態S1から状態S9までの状態変化が示されている。図6に示す状態S1は、図4に示した脆弱性のある関数の実行によりスタック領域が上書きされ、当該関数から呼び出し元の関数へとリターンする直前の状態を示している。このとき、espは攻撃コードの先頭を示している。そして、eipは脆弱性のある関数から呼び出し元の関数に制御を戻すためのret命令リターン命令の位置を指している。プロセッサ20は、eipに従ってret命令を実行し、espが指していた場所の内容、すなわち、VirtualProtect関数のアドレス0x7C801AD0をeipに設定し、espを1ダブルワード4バイト増加させる。これにより、状態S2へと遷移する。すなわち、脆弱性のある関数の呼び出し元ではなく、VirtualProtect関数へ遷移することとなる。状態S2では、プロセッサ20は、eipに従ってVirtualProtec関数を実行する。このとき、VirtualProtect関数は、espが指す場所の次のダブルワードから順に4つのダブルワードを引数として受け取る。第1引数0x65480000は、属性変更の対象領域の先頭アドレスであり、第2引数0x00001000は対象領域のサイズである。図4を参照すると、このアドレス範囲は、静的変数1のアドレス範囲となっている。第3引数0x00000040は、変更後の属性が読み出し、書き込み、実行の全属性であることを示している。第4引数0x65481000は、変更前の属性の保存先であり、図4を参照すると、静的変数2の領域が変更前の属性の保存先として設定されていることがわかる。これにより、静的変数1の4096バイトの領域に、読み出し、書き込み、実行の属性が付与される。状態S3は、VirtualProtect関数からリターンする直前の状態を示している。このとき、eipはret16命令の位置を指している。Windows登録商標のAPIの場合、関数からリターンする際にはespは引数領域の次のアドレスまで移動される。したがって、プロセッサ20は、VirtualProtect関数のret16命令を実行すると、espが指していたアドレスの値0x65401123をリターンアドレスとしてeipに設定し、espを5ダブルワード20バイト分増加させる。これにより、図7に示す状態S4へと遷移する。状態S4において、eipが指す0x65401123番地には、ret命令が格納されている。そのため、プロセッサ20は、eipに従ってret命令を実行し、espが指している場所に格納されている0x65401122をeipに設定し、espを1ダブルワード4バイト増加させる。図4を参照すると、0x65401122番地には、0x54pushesp命令が格納されていることがわかる。これにより、状態S5へと遷移する。状態S5では、プロセッサ20は、eipに従ってpushesp命令を実行する。プロセッサ20は、pushesp命令を実行すると、espを1ダブルワード4バイト減少させ、espが指す場所に元のespの値図7の例ではesp4を格納する。また、プロセッサ20は、eipを1命令分先へ進める。これにより、状態S6へと遷移する。状態S6では、プロセッサ20は、eipに従ってret命令を実行する。そして、プロセッサ20は、espが指す場所に格納されている値esp4をeipにセットし、espを1ダブルワード4バイト増加させる。これにより、図8に示す状態S7へと遷移する。状態S7では、espとeipはともに、図5に示したスタック領域上のブロックBの先頭を指している。プロセッサ20は、eipに従って、ブロックBのプログラムコードをスタック領域から順次読み出して実行していく。これにより、データ領域上の静的変数1の領域に攻撃コード本体がコピーされる。これにより、状態S8へと遷移する。状態S8では、eipはブロックBのプログラムコードの最後の命令を指している。プロセッサ20は、eipに従って、静的変数1のアドレスをeipに設定するjmp命令を実行する。これにより、状態S9へと遷移する。状態S9では、eipは、データ領域上の静的変数1の領域の先頭を指している。前述したように、静的変数1の領域には、攻撃コード本体が格納されている。したがって、プロセッサ20は、eipに従って、攻撃コード本体のプログラムコードを静的変数1の領域から順次読み出して実行していく。これにより、プロセッサ20は、WinExec関数により電卓アプリケーションを起動する。前述したように、ここでは電卓アプリケーションが起動されることとしたが、攻撃コード本体のプログラムコードを変更することにより、任意の処理の実行が可能となる。ここで、状態S9において、WinExec関数が呼び出されたとき、リターンアドレスが指している領域である静的変数1の領域には実行属性が付与されており、通常のプログラムコードのためのメモリ領域と同様に見える。そのため、リターンアドレスの指し示す先がプログラムコードを格納するためのメモリ領域であるかどうか判断することにより不正アクセスを検出するという一般的な手法では、図4~図8に示したような不正アクセスを検出することができない。また、リターンアドレスの指し示す先の属性が書込み可能であるかどうか判断することにより不正アクセスを検出するという一般的な手法を用いれば、当該不正アクセスの検出は可能になるものの、この手法では、前述したように誤検出の可能性がある。また、状態S9において、WinExec関数が呼び出されたとき、リターンアドレスの指し示す先が関数の先頭である可能性は低い。そのため、リターンアドレスの指し示す先が関数の開始アドレスであるかどうか判断することにより不正アクセスを検出するという一般的な手法では、当該不正アクセスを検出することができない。さらに、正常なプログラムの中には、call命令を用いずに関数呼び出しを行うものもあるため、リターンアドレスの指し示す先の1つ前の命令がcall命令かどうか判断することにより不正アクセスを検出するという一般的な手法では誤検出の可能性がある。一方、本実施形態における検出手法を用いることにより、上述したような誤検出をすることなく、不正アクセスを検出することが可能となる。以下に本実施形態における検出の手順について説明する。図9は、本実施形態における不正アクセスの検出処理の一例を示すフローチャートである。図9に示す処理は、呼び出し検出部40が、所定のAPI関数の呼び出しを検出することにより開始される。リターンアドレス取得部42は、呼び出し検出部40によりAPI関数の呼び出しが検出されると、図9に示すバックトレースのループ処理において、スタック領域を参照してリターンアドレスを順次取得するS901。そして、順次取得されるリターンアドレスのそれぞれについて、バックトレースのループ内の処理が実行される。属性変更検出部44は、呼び出し検出部40により検出されたAPI関数が、例えばVirtualProtect等のメモリ属性変更関数であるかどうか判断するS902。メモリ属性変更関数である場合S902:YES、属性変更検出部44は、さらに、変更後の属性が実行属性を含むものであるかどうか判断するS903。変更後の属性が実行属性を含むものである場合S903:YES、属性変更検出部44は、さらに、リターンアドレス取得部42により取得されたリターンアドレスによって示されるリターン先の1つ前の命令がcall命令であるかどうか判断するS904。そして、call命令であればS904:YES、属性変更検出部44は、属性変更の対象となっている領域のアドレス範囲をアドレス範囲記憶部46に記憶するS905。すなわち、属性変更検出部44は、呼び出し検出部40により検出されたAPI関数の呼び出しは攻撃コードによるものである可能性が高いとして、属性変更の対象となっている領域のアドレス範囲をアドレス範囲記憶部46に記憶する。呼び出し検出部40により検出されたAPI関数がメモリ属性変更関数でない場合S902:NO、不正アクセス検出部48は、リターンアドレス取得部42により取得されたリターンアドレスが、アドレス範囲記憶部46に記憶されているアドレス範囲内に含まれるかどうか判断するS906。また、変更後の属性に実行属性が含まれない場合S903:NO、リターンアドレスによって示されるリターン先の1つ前の命令がcall命令である場合S904:NO、もしくは、アドレス範囲を保存した場合S905においても、当該判定処理S906に遷移する。そして、リターンアドレスがアドレス範囲内に含まれる場合S906:YES、不正アクセス検出部48は、攻撃コードによる不正アクセスが行われていると判定するS907。この場合、不正アクセス検出部48は、例えば、不正アクセスの判定結果を示す情報を出力しS908、実行中のプログラムを強制終了させる。一方、リターンアドレスがアドレス範囲内に含まれない場合S906:NO、不正アクセス検出部48は、必要に応じて、他の一般的な手法による不正アクセスの検出処理を実行するS909。そして、リターンアドレス取得部42により順次取得される複数のリターンアドレスについて上述の処理が実行された後、呼び出し検出部40は、検出されたAPI関数の本体を実行するS910。図9に示した処理により、図5に示した攻撃コードによる不正アクセスを検出する場合を説明する。まず、図6に示す状態S2において、呼び出し検出部40が、VirtualProtect関数の呼び出しを検出すると、図9に示す処理が開始される。そして、リターンアドレス取得部42は、スタック領域を参照し、リターンアドレス0x65401123を取得するS901。図6の状態S2において実行されるVirtualProtect関数は、メモリ属性変更関数でありS902:YES、図4に示したデータ領域における静的変数1の領域に実行属性を付与するものであるS903:YES。また、図4に示すように、取得されたリターンアドレス0x65401123の指し示す先の1つ前の命令はcall命令ではないS904:NO。したがって、属性変更検出部44は、VirtualProtect関数により実行属性が付与される領域のアドレス範囲0x65480000~0x65480FFFをアドレス範囲記憶部46に記憶するS905。そして、リターンアドレス0x65401123は保存されたアドレス範囲0x65480000~0x65480FFFに含まれないためS906:NO、不正アクセス検出部48は、他の一般的な手法による不正アクセスの検出処理を実行するS909。そして、リターンアドレス取得部42は次のリターンアドレスの取得を試みるが、スタックに格納されていたベースアドレスはバッファオーバーフローにより別の値に上書きされているため不正なアドレスであると判定される。そのため、ここでバックトレース処理のループが終了し、呼び出し検出部40は、API関数の本体、すなわち、VirtualProtect関数を呼び出して属性変更処理を実行するS910。これにより、データ領域における静的変数1の領域に実行属性が付与される。その後、図8に示す状態S9に遷移するまでの間にはAPI関数の呼び出しは行われないため、図9に示す処理は実行されない。そして、図8に示す状態S9において、呼び出し検出部40が、WinExec関数の呼び出しを検出すると、図9に示す処理が開始される。WinExec関数の呼び出しが行われたとき、スタック領域には、WinExec関数を呼び出すcall命令の次の命令のアドレスがリターンアドレスとして格納されている。リターンアドレス取得部42は、スタック領域を参照し、このリターンアドレスを取得するS901。WinExec関数は、メモリ属性変更関数ではないためS902:NO、不正アクセス検出部48は、リターンアドレスが、保存されたアドレス範囲0x65480000~0x65480FFFに含まれるかどうか判定するS906。ここで、WinExec関数を呼び出すcall命令は、属性変更が行われた静的変数1の領域にあるため、リターンアドレスも当該領域内にある。つまり、リターンアドレスは、保存されたアドレス範囲0x65480000~0x65480FFFに含まれているS906:YES。そのため、不正アクセス検出部48は、攻撃コードによる不正アクセスが行われていると判定するS907。そして、不正アクセス検出部48は、不正アクセスの判定結果を出力しS908、処理を強制終了させる。これにより、WinExec関数の本体は実行されず、不正アクセスを防止することが可能となる。本実施形態によれば、呼び出し検出部40により検出された関数が、メモリ上の指定されたアドレス範囲の領域に実行可能属性を付与する関数例えばVirtualProtectであり、リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令でない場合に、当該アドレス範囲がアドレス範囲記憶部46に記憶される。そして、リターンアドレスがアドレス範囲記憶部46に記憶されているアドレス範囲内である場合に、不正アクセスが行われていると判定される。したがって、リターンアドレスの指し示す先がプログラムコードを格納するためのメモリ領域と同様に見える場合であっても、不正アクセスを検出することができる。さらに、リターンアドレスの指し示す先の属性が書込み可能であっても、その領域に実行属性を付与した関数の各リターンアドレスの指し示す先の1つ前の命令が関数の呼び出し命令であれば不正アクセスとして誤検出されることはない。そのため、メモリ上のデータ領域に別のプログラムコードを展開する正常なプログラムによる処理を不正アクセスとして誤検出することを防ぐことができる。このように、本実施形態によれば、不正アクセスの検出精度を高めることが可能となる。また、本実施形態によれば、リターンアドレスの指し示す先が関数の先頭でない場合であっても、不正アクセスを検出することができる。さらに、本実施形態では、単に、リターンアドレスの指し示す先の1つ前の命令がcall命令でない場合に不正アクセスが行われていると判定するのではない。そのため、call命令を用いずに関数呼び出しを行う正常なプログラムによる処理を不正アクセスとして誤検出することを防ぐことができる。したがって、本実施形態によれば、不正アクセスの検出精度を高めることが可能となる。また、本実施形態によれば、リターンアドレス取得部42は、バックトレースにより、スタック領域に格納されている複数のリターンアドレスを順次取得することができる。そして、順次取得されるリターンアドレスのそれぞれについて、図9に示したように、属性変更検出部44による処理と、不正アクセス検出部48による処理とが実行される。したがって、複数の関数が階層的に呼び出される構成となっている場合においても同様に、不正アクセスを検出することが可能となる。なお、本実施形態は、本発明の理解を容易にするためのものであり、本発明を限定して解釈するためのものではない。本発明は、その趣旨を逸脱することなく、変更/改良され得るととともに、本発明にはその等価物も含まれる。"