DLLのエクスポートディレクトリを取得したいのですがうまくいきません。
DLLをロードすればうまくいくんですが、できれば
Dependency Walkerのようにロードしないで取得したいです。
下記のコードですと、exportDirectory->NumberOfNamesが
425297となり、この時点で明らかに異常な数値になってしまいます。
fileDataではなく、moduleを使うとちゃんと954になり、うまくいきます。
dosとntまでは正しい情報が取れているようです。
exportDirectoryからがおかしいようです。
ファイルデータとしてただ読み込んだだけでは
DLLの解析はできないのでしょうか?
環境はVC6 WinXP HomeEdition SP3です。
よろしくお願いします。
#define MAKE_PTR(type, ptr, offset) (type)((DWORD)(ptr)+(DWORD)(offset))
void dump(HMODULE module)
{
// モジュールのパスを取得
TCHAR path[MAX_PATH]; ::GetModuleFileName(module, path, MAX_PATH);
// ファイルを開く
HANDLE file = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
// ファイルサイズを取得する
DWORD fileSize = ::GetFileSize(file, 0);
// ファイルデータ用のバッファを確保する
BYTE* fileData = new BYTE[fileSize];
// ファイルデータを取得する
::ReadFile(file, fileData, fileSize, &fileSize, 0);
// ファイルを閉じる
::CloseHandle(file);
// イメージ情報を取得する
// IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)module; // これだとうまくいく
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)fileData;
IMAGE_NT_HEADERS* nt = MAKE_PTR(IMAGE_NT_HEADERS*, dos, dos->e_lfanew);
IMAGE_EXPORT_DIRECTORY* exportDirectory = MAKE_PTR(IMAGE_EXPORT_DIRECTORY*, dos,
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
// エクスポートディレクトリの情報を取得する
DWORD* nameTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfNames);
WORD* ordinalTable = MAKE_PTR(WORD*, dos, exportDirectory->AddressOfNameOrdinals);
DWORD* addressTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfFunctions);
// エクスポートディレクトリをダンプする
for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++) {
LPCSTR name = MAKE_PTR(LPCSTR, dos, nameTable[i]);
WORD ordinal = ordinalTable[i];
PROC proc = (PROC)addressTable[i];
printf("%3d, %3d, %08X, %s\n", i, ordinal, proc, name);
}
// バッファを開放する
delete[] fileData;
}
void main()
{
dump(::GetModuleHandle(TEXT("kernel32.dll")));
}
CreateFileMapping() の SEC_IMAGE を利用すれば、LoadLibrary() でロードした場合と同じようにデータが配置されます。
void dump(HMODULE module)
{
TCHAR path[MAX_PATH]; ::GetModuleFileName(module, path, MAX_PATH);
HANDLE file = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
HANDLE map = ::CreateFileMapping(file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID view = ::MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)view;
IMAGE_NT_HEADERS* nt = MAKE_PTR(IMAGE_NT_HEADERS*, dos, dos->e_lfanew);
IMAGE_EXPORT_DIRECTORY* exportDirectory = MAKE_PTR(IMAGE_EXPORT_DIRECTORY*, dos,
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* nameTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfNames);
WORD* ordinalTable = MAKE_PTR(WORD*, dos, exportDirectory->AddressOfNameOrdinals);
DWORD* addressTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfFunctions);
for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++) {
LPCSTR name = MAKE_PTR(LPCSTR, dos, nameTable[i]);
WORD ordinal = ordinalTable[i];
PROC proc = (PROC)addressTable[i];
printf("%3d, %3d, %08X, %s\n", i, ordinal, proc, name);
}
::UnmapViewOfFile(view);
::CloseHandle(map);
::CloseHandle(file);
}
コピペするだけで完璧に動作しました。
非常に助かりました。ありがとうございました。
少しおかしいところがあったので修正しました。
これでDependency Walkerとほぼ同じになりました。
void dump(HMODULE module)
{
TCHAR path[MAX_PATH]; ::GetModuleFileName(module, path, MAX_PATH);
_tprintf(TEXT("dump %s\n"), path);
HANDLE file = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
HANDLE map = ::CreateFileMapping(file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID view = ::MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)view;
IMAGE_NT_HEADERS* nt = MAKE_PTR(IMAGE_NT_HEADERS*, dos, dos->e_lfanew);
IMAGE_EXPORT_DIRECTORY* exportDirectory = MAKE_PTR(IMAGE_EXPORT_DIRECTORY*, dos,
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* nameTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfNames);
WORD* ordinalTable = MAKE_PTR(WORD*, dos, exportDirectory->AddressOfNameOrdinals);
DWORD* addressTable = MAKE_PTR(DWORD*, dos, exportDirectory->AddressOfFunctions);
for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++) {
LPCSTR name = MAKE_PTR(LPCSTR, dos, nameTable[i]);
WORD ordinal = ordinalTable[i];
PROC proc = (PROC)addressTable[ordinal]; // 修正
printf("%3d, %3d, %08X, %s\n", i, ordinal + exportDirectory->Base, proc, name); // 修正
}
::UnmapViewOfFile(view);
::CloseHandle(map);
::CloseHandle(file);
_tprintf(TEXT("\n"));
}
void main()
{
dump(::LoadLibrary(TEXT("kernel32.dll")));
dump(::LoadLibrary(TEXT("shell32.dll")));
}
ツイート | ![]() |