I'm trying to read a PE file.
The problems is that the data uses RVA pointers while I need offset within the file
to get what I need.
How can I convert the RVA to offset in the file?
An RVA ("relative virtual offset") is used to describe a memory offset if the base address is unknown. So it's not the same like a file offset! If you have the section table it's easy to calculate a file offset from a RVA.
A description of a field that indicates that the value of the field must be zero for generators and consumers must ignore the field. Relative virtual address (RVA) In an image file, this is the address of an item after it is loaded into memory, with the base address of the image file subtracted from it.
RVA = virtual address – base address (starting address in the memory) The address of the entry point is the address where the PE loader will begin execution; this is the address that is relative to image base when the executable is loaded into memory.
The file offset is actually a location within that particular file. To make it easier for you to understand it is actually the distance from the starting point either the start of the file or the start of a memory address. The offset value is added to the base value to determine the actual value.
To determine the file offset by RVA, you need:
You will receive a file offset that you need.
Below example gives file offset of address of entry point from RVA. One can pass any pointer to get its disk offset from RVA.
Basically we need to find in which section the address belongs. Once the correct section is identified use below formula to get offset.
DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
(sectionHeader->PointerToRawData);
then add file base address to get physical address
retAddr+(PBYTE)lpFileBase
LPCSTR fileName="exe_file_to_parse";
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS peHeader;
PIMAGE_SECTION_HEADER sectionHeader;
hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("\n CreateFile failed in read mode \n");
return 1;
}
hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(hFileMapping==0)
{
printf("\n CreateFileMapping failed \n");
CloseHandle(hFile);
return 1;
}
lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0); // Base pointer to file
if(lpFileBase==0)
{
printf("\n MapViewOfFile failed \n");
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 1;
}
dosHeader = (PIMAGE_DOS_HEADER) lpFileBase; //pointer to dos headers
if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
{
//if it is executable file print different fileds of structure
//dosHeader->e_lfanew : RVA for PE Header
printf("\n DOS Signature (MZ) Matched");
//pointer to PE/NT header
peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
if(peHeader->Signature==IMAGE_NT_SIGNATURE)
{
printf("\n PE Signature (PE) Matched \n");
// valid executable so we can proceed
//address of entry point
DWORD ptr = peHeader->OptionalHeader.AddressOfEntryPoint;
//instead of AEP send any pointer to get actual disk offset of it
printf("\n RVA : %x \n",ptr); // this is in memory address i.e. RVA
//suppose any one wants to know actual disk offset of "address of entry point" (AEP)
sectionHeader = IMAGE_FIRST_SECTION(peHeader); //first section address
UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
UINT i=0;
//check in which section the address belongs
for( i=0; i<=nSectionCount; ++i, ++sectionHeader )
{
if((sectionHeader->VirtualAddress) > ptr)
{
sectionHeader--;
break;
}
}
if(i>nSectionCount)
{
sectionHeader = IMAGE_FIRST_SECTION(peHeader);
UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
for(i=0; i<nSectionCount-1; ++i,++sectionHeader);
}
//once the correct section is found below formula gives the actual disk offset
DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
(sectionHeader->PointerToRawData);
printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase);
// retAddr+(PBYTE)lpFileBase contains the actual disk offset of address of entry point
}
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
//getchar();
return 0;
}
else
{
printf("\n DOS Signature (MZ) Not Matched \n");
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 1;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With