Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
269 views
in Technique[技术] by (71.8m points)

c++ - Resolving RVA's for Import and Export tables within a PE file

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)));

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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);

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

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 greater or equal to 0 and less then pNtHdr->FileHeader.NumberOfSections where

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

and at the same time

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

then you should search for export data in the section 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);

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).

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 *)).

For more information about PE I recommend you http://msdn.microsoft.com/en-us/magazine/cc301808.aspx


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...