首先放一张pe文件结构图
在这里插入图片描述

pe文件结构大致分为以下几个部分
在这里插入图片描述

DOS头是用来兼容MS-DOS操作系统的
NT头包含windows PE文件的主要信息
节表:是PE文件后续节的描述
节:每个节实际上是一个容器,可以包含代码、数据等等,每个节可以有独立的内存权限,比如代码节默认有读/执行权限,节的名字和数量可以自己定义。
在学习pe文件结构中,熟悉文件结构图非常重要,下面我们就来一起学习一下。

DOS头

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
WORD   e_magic;                     // 一个WORD类型,值是一个常数0x4D5A,用文本编辑器查看该值位‘MZ’,可执行文件必须都是’MZ’开头。
WORD   e_cblp;                      
WORD   e_cp;                        
WORD   e_crlc;                      
WORD   e_cparhdr;                
WORD   e_minalloc;                  
WORD   e_maxalloc;                
WORD   e_ss;                      
WORD   e_sp;                      
WORD   e_csum;                
WORD   e_ip;                        
WORD   e_cs;                        
WORD   e_lfarlc;                
WORD   e_ovno;                
WORD   e_res[4];      
WORD   e_oemid;                  
WORD   e_oeminfo;                  
WORD   e_res2[10];                
LONG   e_lfanew;                    //Offset to start of PE header 指向PE文件头
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

PE文件头

IMAGE_NT_HEADERS STRUCT
DWORD Signature PE文件标识
IMAGE_FILE_HEADER FileHeader pe标准文件头
IMAGE_OPTIONAL_HEADER32 OptionalHeader
IMAGE_NT_HEADERS ENDS

pe标准文件头

typedef struct_IMAGE_FILE_HEADER{
WORD Machine; //可以运行在什么cpu上,任意: 0 Intel 386以及后续: 14C x86: 8864
WORD NumberOfSections; //表示节的数量(一共有多少个节)
DWORD TimeDataStamp; //编写器填写的时间戳 与文件属性里面(创建时间、修改时间)无关
DWORD PointerToSymbolTable //调试相关
DWORD PointerOfSymbols; //调试相关
WORD SizeOfOptionalHeader //可选PE头的大小(32位PE文件; 0xE0 64位PE文件: 0xF0)
WORD Characteristics; //文件属性
}IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

pe可选文件头

//32位的可选pe头长度为E0, 64位的可选pe头长度为F0

WORD Magic; * 说明文件类型:10B 32位下的PE文件 20B 64位下的PE文件
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;* 所有代码节的和,必须是FileAlignment的整数倍 编译器填的 没用
DWORD SizeOfInitializedData;* 已初始化数据大小的和,必须是FileAlignment的整数倍 编译器填的 没用
DWORD SizeOfUninitializedData;* 未初始化数据大小的和,必须是FileAlignment的整数倍 编译器填的 没用
DWORD AddressOfEntryPoint;* 程序入口
DWORD BaseOfCode;* 代码开始的基址,编译器填的 没用
DWORD BaseOfData;* 数据开始的基址,编译器填的 没用
DWORD ImageBase;* 内存镜像基址
DWORD SectionAlignment;* 内存对齐
DWORD FileAlignment;* 文件对齐
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;* 内存中整个PE文件的映射的尺寸,可以比实际的值大,但必须是SectionAlignment的整数倍
DWORD SizeOfHeaders;* 所有头+节表按照文件对齐后的大小,否则加载会出错
DWORD CheckSum;* 校验和,一些系统文件有要求.用来判断文件是否被修改.
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;* 初始化时保留的堆栈大小
DWORD SizeOfStackCommit;* 初始化时实际提交的大小
DWORD SizeOfHeapReserve;* 初始化时保留的堆大小
DWORD SizeOfHeapCommit;* 初始化时实践提交的大小
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;* 目录项数目,剩余结构体的数量