WIN32汇编语言教程:第17章 PE文件 · 17.1 PE文件的结构(2)

17.1.3 PE文件头(NT文件头)

从DOS文件头的e_lfanew字段(文件头偏移003ch)得到真正的PE文件头位置后,现在来看看它的定义,PE文件头是由IMAGE_NT_HEADERS结构定义的:

IMAGE_NT_HEADERS STRUCT
	Signature          DWORD				?		;PE文件标识
	FileHeader         IMAGE_FILE_HEADER		<>	;★
	OptionalHeader     IMAGE_OPTIONAL_HEADER32	<>	;★
IMAGE_NT_HEADERS ENDS

PE文件头的第一个双字是一个标志,它被定义为00004550h,也就是字符“P”,“E”加上两个0,这也是“PE”这个称呼的由来,大部分的文件属性由标志后面的IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER32结构来定义,从名称看,似乎后面的这个PE文件表头结构是可选的(Optional),但实际上这个名称是名不符实的,因为它总是存在于每个PE文件中。

1. IMAGE_FILE_HEADER结构

IMAGE_FILE_HEADER结构的定义如下所示,字段后面的注释中标出了字段相对于PE文件头的偏移量,以供读者快速参考:

IMAGE_FILE_HEADER STRUCT
	Machine			WORD	?	;0004h - 运行平台★
	NumberOfSections		WORD	?	;0006h - 文件的节数目★
	TimeDateStamp			DWORD	?	;0008h - 文件创建日期和时间
	PointerToSymbolTable		DWORD	?	;000ch - 指向符号表(用于调试)
	NumberOfSymbols		DWORD	?	;0010h - 符号表中的符号数量(用于调试)
	SizeOfOptionalHeader		WORD	?	;0014h - IMAGE_OPTIONAL_HEADER32结构的长度★
	Characteristics		WORD	?	;0016h - 文件属性★
IMAGE_FILE_HEADER ENDS

几个关键字段的含义解释如下。

● Machine字段

用来指定文件的运行平台,常见的定义值见表17.1所示。Windows可以运行在Intel和SUN等几种不同的硬件平台上,不同平台指令的机器码是不同的,为不同平台编译的可执行文件显然无法通用。如果Windows检测到这个字段指定的适用平台与当前的硬件平台不兼容,它将拒绝装入这个文件。

表17.1 运行平台识别码的定义(更多定义参见Windows.inc文件)

Windows.inc中的预定义值16进制值说明
IMAGE_FILE_MACHINE_UNKNOWN0未知平台
IMAGE_FILE_MACHINE_I386014chIntel 386
暂无014dhIntel 486
暂无014ehIntel 586
暂无0160hR3000(大尾方式)
IMAGE_FILE_MACHINE_R30000162hR3000(小尾方式)
IMAGE_FILE_MACHINE_R40000166hR4000(小尾方式)
IMAGE_FILE_MACHINE_R100000168hR10000(小尾方式)
IMAGE_FILE_MACHINE_ALPHA0184hDec Alpha AXP
IMAGE_FILE_MACHINE_POWERPC01f0hIBM Power PC(小尾方式)
IMAGE_FILE_MACHINE_ALPHA640284hDec Alpha AXP64

● NumberOfSections字段

指出文件中存在的节的数量(如图17.1中的④所示),同样,节表的数量(如图17.1中的③所示)也等于节的数量。

● TimeDateStamp字段

编译器创建此文件的时间,它的数值是从1969年12月31日下午4:00开始到创建时间为止的总秒数。

● PointerToSymbolTable和NumberOfSymbols字段

这两个字段并不重要,它们与调试用的符号表有关。

● SizeOfOptionalHeader字段

紧接在当前结构下面的IMAGE_OPTIONAL_HEADER32结构的长度,这个值等于00e0h。

● Characteristics字段

属性标志字段,它的不同数据位定义了不同的文件属性,具体内容如表17.2所示,这是一个很重要的字段,不同的定义将影响系统对文件的装入方式,比如,当位13为1时,表示这是一个DLL文件,那么系统将使用调用DLL入口函数的方式调用文件入口,否则的话,表示这是一个普通的可执行文件,系统直接跳到入口处执行。对于普通的可执行PE文件,这个字段的值一般是010fh,而对于DLL文件来说,这个字段的值一般是210eh。

表17.2 属性位字段的含义

数据位Windows.inc中的预定义值为1时的含义
0IMAGE_FILE_RELOCS_STRIPPED文件中不存在重定位信息
1IMAGE_FILE_EXECUTABLE_IMAGE文件是可执行的
2IMAGE_FILE_LINE_NUMS_STRIPPED不存在行信息
3IMAGE_FILE_LOCAL_SYMS_STRIPPED不存在符号信息
7IMAGE_FILE_BYTES_REVERSED_LO小尾方式
8IMAGE_FILE_32BIT_MACHINE只在32位平台上运行
9IMAGE_FILE_DEBUG_STRIPPED不包含调试信息
10IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP不能从可移动盘(如软盘、光盘)运行
11IMAGE_FILE_NET_RUN_FROM_SWAP不能从网络运行
12IMAGE_FILE_SYSTEM系统文件(如驱动程序),不能直接运行
13IMAGE_FILE_DLL这是一个 DLL 文件
14IMAGE_FILE_UP_SYSTEM_ONLY文件不能在多处理器上计算机上运行
15IMAGE_FILE_BYTES_REVERSED_HI大尾方式

2. IMAGE_OPTIONAL_HEADER32结构

定义IMAGE_OPTIONAL_HEADER32结构的本意在于让不同的开发者能够在PE文件头中使用自定义的数据,这就是结构名称中“Optional”一词的由来,但实际上IMAGE_FILE_HEADER结构不足以用来定义PE文件的属性,反而在这个“可选”的部分中有着更多的定义数据,对于读者来说,可以完全不必考虑这两个结构的区别在哪里,只要把它们当成是连在一起的“PE文件头结构”就可以了。

IMAGE_OPTIONAL_HEADER32结构的定义如下,同样,字段后面的注释中标出了字段本身相对于PE文件头的偏移量:

IMAGE_OPTIONAL_HEADER32 STRUCT
	Magic					WORD	?	;0018h 107h=ROM Image,10Bh=exe Image
	MajorLinkerVersion			BYTE	?	;001ah 链接器版本号
	MinorLinkerVersion			BYTE	?	;001bh
	SizeOfCode				DWORD	?	;001ch 所有含代码的节的总大小
	SizeOfInitializedData		DWORD	? 	;0020h所有含已初始化数据的节的总大小
	SizeOfUninitializedData		DWORD	?	;0024h 所有含未初始化数据的节的大小
	AddressOfEntryPoint			DWORD	?	;0028h 程序执行入口RVA
	BaseOfCode				DWORD	?	;002ch 代码的节的起始RVA
	BaseOfData				DWORD	?	;0030h 数据的节的起始RVA
	ImageBase				DWORD	?	;0034h 程序的建议装载地址
	SectionAlignment			DWORD	?	;0038h 内存中的节的对齐粒度
	FileAlignment				DWORD	?	;003ch 文件中的节的对齐粒度
	MajorOperatingSystemVersion		WORD	?	;0040h 操作系统主版本号
	MinorOperatingSystemVersion		WORD	?	;0042h 操作系统副版本号
	MajorImageVersion			WORD	?	;0044h可运行于操作系统的最小版本号
	MinorImageVersion			WORD	?	;0046h
	MajorSubsystemVersion		WORD 	?	;0048h 可运行于操作系统的最小子版本号
	MinorSubsystemVersion		WORD	?	;004ah
	Win32VersionValue			DWORD	?	;004ch 未用
	SizeOfImage				DWORD	?	;0050h 内存中整个PE映像尺寸
	SizeOfHeaders				DWORD	?	;0054h 所有头+节表的大小
	CheckSum				DWORD	?	;0058h
	Subsystem				WORD	?	;005ch 文件的子系统
	DllCharacteristics			WORD	?	;005eh
	SizeOfStackReserve			DWORD	?	;0060h 初始化时的堆栈大小
	SizeOfStackCommit			DWORD	?	;0064h 初始化时实际提交的堆栈大小
	SizeOfHeapReserve			DWORD	?	;0068h 初始化时保留的堆大小
	SizeOfHeapCommit			DWORD	?	;006ch 初始化时实际提交的堆大小
	LoaderFlags				DWORD	?	;0070h 未用
	NumberOfRvaAndSizes			DWORD	?	;0074h 下面的数据目录结构的数量
	DataDirectory				IMAGE_DATA_DIRECTORY 16 dup(<>) ;0078h
IMAGE_OPTIONAL_HEADER32 ENDS

上页:第17章 PE文件 · 17.1 PE文件的结构(1) 下页:第17章 PE文件 · 17.1 PE文件的结构(3)

第17章 PE文件

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号