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.
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
.textstarts at virtual offset
0x1000. Virtual offset is a synonym for RVA.
- A virtual size of
0x24C, meaning the in-memory size in bytes, means the section ends at
0x1000+0x24C = 0x124C.
- Our example RVA
0x124C, so it belongs to the
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
Credits for some parts of this text go to Sunshine2k for his tutorial.