3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PEファイルのバイナリ構造(5) エクスポート関数の定義位置の取得

Posted at

エクスポート関数とは

エクスポート関数とは、そのモジュールが外部に公開している(別のモジュールから呼び出すことが可能な)関数の一覧になります。
DEFファイルだと以下の様な感じで定義している奴ですね。

EXPORTS
	FUNC1	@1	NONAME
	FUNC2	@100

エクスポート関数に関しては、

  • 関数名
  • 序数

のどちらでもアクセス可能となっています。
また序数は基本必須で、明示的に指定してない場合でも自動で割り振られていますが、関数名に関しては無い(あえて名前では公開していない)場合がありますので少し注意が必要です。

IMAGE_SECTION_HEADERアドレスの取得

公開関数の定義へアクセスする為には、まずそのアドレスが定義されている「IMAGE_SECTION_HEADER」へのアドレスを取得するところから始めます。
IMAGE_SECTION_HEADERへのアドレスに関しては、IMAGE_NT_HEADERSのOptionalHeaderメンバに定義されていますので、最初はそちらを参照します。

IMAGE_DATA_DIRECTORY& tData = tNT.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
DWORD nOffset = tData.VirtualAddress;

IMAGE_NT_HEADERSに関しては前述で述べたとおり、解析しているモジュール側のアーキテクチャに合せて32bitと64bitで対応する構造体を使用します。

IMAGE_DIRECTORY_ENTRY_EXPORTに関しては定義されている定数で、通常は0が割り当てられています。

このVirtualAddressが目的とするIMAGE_SECTION_HEADERへのアドレスとなります。

IMAGE_SECTION_HEADERの検索

IMAGE_SECTION_HEADERの数に関しては、IMAGE_NT_HEADERSのFileHeader.NumberOfSectionsに保存されていて、構造体の中には、

  • アドレス
  • ファイルポインタ
  • セクションサイズ

が格納されています。

メンバ
VirtualAddress 先頭アドレス
Misc.VirtualSize メモリ上に読み込まれた時に確保されるデータサイズ。
SizeOfRawData そのセクションがファイル上で確保されているサイズ。

また、構造体の配列の先頭アドレスは、以下の様にマクロを使用して取得します。

PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(&tNT);

実際に目的とするセクションのアドレスに関しては、VirtualAddressからVirtualSizeまでの範囲に取得したアドレスが含まれているかどうか、で検索します。

PIMAGE_SECTION_HEADER sec = NULL;
for ( int i=0; i < tNT.FileHeader.NumberOfSections; i++, section++ )
{
	DWORD size = section->Misc.VirtualSize;
	if ( size == 0 ){size = section->SizeOfRawData;}
	if ( (rva >= section->VirtualAddress) &&  (rva < (section->VirtualAddress + size)))
	{
		sec = section;
		break;
	}
}
if( sec == NULL ){ return false;}

セクションにはアドレスとファイルポインタの両方の情報が含まれていますので、これを使用すると相互に変換を行うことができます。

UINT delta = sec->VirtualAddress - sec->PointerToRawData;

この値を利用してIMAGE_SECTION_HEADERのアドレスをファイルポインタへと変換すれば、ようやく目的とするエクスポート関数が定義されている場所へと到達できます。

IMAGE_EXPORT_DIRECTORY& tExport = (*(IMAGE_EXPORT_DIRECTORY*)&(pFile[nOffset - delta]));

次は実際に外部公開関数の列挙を行います。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?