关于PE文件格式中IMAGE_OPTIONAL_HEADER.FileAlignment的一些说明

来源:互联网 发布:java链接oracle数据库 编辑:程序博客网 时间:2024/05/01 06:53

关于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

 

原创粉丝点击