DOS块的后面接着就是NT头了。NT头(NT Header)是PE文件中的一个数据结构,用于描述可执行文件的详细信息和布局。它位于PE文件的DOS头之后,紧接着DOS Stub,如图3-6所示。NT头是用于现代Windows操作系统的可执行文件格式的关键部分。NT头包含了PE文件的各种信息,包括文件的签名、文件头和扩展头。
■IMAGE_NT_HEADERS结构
NT头的结构可以通过一个名为IMAGE_NT_HEADERS的结构体来表示。我们在winnt.h头文件中搜索到这个结构体的定义如下:
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature; //PE文件的签名(PE特征码)
IMAGE_FILE_HEADER FileHeader; //文件头
IMAGE_OPTIONAL_HEADER64 OptionalHeader; //64位PE文件扩展头
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //PE文件的签名(PE特征码)
IMAGE_FILE_HEADER FileHeader; //文件头
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //32位PE文件扩展头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
我们发现有两个NT头结构的定义,一个是32位PE文件,另一个是64位PE文件。稍后我们将详细讲解它们的区别。
图3-6 PE文件结构
【注】块表为节表的同义词。
■PE特征码(签名)
文件的签名由Signature字段表示,它是一个4个字节的固定标识,用于表示该文件是一个PE文件。在32位的PE文件中,Signature的值为0x00004550(或者ASCII字符"PE\0\0"),在64位的PE文件中,Signature的值同样为0x00004550(或者ASCII字符"PE\0\0")。
特征码是一个固定的标识值,用于告知操作系统或其他工具,该文件遵循PE文件格式的规范,并提供了正确的结构和布局信息。操作系统在加载和解析PE文件时,会首先检查特征码,以确认文件是否为有效的PE文件。
特征码的位置在PE文件的NT头中,可以通过IMAGE_NT_HEADERS结构体中的Signature字段来访问。
■文件头(COFF文件标头)
在PE文件的开头,或紧接在映像文件签名之后,是以下格式的标准 COFF 文件头(20个字节)。 请注意,Windows 加载器将节区数限制为 96。
文件头(FileHeader)字段描述了文件的基本属性和布局,包括文件的机器架构、节表的数量和大小等信息。它是一个IMAGE_FILE_HEADER结构体,包含了各种字段,如Machine、NumberOfSections、SizeOfOptionalHeader等。我们在winnt.h头文件中搜索到文件头结构体的定义如下:
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; // CPU架构类型
WORD NumberOfSections; // 节区数量
DWORD TimeDateStamp; // 文件创建时间戳
DWORD PointerToSymbolTable; // COFF符号表偏移地址
DWORD NumberOfSymbols; // COFF符号表条目数量
WORD SizeOfOptionalHeader; // 可选头的大小
WORD Characteristics;// 文件属性标志
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Offset |
大小 |
字段 |
说明 |
0 |
2 |
设备 |
标识目标计算机类型的数字。 有关详细信息,请参阅MSDN目标计算机类型。 |
2 |
2 |
NumberOfSections |
节区数目。 这指示节表的大小,该表紧跟在PE头之后。 |
4 |
4 |
TimeDateStamp |
自 1970 年 1 月 1 日 00:00 起的秒数的低 32 位(C 运行时 time_t 值),指示文件的创建时间。 |
8 |
4 |
PointerToSymbolTable |
COFF 符号表的文件偏移量;如果没有 COFF 符号表,则为零。 映像文件的此值应为零,因为 COFF 调试信息已被弃用。 |
12 |
4 |