
Portable Executable: Converting RVA to File Offset and Back
Introduction
Most fields in a Portable Executable (.exe) file that refer to a location in memory use a so-called Relative Virtual Address (RVA). This is useful because it allows the Windows loader to load the executable in any virtual memory location, without having to change every pointer in the executable. The RVA is relative to the Load Base Address, which is the location where the first byte of the executable is loaded into memory. A virtual address
refers to a location in memory, whereas a file offset
refers to a location in an executable file on physical storage.
The goal is to convert between these values:
- (Relative) Virtual Address: a location in virtual memory
- File offset: a location in a file on physical storage
How it Works
When an executable is loaded into memory it is not copied byte for byte from disk. What happens is a process called aligning: the sections in a PE file are spaced so they all start on the first byte of a memory page (usually 4096 bytes on x86 systems). This can introduce padding at the end of sections. Because of this effect, among other things, we cannot translate directly between RVA and file offset.
-
- An overview of information contained in the IMAGE_SECTION_HEADER.
Luckily, the PE file header contains a structure called IMAGE_SECTION_HEADER
that allows us to make the translation. Since we can deduce the virtual memory layout from the this header, we can trace back the RVA to the PE section that resides at that address. Once we know the name of the PE section–and the offset into that section– we can find the file offset.
Of course, we can also reverse the process to find the a file offset’s corresponding RVA.
Example: RVA to File Offset
Let’s assume we have a RVA 0x11B4
for this example.
1. Find out which section the RVA belongs to.
- The section
.text
starts at virtual offset0x1000
. Virtual offset is a synonym for RVA. - A virtual size of
0x24C
, meaning the in-memory size in bytes, means the section ends at0x1000+0x24C = 0x124C
. - Our example RVA
0x11B4
is between0x1000
and0x124C
, so it belongs to the.text
section.
2. Subtract the virtual offset of the section from the RVA. This gives an offset relative to the .text section, instead of relative to the Load Base Address.
0x11B4 - 0x1000 = 0x1B4
3. Add the location of the .text section in the file to the offset for our final answer. The section offsets in the file are in the Raw Offset field.
0x1B4 + 0x400 = 0x5B4
So: the RVA 0x11B4
is equivalent to file offset 0x5B4
. This formula summarizes the calculation.
File Offset = RVA - Section Virtual Offset + Section Raw Offset
Useful Programs
I suggest using a program like dumpbin or LordPE to help you analyze PE files. Most of these programs have a feature for translating between the offsets.
-
- The location calculator of LordPE.
Credits for some parts of this text go to Sunshine2k for his tutorial.
hello and thank you so much for this tutorial but i have a note on this subject first of all the method that you explained i think is true but in real life only this equitation can do the job
Virtual Address – Image Base
Yes i know that everyone agree with you but if we use for example ollydbg we can see in the command bar when we select an instruction something like this
0040B967–>0040B968 : … | OFFEST:0000B967->0000B968
so to double check this if we open the program with a hex editor and press ctrl+G and type B967 we will notice the same opecode at it is in the RVA so i hope that you have an answer for this and again thank you so much
While that might be true for the first section of a PE executable, it is an oversimplification. The spacing between subsequent sections is changed (usually increased) when the PE file is loaded into memory, so you will see that your formula does not hold true for locations in subsequent sections.