c – 在PE文件中解析用于导入和导出表的RVA

前端之家收集整理的这篇文章主要介绍了c – 在PE文件中解析用于导入和导出表的RVA前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在编写一个PE解析器/加载程序.
我已经使用标准的c文件io,检索到的有效的DOS和PE头(可选标题)成功地将PE文件加载到内存中,并获得了PE的部分的访问.
我的下一个目标是访问导出表以检索导出的符号.
为了做到这一点,我已经使用存储在可选头数据字典数组中的RVA(索引0)(我相信指向导出表),并将该地址添加到加载到程序存储器中的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_EXPORT,IMAGE_DIRECTORY_ENTRY_IMPORT,IMAGE_DIRECTORY_ENTRY_IAT和IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT).我可以简单地解释你有问题的部分.我的意思是说明如何找出PE内的例如IMAGE_EXPORT_DIRECTORY的指针.

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

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

在指向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的部分,并找到一个或者等于0和等于0而不是pNtHdr-> FileHeader.NumberOfSections

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_DIRECTORY_ENTRY_IMPORT对应的(IMAGE_IRPORT_DESCRIPTOR *)对应于IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT的(IMAGE_IMPORT_DESCRIPTOR *),您应该重复找到与IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT相对应的过程,以转储包含绑定信息(如果存在)的导入信息.

要从IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT(对应于delayimp.h中定义的(ImgDelayDescr *))转储信息,您还应该使用来自IMAGE_DIRECTORY_ENTRY_IAT(对应于(IMAGE_THUNK_DATA32 *))的信息.

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

猜你在找的C&C++相关文章