打印導出表信息

導出表是數據目錄中的第一張表,要注意 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==FOA
	if (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導出文件

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章