PE文件格式(区块)
节区头定义了各节区的属性
节区头是由IMAGE_SECTION_HEADER结构体组成的数组,每个结构体对应一个节区
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // Name,为对应节区的名字,IMAGE_SIZEOF_SHORT_NAME的值固定为8。如名字的长度小于8,以NULL字符结束;名字的长度等于8,则没有NULL字符,因为数组长度为8。节区的名字通常以点号开头,通常而言,这个名字可以随便修改
union {
DWORD PhysicalAddress;
DWORD VirtualSize; // 在未对齐的情况下,区块所有数据的大小
} Misc;
DWORD VirtualAddress; // 区块被装载到内存时的RVA,这个值总是SectionAlignment的整数倍
DWORD SizeOfRawData; // 区块数据在磁盘文件中按照FileAlignment对齐后的大小
DWORD PointerToRawData; // 区块数据在磁盘文件中的偏移地址
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; // 区块的属性值,表明区块的可读、可写、可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
IMAGE_SECTION_HEADER结构体占用40字节,下图是节表头文件偏移值:0x1E8
节区的大小是需要进行对齐处理的,而且在文件中的对齐值与在内存中的对齐值是不一样的,在IMAGE_NT_HEADERS的OptionalHeader中指明了这两个值(FileAlignment和SectionAlignment)
节区的起始地址总是进行对齐后的值
下图中可以看到PE文件节区的数目为5,文件对齐值为0x200,节区(内存)对齐值为0x1000
上面已经计算出了节表头的文件偏移值为0x1E8,而且知道每个节表头的大小为40字节,那么5个节表头的大小就是200字节,因此可以计算出节表头结束的偏移值为:
0x1E8 + 40 × 5 = 0x2B0
区块中的数据逻辑通常是关联的。PE文件一般至少有两个区块,一个是代码块,另一个是数据块。每个块都有特定的名字,这个名字用于表示区块的用途
RVA(相对虚拟地址),相对于PE文件载入地址的偏移地址
相对虚拟地址(RVA)= 虚拟地址(VA)- 基址(ImageBase)
RAW = RVA - VirtualAddress + PointerToRawData
RVA = 1100,File Offset = ?
1100位于第一个节区(.text)
RAW = 1100(RVA)- 1000(VirtualAddress)+ 400(PointerToRawData)= 500
为了更容易理解,写一个程序,把随机基址关掉
RVA = 0x403018 – 0x400000 = 0x3018
File Offset = 0x3018 – 0x3000+0x1E00 = 0x1E18
congtou