MZ格式的文件头IMAGE_DOS_HEADER结构定义:

IMAGE_DOS_HEADER      STRUCT

       e_magic                     word             ?            ;DOS可执行文件标记,为“MZ

       e_cblp                 word             ?           

       e_cp                     word             ?

       e_crlc                   word             ?

       e_cparhdr            word             ?

       e_minalloc          word             ?

       e_maxalloc          word             ?

       e_ss                            word             ?DOS代码的初始化堆栈段

       e_sp                     word             ?DOS代码初始化堆栈指针

       e_csum                word             ?

       e_ip                            word             ?DOS代码的入口IP

       e_cs                            word             ?DOS代码的入口CS

       e_lfarlc                word             ?

       e_ovno                word             ?

       e_res                    word             ?

       e_oemid              word             ?

       e_oeminfo          word             ?

       e_res2                  word             10 dup (?)

       e_lfanew             dword          ?;指向PE文件头(总是以8字节为单位对齐的)

IMAGE_DOS_HEADER      ENDS

如果是LELX等格式文件,那么e_lfanew字段指向的位置回事LE文件头和LX文件头

 

那么也就是说从3ch位置找到一个双字节,这个双字节指向PE文件头的偏移

 

PE文件头IMAGE_NT_HEADERS结构:

IMAGE_NT_HEADERS       STRUCT

       Signature                   dword          ?;PE文件标识,通常为00004550hP,’E’

       FileHeader                 IMAGE_FILE_HEADER              <>

       OptionalHeader        IMAGE_OPTIONAL_HEADER32      <>

IMAGE_NT_HEADERS       ENDS

 

IMAGE_FILE_HEADER结构:

IMAGE_FILE_HEADER       STRUCT

       Machine                                  word             ?4h-支持平台

       NumberOfSections                 word             ?6h-文件的节数目

       TimeDateStamp                      dword          ?8h-文件创建日期和时间

PointerToSymbolTable            dword          ?0ch-指向符号表(用于调试)

NumberOfSysbols                   dword          ?10h-符号表中符号数量

SizeOfOptionalHeader           word             ?14h-IMAGE_OPTIONAL_HEADER32结构的长度

Characteristics                         word             ?16h-文件属性

IMAGE_FILE_HEADER       ENDS

 

IMAGE_OPTIONAL_HEADER32结构:

IMAGE_OPTIONAL_HEADER32      STRUCT

       Magic                                       dword   ?18h-107h=ROM Image10Bh=exe Image

       MajorLinkerVersion                byte       ?1ah-连接器版本号

       MinorLinkerVersion                byte       ?1bh

       SizeOfCode                              dword   ?;1ch-所有含代码的节总大小

       SizeOfInitializedData                     dword   ?;20h-所有含已初始化数据的节总大小

       SizeOfUninitializedData         dword   ?;24h-所有含为初始化数据的节总大小

       AddressOfEntryPoint                     dword   ?;28h-代码执行入口RVA

       BaseOfCode                                   dword   ?;2ch-代码的节的起始RVA

       BaseOfData                             dword   ?;30h-数据的节的起始RVA

       ImageBase                               dword   ?;34h-程序建议装载地址

       SectionAlignment                   dword   ?;38h-内存中的节对齐粒度

       FileAlignment                          dword   ?;3ch-文件中的节对齐粒度

       MajorOperatingSystemVersion    word      ?;40h-操作系统主版本号

       MinorOperatingSystemVersion    word      ?;42h-操作系统副版本号

       MajorImageVersion                word      ?;44h-可运行与操作系统的最小版本号

       MinorImageVersion                word      ?;46h

       MajorSubsystemVersion        word      ?;48h-可运行于操作系统的最小子版本号

       MinorSubsystemVersion        word      ?;4ah

       Win32VersionValue                dword   ?;4ch-未用

       SizeOfImage                            dword   ?;50h-内存中整个PE映像尺寸

       SizeOfHeader                          dword   ?;54h-所有头+节表的大小

       CheckSum                               dword   ?;58h

       Subsystem                               word      ?;5ch-文件的子系统

       DllCharacteristics                    word      ?;5eh

       SizeOfStackReserve                dword   ?;60h-初始化时堆栈大小

       SizeOfStackCommit                dword   ?;64h-初始化时实际提交的堆栈大小

       SizeOfHeapReserve                dword   ?;68h-初始化时保留的堆大小

       SizeOfHeapCommit                dword   ?;6ch-初始化时实际提交的堆大小

       LoaderFlags                             dword   ?;70h-未用

       NumberOfRvaAndSizes          dword   ?;74h-下面的数据目录结构的数量

DataDirectory     IMAGE_DATA_DIRECTORY 16 dup(<>)78h

IMAGE_OPTIONAL_HEADER32      ENDS

 

对于每个文件总是使用独立的虚拟地址空间,优先装入地址不可能被其他模块占据,所以exe总是能够按照ImageBase地址装入,但是对于DLL文件来说,由于多个DLL文件全部使用宿主exe文件的地址空间,不能保证优先装入地址没有被其他DLL使用,所以DLL文件中必须包含重定位信息以防万一。

 

IMAGE_DATA_DIRECTORY结构体:

IMAGE_DATA_DIRECTORY      STRUCTS

       VirtualAddress          dword                 ?;数据的起始RVA

       Isize                            dword                 ?;数据块的长度

IMAGE_DATA_DIRECTORY      ENDS

 

Windows装载器在装载DOS部分、PE文件头部分和节表部分时不做任何处理,而装载节的时候根据节的属性做不同的处理:

内存页的属性——对于磁盘映射文件来说,所有的页都是按照磁盘映射文件函数制定的属性设置的,但是装载可执行文件时,与节对应的内存页的属性要按照节的属性来设置,所以在同一个模块的内存页中,从不同节映射过来的内存页的属性是不同的。

 

节的偏移地址——节的其实地址在磁盘文件中按照IMAGE_OPTIONAL_HEADER32结构的FileAlignment字段对齐的,而被装载到内存中时是按照同一结构中的SectionAlignment对齐的,两者的值可能不同,所以一个节被装入内存后相对于文件头的偏移在磁盘文件中的偏移可能是不同的。节是相同属性数据的组合,当节被装载到内存中的时候,同一个节对应的内存页将被赋予相同的页属性,Windows系统对内存属性的设置是已页尾单位进行的,所以在节内存中的对齐单位必须至少是一个页的大小,对于Win32而言就是4KB,而Win64就是8KB。节在磁盘文件中对齐单位就没有最小4KB的限制,为了减少磁盘文件的大小,文件对齐的单位一般要小于内存的单位,通常为200h,这样,磁盘文件中就不必为每个节最后的零头不足4KB大小了。

 

节的尺寸——对节的处理有两个方面,首先是由于磁盘映像和内存映像中节对齐单位的不同而造成的长度扩展;其次是对包含为未始化数据的节的处理,对于未初始化数据来说(比如.data?),没有必要为他们在磁盘文件中预留空间,只要在可执行文件被装载到内存中后卫他们分配空间就可以了,所以包含未初始化数据节的磁盘文件中长度被定义为0,但是被装载到内存中的地址和大小是被明确指定的。对于这种节来说,它所包含的内存页没有磁盘文件与之对应,这些内存页是Windows装载器根据节的定义开辟出来的。

 

不进行映射的节——有些节中包含的数据仅仅在装载的时候用到,当装载完毕的时候,他们不会被递交物理内存页。最典型的是重定位数据的节,重定位数据对于文件的执行代码是透明的,它只提供Windows装载器使用,执行代码根本不会去访问他们,一旦装载完毕,继续为他们提供内存页是一种浪费,所以这些节存在于磁盘文件中,但不会被映射到内存中。