Windows:PEヘッダからたどって、DLLのエクスポート関数を列挙する
Windows7の32bitアプリ、Visual Studio2008で動作確認。
#include <stdio.h> #include <windows.h> #define RVAtoVA(type, base, offset) ((type)(PVOID)(((PCHAR)(base))+(offset))) int main() { DWORD dwModuleBaseAddr; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS32 pPEHeader; PIMAGE_OPTIONAL_HEADER32 pOptionalHeader; PIMAGE_DATA_DIRECTORY pDataDirectoryHeader; PIMAGE_EXPORT_DIRECTORY pExportDirectoryHeader; CHAR cDLLName[] = "kernel32.dll"; unsigned int i; // DLLファイルはDOS_HEADERから始まる dwModuleBaseAddr = (DWORD)GetModuleHandle(cDLLName); // HMODULEはDLLのベース(先頭)アドレス pDosHeader = (PIMAGE_DOS_HEADER)dwModuleBaseAddr; printf("pDosHeader = dwModuleBaseAddr(%s) = 0x%x\n", cDLLName, dwModuleBaseAddr); // pDosHeader->e_lfanew:PEヘッダ(IMAGE_NT_HEADERS32)へのRVA(モジュールベースアドレスからのオフセット) pPEHeader = (PIMAGE_NT_HEADERS32)(dwModuleBaseAddr + pDosHeader->e_lfanew); printf("pDosHeader->e_lfanew = 0x%x\n", pDosHeader->e_lfanew); printf("pPEHeader = 0x%x\n", pPEHeader); // pPEHeader->OptionalHeader : IMAGE_OPTIONAL_HEADER32 pOptionalHeader = &pPEHeader->OptionalHeader; printf("pOptionalHeader = pPEHeader->OptionalHeader = 0x%x\n", pOptionalHeader); // pOptionalHeader->DataDirectory[0] : エクスポート関数に関わる情報が格納されている pDataDirectoryHeader = &pOptionalHeader->DataDirectory[0]; printf("pDataDirectoryHeader = &pOptionalHeader->DataDirectory[0] = 0x%x\n", pDataDirectoryHeader); // pDataDirectoryHeader->VirtualAddress : IMAGE_EXPORT_DIRECTORY構造体へのRVA(モジュールベースアドレスからのオフセット) pExportDirectoryHeader = (PIMAGE_EXPORT_DIRECTORY)(dwModuleBaseAddr + pDataDirectoryHeader->VirtualAddress); printf("pDataDirectoryHeader->VirtualAddress = 0x%x\n", pDataDirectoryHeader->VirtualAddress); //printf("&pDataDirectoryHeader->VirtualAddress = 0x%x\n", &pDataDirectoryHeader->VirtualAddress); printf("pExportDirectoryHeader = 0x%x\n", pExportDirectoryHeader); // エクスポートされている関数を列挙する for(i=0; i<pExportDirectoryHeader->NumberOfNames; i++) { PCHAR pProcName; DWORD pProc; WORD wOrdinalNum; pProcName = RVAtoVA(PCHAR, dwModuleBaseAddr, RVAtoVA(PDWORD, dwModuleBaseAddr, pExportDirectoryHeader->AddressOfNames)[i]); wOrdinalNum = RVAtoVA(PWORD, dwModuleBaseAddr, pExportDirectoryHeader->AddressOfNameOrdinals)[i]; pProc = RVAtoVA(DWORD, dwModuleBaseAddr, RVAtoVA(PDWORD, dwModuleBaseAddr, pExportDirectoryHeader->AddressOfFunctions)[wOrdinalNum]); printf("0x%x : %s\n", pProc, pProcName); } return 0; }
[参考]
PEフォーマットを解釈せよ!(1-3) − @IT
http://www.atmarkit.co.jp/fsecurity/rensai/re05/re01.html