ImageDirectoryEntryToData イメージからセクションデータを取得

Cの宣言:

PVOID ImageDirectoryEntryToData(
	IN LPVOID pBase,
	IN BOOLEAN bMappedAsImage,
	IN USHORT DirectoryEntry,
	OUT PULONG Size);

VBの宣言:

Declare Function ImageDirectoryEntryToData Lib "imagehlp" ( _
    ByVal pBase As Long, _
    ByVal bMappedAsImage As Long, _
    ByVal DirectoryEntry As Integer, _
    ByRef Size As Long) As Long

説明:

pBaseで指定したイメージのデータディクショナリを元に、DirectoryEntryで指定したセクションを取得する。

引数の意味は以下の通り。
pBase (IN) 取得元のイメージのベースアドレス。
bMappedAsImage (IN) TRUEの場合、pBaseで識別されるイメージがシステムによってロードされたことを示す。FALSEの場合、MapViewOfFile関数によってマップされたことを示す。
DirectoryEntry (IN) 取得するセクションの種類を指定するフラグ。後述の表を参照。
Size (OUT) 取得結果のセクションのサイズ。

DirectoryEntryには以下のいずれかのフラグを指定可能。
IMAGE_DIRECTORY_ENTRY_EXPORT エクスポートテーブル
IMAGE_DIRECTORY_ENTRY_IMPORT インポートテーブル
IMAGE_DIRECTORY_ENTRY_RESOURCE リソーステーブル
IMAGE_DIRECTORY_ENTRY_EXCEPTION 例外テーブル
IMAGE_DIRECTORY_ENTRY_SECURITY 属性認証テーブル
IMAGE_DIRECTORY_ENTRY_BASERELOC ベース再配置テーブル
IMAGE_DIRECTORY_ENTRY_DEBUG デバッグデータ
IMAGE_DIRECTORY_ENTRY_GLOBALPTR グローバルポインタレジスタのRVA
IMAGE_DIRECTORY_ENTRY_TLS スレッドローカルストレージテーブル
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ロードコンフィグレーションテーブル
IMAGE_DIRECTORY_BOUND_IMPORT バウンドインポートテーブル
IMAGE_DIRECTORY_IAT インポートアドレステーブル

戻り値は、取得結果のセクションデータである。関数の実行に失敗した場合、NULLが返される。

Cのサンプル1:

kernel32.dllがエクスポートしている関数のリストを表示する。
void DispExportFuncs(void)
{
	DWORD BaseAddress;
	ULONG Size;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory;
	DWORD *pExportAddressTable;
	WORD *pExportOrdinalTable;
	DWORD *pExportNamePointerTable;
	DWORD i, j;

	/* kernel32.dllのベースアドレスを取得 */
	BaseAddress = (DWORD)GetModuleHandle("kernel32.dll");

	/* エクスポートディレクトリを取得 */
	pExportDirectory = ImageDirectoryEntryToData(
		(LPVOID)BaseAddress, 
		TRUE, 
		IMAGE_DIRECTORY_ENTRY_EXPORT, 
		&Size);

	/* 各テーブルのポインタを取得 */
	pExportAddressTable = (DWORD *)(BaseAddress + pExportDirectory->AddressOfFunctions);
	pExportOrdinalTable = (WORD *)(BaseAddress + pExportDirectory->AddressOfNameOrdinals);
	pExportNamePointerTable = (DWORD *)(BaseAddress + pExportDirectory->AddressOfNames);

	/* 各エントリの表示 */
	for(i=0; i<pExportDirectory->NumberOfFunctions; i++) {
		printf("序数: %d", pExportDirectory->Base + i);

		for(j=0; j<pExportDirectory->NumberOfNames; j++) {
			if(pExportOrdinalTable[j] == i) printf(", ヒント: %d, 名前: %s", j, BaseAddress + pExportNamePointerTable[j]);
		}

		if(BaseAddress + pExportAddressTable[i] < (DWORD)pExportDirectory || BaseAddress + pExportAddressTable[i] >= (DWORD)pExportDirectory + Size) {
			printf(", アドレス: %08X", BaseAddress + pExportAddressTable[i]);
		} else {
			printf(", フォワーダ参照: %s", BaseAddress + pExportAddressTable[i]);
		}

		printf("\n");
	}
}



Cのサンプル2:

user32.dllが(非遅延)インポートしている関数のリストを表示する。
void DispImportFuncs(void)
{
	DWORD BaseAddress;
	ULONG Size;
	PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
	PIMAGE_THUNK_DATA pThunkData;
	PIMAGE_IMPORT_BY_NAME pImportByName;

	/* user32.dllを読み込み */
	BaseAddress = (DWORD)LoadLibrary("user32.dll");

	/* インポートディレクトリを取得 */
	pImportDescriptor = ImageDirectoryEntryToData(
		(LPVOID)BaseAddress, 
		TRUE, 
		IMAGE_DIRECTORY_ENTRY_IMPORT, 
		&Size);

	/* 各インポート関数名を表示 */
	while(pImportDescriptor->OriginalFirstThunk != 0) {
		printf("DLL名: %s\n", BaseAddress + pImportDescriptor->Name);

		pThunkData = (PIMAGE_THUNK_DATA)(BaseAddress + pImportDescriptor->OriginalFirstThunk);

		while(pThunkData->u1.Ordinal != 0) {
			if(IMAGE_SNAP_BY_ORDINAL(pThunkData->u1.Ordinal)) {
				printf("\t序数: %d\n", IMAGE_ORDINAL(pThunkData->u1.Ordinal));
			} else {
				pImportByName = (PIMAGE_IMPORT_BY_NAME)(BaseAddress + (DWORD)pThunkData->u1.AddressOfData);
				printf("\tヒント: %d, 関数名: %s\n", pImportByName->Hint, pImportByName->Name);
			}

			pThunkData++;
		}

		printf("\n");
		pImportDescriptor++;
	}

	/* 後処理 */
	FreeLibrary((HMODULE)BaseAddress);
}

VBのサンプル:

kernel32.dllがエクスポートしている関数の一覧をテキストボックスに表示する。
'宣言
Declare Function MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByRef Dest As Any, _
    ByRef Src As Any, _
    ByVal Size As Long) As Long

Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyA" ( _
    ByVal DestStr As String, _
    ByVal pSrc As Any) As Long

'コード
Private Sub Command1_Click()
    Dim Size As Long
    Dim BaseAddress As Long
    Dim pExportDirectory As Long
    Dim ExportDirectory As IMAGE_EXPORT_DIRECTORY
    Dim ExportNamePointerTable() As Long
    Dim S As String
    Dim FuncName As String * 1000
    Dim I As Long
    
    'kernel32.dllのベースアドレスを取得
    BaseAddress = GetModuleHandle("kernel32.dll")
    
    'エクスポートディレクトリを取得
    pExportDirectory = ImageDirectoryEntryToData(BaseAddress, 1, IMAGE_DIRECTORY_ENTRY_EXPORT, Size)
    MoveMemory ExportDirectory, ByVal pExportDirectory, Len(ExportDirectory)
    
    'エクスポートされている関数の名前のリストを取得
    ReDim ExportNamePointerTable(ExportDirectory.NumberOfNames - 1)

    MoveMemory _
        ExportNamePointerTable(0), _
        ByVal (BaseAddress + ExportDirectory.AddressOfNames), _
        ExportDirectory.NumberOfNames * 4
    
    '各関数名を表示
    For I = 0 To ExportDirectory.NumberOfNames - 1
        PtrToStr FuncName, BaseAddress + ExportNamePointerTable(I)
        S = S & Left(FuncName, InStr(FuncName, vbNullChar) - 1) & vbCrLf
    Next
    
    Text1.Text = S
End Sub


(original text:2000/03/22 更新)

本ドキュメントの内容は保証しません。本ドキュメントによって生じた結果について、一切の責任を負いません。