我目前正在编写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)));
Run Code Online (Sandbox Code Playgroud)
我是否必须使用内存映射IO来正确执行此操作?我在计算地址错了吗?有关PE RVA的信息似乎很少.提前致谢.
Ole*_*leg 13
我从时间打开一个我的老项目,因为我喜欢你检查进口和出口的目录结构(IMAGE_DIRECTORY_ENTRY_EXPORT
,IMAGE_DIRECTORY_ENTRY_IMPORT
,IMAGE_DIRECTORY_ENTRY_IAT
和IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
).我可以简单地解释你遇到问题的部分.我的意思是如何找到指针的部分,例如IMAGE_EXPORT_DIRECTORY
在PE内部.
首先,可以使用读/写文件操作来分析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);
Run Code Online (Sandbox Code Playgroud)
在我们有指向pSrcFile
PE文件的指针后,我们可以找到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);
Run Code Online (Sandbox Code Playgroud)
现在我们需要任何目录的虚拟地址.例如,
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
Run Code Online (Sandbox Code Playgroud)
是导出目录的虚拟地址.之后将虚拟地址转换为内存指针,我们应该找到内部有这个虚拟地址的PE部分.要做到这一点,我们可以列举PE的部分,且找到一个i
擦菜板或等于0
和小于pNtHdr->FileHeader.NumberOfSection
S其中
pFirstSectionHeader[i].VirtualAddress <=
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
Run Code Online (Sandbox Code Playgroud)
同时
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
< pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize
Run Code Online (Sandbox Code Playgroud)
那么你应该在以下部分中搜索导出数据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);
Run Code Online (Sandbox Code Playgroud)
你应该重复找到相同的程序(IMAGE_IMPORT_DESCRIPTOR *)
对应于IMAGE_DIRECTORY_ENTRY_IMPORT
和(IMAGE_BOUND_IMPORT_DESCRIPTOR *)
相当于IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
转储导入信息包含绑定信息(如果存在的话).
要转发信息IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
(对应(ImgDelayDescr *)
于delayimp.h中定义),您还应使用IMAGE_DIRECTORY_ENTRY_IAT
(对应于(IMAGE_THUNK_DATA32 *)
)的信息.
有关PE的更多信息,我建议你http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
归档时间: |
|
查看次数: |
8946 次 |
最近记录: |