PE文件内名存实亡的对齐

大家知道PE文件中IMAGE_NT_HEADERS的IMAGE_OPTIONAL_HEADER32里有两个对其因子SectionAlignment和FileAlignment分别表示内存中块的对齐和文件中块的对齐。我同时翻阅了Visual Studio, Microsoft Portable Executable and Common Object File Format Specification Revision 8.0 - May 16, 2006英文原版以及各种中文版的PE文件格式解析(其中包括《加密与解密》),发现描述Section时特别指出块的PointerToRawData和SizeOfRawData必须遵循FileAlignment(即必须是对齐因子的整数倍),而VirtualAddress必须遵循SectionAlignment,同时两个对齐因子必须都是2的整数次幂,且FileAlignment必须小于等于SectionAlignment。
对于此点,各色文档参差不齐,例如英文文档中没有强调VirtualAddress的对齐,而《加密与解密》中没有强调PointerToRawData的对齐。众说风云,姑且先放一下,我用LordPE+Win2k(SP4)作了一系列的试验来验证对齐问题。

首先必须研究一下section(有人译成节,本人将其译成块,在下文中不再解释)。
可执行文件中,块有4个主要参数和2个参考参数,分别为:
4个主要参数:
PointerToRawData(在LordPE中为ROffset)表示块在文件中开始的偏移
SizeOfRawData(在LordPE中为RSize)表示块在文件中对齐后的大小
VirtualAddress(在LordPE中为VOffset)表示块在内存中的RVA(相对虚拟地址)
VirtualSize(在LordPE中为VSize)表示块从文件映射到内存时实际需要映射的大小(也就是对齐前实际使用了的大小)
特别的,英文文档指出当VirtualSize > SizeOfRawData时表示块内数据全部是0,通常下VirtualSize <= SizeOfRawData。
由此看来英文文档中的对齐要求不无理由,除VirtualSize和块实际存储信息有关(可能是代码多少,数据多少),其它三项都要求对齐。
2个参考参数:
分别是BYTE name[8];块名字,详细参见英文文档和Characteristics表示块的属性(可执行?保存已初始化数据?等等)
还有一些和调试相关的参数详细参见英文文档。

既然对齐如此必要,那么理应严格遵循,但是试验结果令人大吃一惊。
FileAlignment使用了win2k\system32\notepad.exe作为试验对象。
Notepad.exe的块表:
name  VOffset    VSize    ROffset    RSize    Flags
.text  00001000  0000654A  00000600  00006600  60000020
.data  00008000  00001944  00006C00  00000600  C0000040
.rsrc  0000A000  00005238  00007200  00005400  40000040

FileAlignment : 200h  SectionAlignment : 1000h    运行结果:ok
FileAlignment : 400h  SectionAlignment : 1000h    运行结果:ok
FileAlignment : 600h  SectionAlignment : 1000h    运行结果:错误,原因:600h不是2的整数次幂
FileAlignment : 800h  SectionAlignment : 1000h    运行结果:ok
FileAlignment : 1000h  SectionAlignment : 1000h    运行结果:ok
FileAlignment : 2000h  SectionAlignment : 1000h    运行结果:错误,原因:FileAlignment > SectionAlignment

可见FileAlignment并没有严格遵循对齐原则。
而SectionAlignment是严格遵循的,因为它关系到SizeOfImage,EntryPoint等与RVA和VA相关的所有内容。

最后的结果大出所料但又在情理之中,文件中FileAlignment没有严格遵循对齐原则,因为在映射到内存时地址会重新改写,只要内容上没有问题,映射后与映像文件对齐没有关系。但是SectionAlignment却要严格遵循,因为映射到内存后诸多寻址与其息息相关。
PELoader和我们玩了一个游戏,只要EXE能够执行,不必细究那些次要因素带来的影响。
当然这些推断只是基于本环境(win2k+sp4),其它系统上不敢妄言,由于看不到系统PELoader的代码实现,所以这些只是表象的推测而已,更待高手指点迷津。

附件中带有win2k下的notepad,英文版的文档。

  • 标 题:答复
  • 作 者:linxer
  • 时 间:2007-06-24 00:03

ROffset可以不对齐,这个时候会在load的时按FileAlignment向下对齐
VSize的大小只是效验下是否跨越下一个节了,或者是否超出了SizeOfImage,如果出现越界问题,提示非法32位应用程序,否则的话,它的值没有意义,节的大小不是由它决定的......对非最后一个节,按节间VOffset之差,最后一节用SizeOfImage-VOffset

  • 标 题:答复
  • 作 者:linxer
  • 时 间:2007-06-27 21:31

不管VirtualSize和SizeOfRawData的关系怎么样,貌似都是从磁盘上读取SizeOfRawData大小数据填充该节的头部,剩下的空间全填充0