We have discussed the term RVA before, but it is especially strange and helpless for friends who are new to PE files. Chinese people do not like the abbreviations of foreigners, but they always ** accept ...... However, with the knowledge of the frontend, we should be able to talk about this concept. At least it doesn't seem so confusing and helpless ~
RVA is the abbreviation of relative virtual address. As its name suggests, RVA is a "relative address ". In the PE file, most of the data structures that contain addresses are indicated by RVA ??
More accurately, RVA is the offset of a Data Location relative to the file header when the PE file is loaded into the memory. For example, if the windows loader loads a PE file into the memory at 00400000 H, and a data in a block is loaded at 0040 ** XH, then the RVA of this data is (0040 ** XH-00400000 H) = ** XH. In other words, add the RVA value to the base address of the file to be loaded, you can find the actual address of the data in the memory.
The offset position and size of the DOS file header, PE file header, and block table remain unchanged. After each block is mapped to the memory, its offset position changes.
RVA makes it easy to locate the data after the file is loaded into the memory, but it makes trouble to locate the static PE file on the disk. Let's give an example :...... As the example is in the video, I won't write it if I try to get the time. Let's see the video demonstration.
How to convert the RVA and file offset?
When processing PE files, any RVA must be converted to a file offset before it can be used to locate and access the data in the file, but the conversion cannot be completed using a simple formula. In fact, the only available method is the most stupid one:
Step 1: scan the block table cyclically to obtain the starting RVA of each block in the memory (according to the virtualaddress field in image_section_header), and according to the block size (according to the sizeofrawdata field in image_section_header) calculate the end RVA of the block (the two can be added together), and determine whether the target RVA falls into the block.
Step 2: After the target RVA is in a specific block, use the target RVA to subtract the starting RVA from the block, in this way, the offset between the target RVA and the starting address rva2.
Step 3: Obtain the offset address of the block in the file in the block table (according to the pointertorawdata field in image_section_header) and add the offset value to the rva2 value obtained in step 2, the real file offset address is obtained.