This is fun! You have to loop through sections to find the correct location based on it's virtual address. Here is some code I wrote after a lot of
I can try to explain this, but it took a lot of time to understand it myself and I haven't looked at it in a few weeks and I already forgot a lot of the technical stuff. I was writing a C++ class to handle a lot of this too
In my code buffer is a pointer to a MapViewOfFile but it can be any char pointer.
/* Example usage...I know not perfect but should help a bit. */
unsigned char * lpFile = (unsigned char *)(void *)MapViewOfFile(fileMap, FILE_MAP_ALL_ACCESS, 0,0, 0);
if(lpFile==NULL) {
printf("Failed to MapViewOfFile\r\n");
exit(0);
}
header_dos = (PIMAGE_DOS_HEADER)lpFile;
header_nt = (PIMAGE_NT_HEADERS32)&lpFile [header_dos->e_lfanew];
IMAGE_DATA_DIRECTORY import = header_nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR im = (PIMAGE_IMPORT_DESCRIPTOR)&lpFile[RVA2Offset(lpFile, import.VirtualAddress)];
/* RVA is relative to the section it resides in. */
int RVA2Offset(unsigned char * buffer, DWORD rva)
{
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew ];
PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew + sizeof(IMAGE_NT_HEADERS) ];
for(int sectionIndex = 0; sectionIndex < header->FileHeader.NumberOfSections; sectionIndex++) {
/*
Check if the RVA is within the virtual addressing space of the section
Make sure the RVA is less than the VirtualAddress plus its raw data size
IMAGE_HEADER_SECTION.VirtualAddress = The address of the first byte of the section when loaded into memory, relative to the image base. For object files, this is the address of the first byte before relocation is applied.
Our ImageBase is 0, since we aren't loaded into actual memory
*/
section = (PIMAGE_SECTION_HEADER) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (sectionIndex*sizeof(IMAGE_SECTION_HEADER))];
if (rva >= section->VirtualAddress && (rva <= section->VirtualAddress + section->SizeOfRawData)) {
/**
PointerToRawData gives us the section's location within the file.
RVA - VirtualAddress = Offset WITHIN the address space
**/
return section->PointerToRawData + (rva - section->VirtualAddress);
}
}
return 0;
}