gpt4 book ai didi

c++ - 解析 PE 文件中导入和导出表的 RVA

转载 作者:可可西里 更新时间:2023-11-01 15:54:30 26 4
gpt4 key购买 nike

我目前正在编写 PE 解析器/加载器。我已经使用标准 c 文件 io 成功地将 PE 文件加载到内存中,检索到有效的 DOS 和 PE header (可选 header )以及获得对 PE 部分的访问权限。我的下一个目标是访问导出表以检索导出的符号。为此,我使用了存储在索引 0 处的可选 header 数据字典数组中的 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 的部分并找到大于或等于 0 且小于 pNtHdr->FileHeader.NumberOfSectioni,其中

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_IMPORT_DESCRIPTOR *) 和对应于 (IMAGE_BOUND_IMPORT_DESCRIPTOR *) >IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 转储包含绑定(bind)信息(如果存在)的导入信息。

要从 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++ - 解析 PE 文件中导入和导出表的 RVA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2975639/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com