各セクションについて
.text、.data、.rsrcなどの各セクションは、IMAGE_SECTION_HEADER
構造体が羅列されたデータの後に配置されます。
今回は、セクションの中でもデータ構造的に興味深い、インポートセクション、およびリソースセクションを取り上げて解説します。
インポートセクション(.idata)
インポートとは
インポートとは外部DLLと動的リンクを行うための準備のことを言います。プロセスメモリにEXEファイルのイメージがロードされた後、ここで解説するインポート情報をもとに動的リンクの準備を行うことで、Win32APIなどの各種DLL関数の呼び出しができるようになります。
インポートセクションの構造
インポートセクションには、DLL名、関数名、関数名を示すRVA、実行可能アドレスを示すRVAなどの情報が存在します。
IMAGE_IMPORT_DESCRIPTOR構造体
インポートセクションの先頭に配置されるのがIMAGE_IMPORT_DESCRIPTOR
構造体です。この構造体は動的リンクするDLLの個数だけ存在します。ただし、この構造体のあとに、0で埋め尽くされた20バイト(IMAGE_IMPORT_DESCRIPTOR
のサイズ)のNULL空間が配置されます。
typedef struct _IMAGE_IMPORT_DESCRIPTOR { DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) DWORD TimeDateStamp; DWORD ForwarderChain; // -1 if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR; typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
- OriginalFirstThunk
- TimeDateStamp
- ForwarderChain
- Name, FirstThunk
OriginalFirstThunk
はルックアップテーブル内を示すRVAです。対象DLLのルックアップデータが羅列する先頭アドレスをRVAで示します。TimeDateStamp
には動的リンク時にタイムスタンプが格納されます。EXEファイルの状態(実行していない状態)では0です。ForwarderChain
にはエクスポート転送を許可するときは-1、許可しないときは0を指定します。一般的には0を指定します。Name
はDLL名を示すRVAです。最後のFirstThunk
はインポートテーブル内を示すRVAです。対象DLLのインポートテーブルが羅列する先頭アドレスをRVAで示します。DLL名の集合データ
IMAGE_IMPORT_DESCRIPTOR
構造体の次に配置されるのがDLL名です。1つのDLLは16バイト(16バイトに満たないときはNULLで埋められます)で、動的リンクするDLLの数だけ存在します。
ルックアップテーブル
ルックアップテーブルはDWORD
配列で構成され、次のように表現されます。
RVAが示すのは、ルックアップテーブルの次に配置されるヒントテーブル内の関数名の先頭アドレスです。
ヒントテーブル
ヒントテーブルは0が格納されるDWORD
値、NULL文字で終わる可変長の文字列の集合からなります。1つのデータの開始位置を偶数に合わせる必要があるため、必要に応じて文字列終端のNULL文字が2バイトになることがあります。
インポートアドレステーブル
内容はルックアップテーブルと同一です。動的リンク時に実際のDLL関数の実行アドレスに書き換えられます。