PE节表属性

全局变量有无初始值的区别:

没有初始值:PE文件在文件中的状态的时候不会对该变量的地址进行存储,只有在内存中运行的时候的状态才会进行分配

有初始值:PE文件在文件中的状态的时候会对该变量的地址进行存储


VA:英文全称是Virual Address,简称VA,中文意思是虚拟地址,指的是文件被载入虚拟空间后的地址。

ImageBase:中文意思是基址,指的是程序在虚拟空间中被装载的位置。

RVA:相对虚拟地址,可以理解为文件被装载到虚拟空间(拉伸)后先对于基址的偏移地址。

它的对齐方式一般是以1000h为单位在虚拟空间中对齐的(传说中的4K对齐),具体对齐需要参照IMAGE_OPTIONAL_HEADER32中的SectionAlignment成员。

FOA:文件偏移地址。可以理解为文件在磁盘上存放时相对于文件开头的偏移地址。

它的对齐方式一般是以200h为单位在硬盘中对齐的(512对齐),具体对齐需要参照IMAGE_OPTIONAL_HEADER32中的FileAlignment成员。

计算方式:RVA = VA(虚拟地址) - ImageBase(基址)


RVA(相对虚拟地址)转换FOA(文件偏移地址)过程:

int a = 0x12345678;
int main() {
    printf("地址:%.8X\n",&a);
    printf("数值:%d\n",a);
    return 0; 
} 

运行结果:

D:\VC6EN\COMMON\MSDEV98\BIN\Debug>5.exe
地址:00424A30
数值:305419896

我们要求RVA,RVA = VA - ImageBase,VA虚拟地址为0x00424A30

那么 RVA = 424A30 - ImageBase

查看Imagebase:0x00400000

RVA = 424A30 - 400000 = 24A30

接下来寻址FOA,就要考虑文件对齐跟内存对齐不是一样的问题 所以我们要考虑是否对齐方式是一样的

第一种情况:如果文件对齐跟内存对齐一样,那么这样就可以直接去找


第二种情况:比如文件对齐和内存对齐不一样

我们需要判断RVA属于哪个节/头,这里也要分为两种情况!

1):如果RVA属于文件头部(DOS头 + PE头 + 节表)

那么不需要进行计算了,因为DOS头和PE头和节表在文件中和在内存中展开都是一样的,直接从开始位置寻找到RVA个字节即可,那么这里也就是24A30

2):如果RVA不在头,就要判断在哪个节里面

判断节开始位置到节结束位置 我们的RVA是否在这个范围里面 20890

RVA >= 指定节.VirtualAddress

RVA <= 指定节.VirtualAddress + 当前节内存对齐后的大小

差值 = RVA - 指定节.VirtualAddress + 当前节内存对齐后的大小

FOA = 指定节.PointerToRawData + 差值


FOA(文件偏移地址)转换RVA(相对虚拟地址)过程:

设FOA为节数据的任意一位置

1.计算差值偏移: FOA - 节.PointerToRawData(节数据在文件中开始的位置) == 差值偏移.

2.计算RVA: 差值偏移 + 节.VirtuallAddress(节数据在内存中展开的位置) == RVA

3.计算虚拟地址: RVA+ ImageBase == VA

需要注意的就是我们的 FOA 在哪一个节中. FOA <= 节.PointerToRawData + 节.SizeofRawData

猜你喜欢

转载自www.cnblogs.com/zpchcbd/p/12312370.html