在PE文件中解析导入和导出表的RVA

我目前正在编写PE解析器/加载器。 我已经使用标准c文件io成功地将PE文件加载到内存中,检索有效的DOS和PE标头(可选标头)以及访问PE的部分。 我的下一个目标是获取对Export表的访问权以检索导出的符号。 为此,我使用存储在索引0的可选头数据字典数组中的RVA(我相信指向导出表)并将此地址添加到加载到程序存储器中的PE文件的地址,然后将其转换为有效的导出表头。 当我这样做时,我正在调出NULL地址和数据。 这是一个小代码片段;

// RVA from optional headers data dictionaries array cast to Export directory type IMAGE_EXPORT_DIRECTORY* ied( (IMAGE_EXPORT_DIRECTORY*)((void*) ((unsigned char*)buffer + ioh->DataDirectory[0].VirtualAddress))); 

我是否必须使用内存映射IO来正确执行此操作? 我在计算地址错了吗? 有关PE RVA的信息似乎很少。 提前致谢。

我打开了一个旧的项目,因为我喜欢你检查导入和导出目录的结构( IMAGE_DIRECTORY_ENTRY_EXPORTIMAGE_DIRECTORY_ENTRY_IMPORTIMAGE_DIRECTORY_ENTRY_IATIMAGE_DIRECTORY_ENTRY_DELAY_IMPORT )。 我可以简单地解释你遇到问题的部分。 我的意思是如何在PE内找到指向例如IMAGE_EXPORT_DIRECTORY的指针。

首先,可以使用读/写文件操作来分析PE文件,但使用文件映射要容易得多,如下所示:

 hSrcFile = CreateFile (pszSrcFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); hMapSrcFile = CreateFileMapping (hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL); pSrcFile = (PBYTE) MapViewOfFile (hMapSrcFile, FILE_MAP_READ, 0, 0, 0); 

在我们有指向PE文件的指针pSrcFile之后我们可以找到PE内部的另一个重要位置:

 pDosHeader = (IMAGE_DOS_HEADER *)pSrcFile; IMAGE_NT_HEADERS32 *pNtHdr = (IMAGE_NT_HEADERS32 *) ((PBYTE)pDosHeader + pDosHeader->e_lfanew); IMAGE_SECTION_HEADER *pFirstSectionHeader = (IMAGE_SECTION_HEADER *) ((PBYTE)&pNtHdr->OptionalHeader + pNtHdr->FileHeader.SizeOfOptionalHeader); 

现在我们需要任何目录的虚拟地址。 例如,

 pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 

是导出目录的虚拟地址。 之后将虚拟地址转换为内存指针, 我们应该找到内部有这个虚拟地址的PE部分 。 要做到这一点,我们可以枚举PE的各个部分并找到一个i grater或等于0且小于pNtHdr->FileHeader.NumberOfSection s其中

 pFirstSectionHeader[i].VirtualAddress <= pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 

同时

 pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress < pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize 

那么你应该在pFirstSectionHeader[i]部分搜索导出数据:

 IMAGE_SECTION_HEADER *pSectionHeader = &pFirstSectionHeader[i]; IMAGE_EXPORT_DIRECTORY *pExportDirectory = (IMAGE_EXPORT_DIRECTORY *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData + pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress - pSectionHeader->VirtualAddress); 

您应该重复查找的相同程序(IMAGE_IMPORT_DESCRIPTOR *)对应于IMAGE_DIRECTORY_ENTRY_IMPORT(IMAGE_BOUND_IMPORT_DESCRIPTOR *) ,对应于IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT以转储包含绑定信息(如果存在)的导入信息。

要从IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT转储信息(对应于(ImgDelayDescr *)定义的(ImgDelayDescr *) ),您还应使用IMAGE_DIRECTORY_ENTRY_IAT信息(对应于(IMAGE_THUNK_DATA32 *) )。

有关PE的更多信息,我建议你http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

并非所有PE映像都具有导出目录表。 您需要检查可选标头的Windows特定“NumberOfRvaAndSizes”字段。 如果它小于或等于IMAGE_DIRECTORY_ENTRY_EXPORT (0),则没有导出目录表(即,在ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]没有任何有效的位置)。

有关示例,请参阅此问题的答案。

有宏定义获得第一部分

PIMAGE_SECTION_HEADER FisrtSection = IMAGE_FIRST_SECTION(NtHeaders)