PE头部是真正用来装载Win32程序的头部,PE头的定义为IMAGE_NT_HEADERS,该结构体包含PE标识符、文件头与可选头这三部分。
该头部具有32位和64位之分。
32位的PE文件格式,IMAGE_NT_HEADERS32定义如下:
- typedef struct _IMAGE_NT_HEADERS {
- DWORD Signature; //位置在e_lfanew上
- IMAGE_FILE_HEADER FileHeader; //e_lfanew + 0x4 文件头结构体
- IMAGE_OPTIONAL_HEADER32 OptionalHeader; //e_lfanew + 0x18 可选头结构体
- } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
该结构体中的Signature就是PE标识符,该部分占四个字节,在Winnt.h头文件中的宏定义为:
- #define IMAGE_NT_SIGNATURE 0x50450000 // PE00
在PE头中,除了IMAGE_NT_HEADERS 以外,还有两个重要的结构体,分别是IMAGE_FILE_HEADER(文件头) 和 IMAGE_OPTIONAL_HEADER32(可选头)。
IMAGE_FILE_HEADER(文件头)
该结构体是IMAGE_NT_HEADERS中的第一个结构体,该结构体紧接在PE标识符的后面。该结构体大小为20个字节。
- typedef struct _IMAGE_FILE_HEADER {
- WORD Machine; //位置为 e_lfanew + 0x4 //该字段表示可执行文件的目标CPU类型
- WORD NumberOfSections; //e_lfanew + 0x6 //该字段表示PE文件的节区的个数
- DWORD TimeDateStamp; //e_lfanew + 0x8 //该字段表明文件时何时被创建的,这个值是自1970年1月1日以来用格林
- //威治时间计算的秒数
- DWORD PointerToSymbolTable; //e_lfanew + 0xC //
- DWORD NumberOfSymbols; //e_lfanew + 0x10 //
- WORD SizeOfOptionalHeader; //e_lfanew + 0x12 //该字段指定IMAGE_OPTIONAL_HEADER结构的大小
- WORD Characteristics; //e_lfanew + 0x14 //该字段指定文件的类型
- } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; //大小20字节
- //Machine字段取值
- // 宏定义 值 意义
- // IMAGE_FILE_MACHINE_I386 0x014c Intel
- // IMAGE_FILE_MACHINE_ALPHA 0x0184 DEC Alpha
- // IMAGE_FILE_MACHINE_IA64 0x0200 Intel(64 - bit)
- // IMAGE_FILE_MACHINE_AXP64 0x0284 DEC Alpha(64 - bit)
- //Characteristics字段取值
- // 宏定义 值 意义
- // IMAGE_FILE_RELOCS_STRIPPED 0x0001 文件中不存在重定位信息
- // IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 文件可执行
- // IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 行号信息已从文件中移除
- // IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 符号信息已从文件中移除
- // IMAGE_FILE_DLL 0x2000 DLL文件
- // IMAGE_FILE_SYSTEM 0x1000 系统文件
- // IMAGE_FILE_32BIT_MACHINE 0x0100 目标平台为32位平台
IMAGE_OPTIONAL_HEADER32(可选头)
- typedef struct _IMAGE_OPTIONAL_HEADER {
- WORD Magic; //位置为 e_lfanew + 0x18 //文件的状态类型
- BYTE MajorLinkerVersion; //e_lfanew + 0x1A //主链接版本号
- BYTE MinorLinkerVersion; //e_lfanew + 0x1B //次链接版本号
- DWORD SizeOfCode; //e_lfanew + 0x1C //代码节的大小
- DWORD SizeOfInitializedData; //e_lfanew + 0x20 //已初始化数据块的大小
- DWORD SizeOfUninitializedData; //e_lfanew + 0x24 //未初始化数据块的大小
- DWORD AddressOfEntryPoint; //e_lfanew + 0x28 //程序执行的入口,相对虚拟地址,简称EP
- DWORD BaseOfCode; //e_lfanew + 0x2C //代码段的起始相对虚拟地址
- DWORD BaseOfData; //e_lfanew + 0x30 //数据段的起始相对虚拟地址
- DWORD ImageBase; //e_lfanew + 0x34 //内存首选装载地址
- DWORD SectionAlignment //e_lfanew + 0x38 //节在内存中的对齐值
- DWORD FileAlignment //e_lfanew + 0x3C //节在文件中的对齐值
- WORD MajorOperatingSystemVersion; //e_lfanew + 0x40 //要求最低操作系统的主版本号
- WORD MinorOperatingSystemVersion; //e_lfanew + 0x42 //要求最低操作系统的次版本号
- WORD MajorImageVersion; //e_lfanew + 0x44 //可执行文件的主版本号
- WORD MinorImageVersion; //e_lfanew + 0x46 //可执行文件的次版本号
- WORD MajorSubsystemVersion; //e_lfanew + 0x48 //要求最低子系统的主版本号
- WORD MinorSubsystemVersion; //e_lfanew + 0x4A //要求最低子系统的次版本号
- DWORD Win32VersionValue; //e_lfanew + 0x4C //该成员变量是被保留的
- DWORD SizeOfImage; //e_lfanew + 0x50 //可执行文件装入内存后的总大小
- DWORD SizeOfHeader; //e_lfanew + 0x54 //PE头的大小,包括DOS头、PE头、节表的总和大小
- DWORD CheckSum; //e_lfanew + 0x58 //校验和
- WORD Subsystem; //e_lfanew + 0x5C //可执行文件的子系统类型
- WORD DllCharacteristics; //e_lfanew + 0x5E //指定DLL文件的属性,该值大部分时候为0
- DWORD SizeOfStackReserve; //e_lfanew + 0x60 //为线程保留的栈大小
- DWORD SizeOfStackCommit; //e_lfanew + 0x64 //为线程已经提交的栈大小
- DWORD SizeOfHeapReserve; //e_lfanew + 0x68 //为线程保留的堆大小
- DWORD SizeOfHeapCommit; //e_lfanew + 0x6C //为线程已经提交的堆大小
- DWORD LoaderFlags; //e_lfanew + 0x70 //被废弃的成员值
- DWORD NumberOfRvaandSizes; //e_lfanew + 0x74 //数据目录项的个数
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //e_lfanew + 0x78 //数据目录表
- //#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
- } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; //大小224字节
- //Magic取值
- // 宏定义 值 意义
- // IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b 可执行文件
- // IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 ROM文件
- //Subsystem取值
- // 宏定义 值 意义
- // IMAGE_SUBSYSTEM_UNKNOWN 0 未知子系统
- // IMAGE_SUBSYSTEM_NATIVE 1 不需要子系统
- // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 图形子系统
- // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 控制台子系统
- //IMAGE_DATA_DIRECTORY
- typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
- } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
- //取值
- // 宏定义 值 意义
- // IMAGE_DIRECTORY_ENTRY_EXPORT 0 导出表在数组中的索引
- // IMAGE_DIRECTORY_ENTRY_IMPORT 1 导入表在数组中的索引
- // IMAGE_DIRECTORY_ENTRY_RESOURCE 2 资源在数组中的索引
- // IMAGE_DIRECTORY_ENTRY_BASERELOC 5 重定位表在数组中的索引
- // IMAGE_DIRECTORY_ENTRY_IAT 12 导入地址表在数组中的索引
IMAGE_SECTION_HEADER(节区详解)
- typedef struct _IMAGE_SECTION_HEADER { //第一个节区,每个节区依次往后推40字节即可
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //位置为 e_lfanew + 0xF8 //保存节的名称
- union {
- DWORD PhysicalAddress; //e_lfanew + 0x100 //
- DWORD VirtualSize; //e_lfanew + 0x104 //数据实际的节区大小
- } Misc;
- DWORD VirtualAddress; //e_lfanew + 0x108 //该节区载入到内存后的相对虚拟地址
- DWORD SizeOfRawData; //e_lfanew + 0x10C //该节区在磁盘上的大小
- DWORD PointerToRawData; //e_lfanew + 0x110 //该节区在磁盘文件上的偏移值
- DWORD PointerToRelocations; //e_lfanew + 0x114
- DWORD PointerToLinenumbers; //e_lfanew + 0x118
- WORD NumberOfRelocations; //e_lfanew + 0x11C
- WORD NumberOfLinenumbers; //e_lfanew + 0x11E
- DWORD Characteristics; //e_lfanew + 0x120 //节区属性
- } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; //该数据结构大小为40字节
- //Characteristics(节区属性)取值
- // 宏定义 值 意义
- // IMAGE_SCN_CNT_CODE 0x00000020 该节区含代码
- // IMAGE_SCN_MEM_SHARED 0x10000000 该节区为可共享
- // IMAGE_SCN_MEM_EXECUTE 0x20000000 该节区为可执行
- // IMAGE_SCN_MEM_READ 0x40000000 该节区为可读
- // IMAGE_SCN_MEM_WRITE 0x80000000 该节区为可写