打印导出表信息
導出表是數據目錄中的第一張表,要注意 VirtualAddress 是內存偏移。導出表中的三張表地址也是內存偏移。
代碼
// 打印導出表 VOID PrintExportTable(LPVOID pFileBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)(pDosHeader->e_lfanew + (DWORD)pFileBuffer + 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));PIMAGE_SECTION_HEADER pSectionHeader = \(PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);PIMAGE_EXPORT_DIRECTORY pExportDirectory = \(PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer, pOptionHeader->DataDirectory[0].VirtualAddress));printf("Base = %x\n", pExportDirectory->Base);printf("NumberOfFunctions = %x\n", pExportDirectory->NumberOfFunctions);printf("NumberOfNames = %x\n", pExportDirectory->NumberOfNames);printf("----AddressOfFunctions----\n");PDWORD AddressOfFunctions = (PDWORD)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer, pExportDirectory->AddressOfFunctions));for (int i = 0; i < pExportDirectory->NumberOfFunctions; i++){printf("AddressOfFunctions[%d] = %x\n", i, AddressOfFunctions[i]);}printf("----AddressOfNames & AddressOfNameOridinals----\n");PDWORD AddressOfNames = (PDWORD)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer, pExportDirectory->AddressOfNames));PWORD AddressOfNameOridinals = (PWORD)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer, pExportDirectory->AddressOfNameOrdinals));for (i = 0; i < pExportDirectory->NumberOfNames; i++){printf("AddressOfNames[%d] = %s, AddressOfOrdinals[%d] = %d\n", i, (char*)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer, AddressOfNames[i])), i, AddressOfNameOridinals[i]);} }VOID TestPrintExportTable(LPSTR lpszFile) {LPVOID pFileBuffer = NULL;if (!ReadPEFile(lpszFile, &pFileBuffer)){printf("讀取文件失敗");return;}PrintExportTable(pFileBuffer);free(pFileBuffer); }// 內存偏移RVA轉成文件偏移FOA // 返回轉換后FOA的值,找不到則返回0 DWORD RvaToFoa(IN LPVOID pFileBuffer,IN DWORD dwRva) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)(pDosHeader->e_lfanew + (DWORD)pFileBuffer + 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));PIMAGE_SECTION_HEADER pSectionHeader = \(PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);// RVA在文件頭中或者文件對齊==內存對齊時,RVA==FOAif (dwRva < pOptionHeader->SizeOfHeaders || \pOptionHeader->SectionAlignment == pOptionHeader->FileAlignment){return dwRva;}// 遍歷節表,確定偏移屬于哪一個節 for (int i = 0; i < pPEHeader->NumberOfSections; i++){ if (dwRva >= pSectionHeader[i].VirtualAddress && \dwRva < pSectionHeader[i].VirtualAddress + pSectionHeader[i].Misc.VirtualSize){int offset = dwRva - pSectionHeader[i].VirtualAddress;return pSectionHeader[i].PointerToRawData + offset;} }printf("找不到RVA %x 對應的 FOA,轉換失敗\n", dwRva);return 0; }運行結果
用 DEPENDENCY WALKER 驗證,解析正確。
附DLL的def導出文件
總結
- 上一篇: 使用def导出动态链接库(VC6)
- 下一篇: 操作系统是如何使用重定位表的