问题描述
我目前正在写一个解析器PE /加载器。
我已成功加载PE文件到内存使用标准的C文件IO,获取有效的DOS和PE头(可选头),以及获得访问PE的部分。
我的下一个目标是获得导出表检索导出的符号。
要做到这一点,我已经使用存储在可选的头的RVA数据字典数组中的索引0(我相信指向导出表),并加入这个地址装入程序存储器PE文件的地址,然后浇铸到这一个有效的出口表头。当我这样做,我转向了空地址和数据。这里是一个小code段;
I am currently writing a PE parser/loader.I have successfully loaded the PE file into memory using standard c file io, retrieved valid DOS and PE headers (the optional header) as well as gaining access to the PE's sections.My next target is to gain access to the Export table to retrieve exported symbols.To do this i have used the RVA stored in the optional headers data-dictionary array at index 0 (which i believe points to the export table) and added this address to the address of the PE file loaded into program memory, then casted this into a valid export table header. I am turning up NULL addresses and data when i do this. here is a small code snippet;
// 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的信息似乎稀疏。
先谢谢了。
Do i have to use memory mapped IO to do this properly? Am i calculating the address wrong? Information on PE RVA's seems sparse.thanks in advance.
推荐答案
我打开我的一个来自我喜欢你检查进口和出口目录(结构时旧项目 IMAGE_DIRECTORY_ENTRY_EXPORT
, IMAGE_DIRECTORY_ENTRY_IMPORT
, IMAGE_DIRECTORY_ENTRY_IAT
和 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
)。我可以在短期解释,你有问题的部分。我指的是一部分,如何找出指针,例如 IMAGE_EXPORT_DIRECTORY
PE内部。
I opened one my old project from the time as I like you examined the structure of import and export directories (IMAGE_DIRECTORY_ENTRY_EXPORT
, IMAGE_DIRECTORY_ENTRY_IMPORT
, IMAGE_DIRECTORY_ENTRY_IAT
and IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
). I can in short explain the part where you have a problem. I mean the part how to find out the pointer to for example IMAGE_EXPORT_DIRECTORY
inside of PE.
所有的原因,可以使用读/写文件操作来分析PE文件,但它更容易使用像下列文件映射的第一
First of all of cause it is possible to use Read/Write file operations to analyse a PE file, but it is much easier to use file mapping like following:
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);
之后,我们有指针 pSrcFile
这点PE文件包含我们可以找到另一个重要场所内PE的:
after we have the pointer pSrcFile
which point to the PE file contain we can find another important places inside of 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);
现在我们都需要的任何目录的虚拟地址。例如,
Now we have all needed virtual address of any directory. For example,
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
是导出目录的虚拟地址。之后,虚拟地址转换成内存指针,我们应该找出里面有这个虚拟地址的PE栏目。要做到这一点,我们可以列举PE的部分,并找到 I
磨碎或等于 0
和小于 pNtHdr-> FileHeader.NumberOfSection
s其中
is a virtual address of export directory. After that to convert the virtual address to the memory pointer, we should find out the section of PE which has this virtual address inside. To do this we can enumerate sections of PE and find an i
grater or equal to 0
and less then pNtHdr->FileHeader.NumberOfSection
s where
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
来转储信息导入包含绑定信息(如果存在的话)。
The same procedure you should repeat to find (IMAGE_IMPORT_DESCRIPTOR *)
which corresponds to IMAGE_DIRECTORY_ENTRY_IMPORT
and (IMAGE_BOUND_IMPORT_DESCRIPTOR *)
which corresponds to IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
to dump import information inclusive a binding information (if exist).
要转储从 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
信息(对应于(ImgDelayDescr *)
在delayimp.h定义),你应该使用也是从信息 IMAGE_DIRECTORY_ENTRY_IAT
(对应于(IMAGE_THUNK_DATA32 *)
)。
To dump information from IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
(corresponds to (ImgDelayDescr *)
defined in delayimp.h) you should use also information from the IMAGE_DIRECTORY_ENTRY_IAT
(corresponds to (IMAGE_THUNK_DATA32 *)
).
有关PE的更多信息,我建议你http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
For more information about PE I recommend you http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
这篇关于解决PE文件中的RVA的导入和导出表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!