关于PE文件格式中IMAGE_OPTIONAL_HEADER.FileAlignment的一些说明
这个字段是在文件对齐时使用的.
例如FileAlignment = 0x1000, 有一个节真正有用的数据大小为0x400, 但是因为FileAlignment是0x1000, 所以连接器生成文件时, 该节的大小就是0x1000了. 这就是文件对齐.
看下面数据:
IMAGE_DOS_HEADER (Size: 0x0040H<64B>)
LONG e_lfanew; // 0x00005440
IMAGE_NT_HEADERS32 (Size: 0x00F8H<248B>)
IMAGE_FILE_HEADER (Size: 0x0014H<20B>)
.......
WORD NumberOfSections; // 0x0004
........
IMAGE_OPTIONAL_HEADER32 (Size: 0x00E0H<224B>)
.......
DWORD SectionAlignment; // 0x00001000
DWORD FileAlignment; // 0x00001000
.......
IMAGE_SECTION_HEADER (Count: 4) (Size: 0x0028H<40B>)(ROF: 0x00005538)
IMAGE_SECTION_HEADER[0]
BYTE Name[8]; // .text
DWORD Misc.PhysicalAddress/Misc.VirtualSize; // 0x000176E1
DWORD VirtualAddress; // 0x00006000
DWORD SizeOfRawData; // 0x00018000
DWORD PointerToRawData; // 0x00006000
DWORD PointerToRelocations; // 0x00000000
DWORD PointerToLinenumbers; // 0x00000000
WORD NumberOfRelocations; // 0x0000
WORD NumberOfLinenumbers; // 0x0000
DWORD Characteristics; // 0x60000020
........
IMAGE_DOS_HEADER + Stub + IMAGE_NT_HEADERS + IMAGE_SECTION_HEADER * 4
= 0x00005538 + 0x0028H * 4
= 0x000055D8 != 0x00006000
IMAGE_SECTION_HEADER * 4的后面就是节了, 但第一个节在文件的中位置是0x00006000
可以看到"IMAGE_DOS_HEADER + Stub + IMAGE_NT_HEADERS + IMAGE_SECTION_HEADER * 4 "这块数据也是要文件对齐的.
所以假设FileAlignment = 0x1000, 通常第一个节在文件中的位置也就是0x1000的(IMAGE_SECTION_HEADER[0].PointerToRawData), 知道为什么吗? 也是文件对齐的缘故.
因为IMAGE_DOS_HEADER + Stub + IMAGE_NT_HEADERS + IMAGE_SECTION_HEADER * n的大小比 0x1000 还小.
还引出了一个问题: 就是书上说的"节表结构后面加一个空的节表结构来代表节表的结束", 但是既然有IMAGE_FILE_HEADER.NumberOfSections, 你觉得还需要用一个空的节表结构来代表结束吗? 节表结构后面的0可能不是空节表结构, 而是因为文件对齐而补的0(经过验证, 我是对的, 看下面).
IMAGE_SECTION_HEADER (Count: 4) (Size: 0x0028H<40B>)(ROF: 0x00004F58)
IMAGE_SECTION_HEADER[0]
BYTE Name[8]; // .text
DWORD Misc.PhysicalAddress/Misc.VirtualSize; // 0x000176E1
DWORD VirtualAddress; // 0x00005000
DWORD SizeOfRawData; // 0x00018000
DWORD PointerToRawData; // 0x00005000
DWORD PointerToRelocations; // 0x00000000
有4个IMAGE_SECTION_HEADER 第一个在0x00004F58
而第一个节在0x00005000
0x00004F58 + * 0x0028H * 4 = 0x00004FF8(差8个byte就到0x00005000, 查看文件, 这8个byte是补0的).
如果是多一个空白IMAGE_SECTION_HEADER的话
0x00004F58 + * 0x0028H * 5 = 0x00005020(都超出第一个节的起始位置了0x00005000)
所以说节表结构后面的0不是空节表结构, 而是因为文件对齐而补的0