一.简介(我以滴水逆向的说法为标准)
首先PE文件包含以下部分:
1.DOS头 2.PE文件头 3.节表(也称节区头) 4.节数据(也称节区)
1和2可以看做PE的头,3和4看做PE的体
细分PE文件头,
扩展PE头包含了一些数据类型,其中
DWORD ImageBase;
决定了文件的优先装入地址,即决定了PE文件在内存中展开的地址
在扩展PE头尾部定义了一个结构体数组,包含16个类似如下的结构体
typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; // 数据表的起始虚拟地址 DWORD Size; // 数据表大小 }IMAGE_DATA_DIRECTORY,*IMAGE_DATA_DIRECTORY
分别是 导出表、导入表、资源表、异常处理表、安全表、重定位表、调试表、版权、指针目录、TLS、载入配置、绑定输入目录、导入地址表、延迟载入、COM信息
二、对齐
PE文件在磁盘和内存中存储形式略有不同
1.首先PE的头部分(包括DOS头和PE文件头)存储区间的大小是不变的
2.变的是PE的体部分,在磁盘和内存中对齐的大小不同(一般磁盘以200h单位对齐,内存以1000h为对齐单位)
在扩展PE头中
DWORD SectionAligment;
DWORD FileAlignment;
SectionAlignment决定了节区在内存的最小单位,即对齐的大小
FileAlignment则决定了节区在磁盘上的最小对齐单位
虽然对齐大小不同,但是我们还是能够定位数据相对于节数据起始地址的位置,因为相对位置不管在磁盘还是内存上都是一样的,多出来的只是拿0填充的NULL值
在节表中定义了
DWORD VirtualAddress;
DWORD PointerToRawData;
VirtualAddress简写VA,表示节区在内存的起始地址,注意不要和ImageBase搞混,这只是每个节区的起始地址,节区的成员有很多,PointerToRawData表示节区在硬盘的起始地址
因此可得公式:
RAW(FOA,即文件偏移地址)- PointerToRawData = RVA(相对节区开头的偏移地址)- VA
两者的差值是一定相等的