PE结构:VA&RVA&FOA转换复习

复习一下,不然会忘

1.imagebase 映像基地址 ,默认是0x400000

2.va 虚拟地址,载入OD后的地址,已经映射到内存的地址。

计算实际装入地址 VA imagebase (映像基址) + RVA(虚拟入口) =>

0x400000 + 0x5d485 = 0x45d485 载入 od 验证

节取虚拟地址范围区间: 虚拟地址开始位置: imagebase + .text节RVA => 0x400000 + 0x00001000 = 401000

虚拟地址结束位置:imagebase + .text节尺寸 => 401000 + 0x0007B0DE = 0x47C0DE .text节结束地址

od 验证 0x47c0de 在 0x47d000 之前,属于text节

虚拟地址RVA 对应到文件中的FOA位置: 以计算 0045D485 对应到文件中位置为例。

RVA(相对便宜) = VA - .text首地址 => 0045D485 - 401000 = 5C485

FOA(文件偏移) = RVA + .text节的文件偏移 0x00001000 = 5C485 + 1000 = 5D485

打开 winhex 验证真伪。

文件偏移转为RVA 计算文件偏移 5d480 对应到虚拟VA中的位置。

vpk = text节首地址 - imagebase - 实际偏移 = 401000 - 400000 - 1000 = 0

va = foa + imagebase + vpk = 5d480 + 400000 + 0 = 45d480

虚拟VA转文件偏移代码 读取代码如下.

import os
import pefile

def RVA_To_FOA(FilePath):
pe = pefile.PE(FilePath)
ImageBase = pe.OPTIONAL_HEADER.ImageBase

for item in pe.sections:
if str(item.Name.decode('UTF-8').strip(b'\x00'.decode())) == ".text":
#print("虚拟地址: 0x%.8X 虚拟大小: 0x%.8X" %(item.VirtualAddress,item.Misc_VirtualSize))
VirtualAddress = item.VirtualAddress
VirtualSize = item.Misc_VirtualSize
ActualOffset = item.PointerToRawData
StartVA = hex(ImageBase + VirtualAddress)
StopVA = hex(ImageBase + VirtualAddress + VirtualSize)
print("[+] 代码段起始地址: {} 结束: {} 实际偏移:{} 长度: {}".format(StartVA,StopVA,ActualOffset,VirtualSize))

with open(FilePath,"rb") as fp:
fp.seek(ActualOffset)
HexCode = fp.read(VirtualSize)
print(HexCode)

RVA_To_FOA("d://lyshark.exe")