PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)
DOS头
typedef struct _IMAE_DOS_HEADER { //DOS .EXE header 位置
WORD e_magic; //Magic number; 0x00
WORD e_cblp; //Bytes on last page of file 0x02
WORD e_cp; //Pages in file 0x04
WORD e_crlc; //Relocations 0x06
WORD e_cparhdr; //Size of header in paragraphs 0x08
WORD e_minalloc; //Minimum extra paragraphs needed 0x0A
WORD e_maxalloc; //Maximum extra paragraphs needed 0x0C
WORD e_ss; //Initial (relative) SS value 0x0E
WORD e_sp; //Initial SP value 0x10
WORD e_csum; //Checksum 0x12
WORD e_ip; //Initial IP value 0x14
WORD e_cs; //Initial (relative) CS value 0x16
WORD e_lfarlc; //File address of relocation table 0x18
WORD e_ovno; //Overlay number 0x1A
WORD e_res[4]; //Reserved words 0x1C
WORD e_oemid; //OEM identifier (for e_oeminfo) 0x24
WORD e_oeminfo; //OEM information; e_oemid specific 0x26
WORD e_res2[10]; //Reserved words 0x28
LONG e_lfanew; //File address of new exe header 0x3C
} IMAGE_DOS-HEADER, *PIMAGE_DOS_HEADER;
- e_magic 字段是一个DOS可执行文件的标识符,该字段占用两个字节,该位置保存着的字符是“MZ”。
- e_lfanew字段是新exe头部的文件地址。用于表示DOS头之后的NT头的相对文件起始地址的偏移。
NT头
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //文件的运行平台,是x86、x64还是I64等
WORD NumberOfSections; //该PE文件中有多少个节,也就是节表中的项数
DWORD TimeDateStamp; //PE文件的创建时间
DWORD PointerToSymbolTable; //COFF文件符号表在文件中的偏移
DWORD NumberOfSymbols; //符号表的数量
WORD SizeOfOptionalHeader; //可选头的大小
WORD Characteristics; //可执行文件的属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; //标志字
BYTE MajorLinkerVersion; //链接程序的主版本号
BYTE MinorLinkerVersion; //链接程序的次版本号
DWORD SizeOfCode; //所有含代码的节的总大小
DWORD SizeOfInitializedData; //所有含已初始化数据的节的大小
DWORD SizeOfUninitializedData; //所有含未初始化数据的节的大小
DWORD AddressOfEntryPoint; //程序执行入口
DWORD BaseOfCode; //代码的区块起始RVA
DWORD BaseOfData; //数据的区块起始RVA
DWORD ImageBase; //程序的首选装载地址
DWORD SectionAlignment; //内存中区块的对齐大小
DWORD FileAlignment; //文件中区块的对齐大小
WORD MajorOperatingSystemVersion; //要求操作系统最低版本号的主版本号
WORD MinorOperatingSystemVersion; //要求操作系统最低版本号的副版本号
WORD MajorImageVersion; //可运行于操作系统的主版本号
WORD MinorImageVersion; //可运行于操作系统的次版本号
WORD MajorSubsystemVersion; //要求最低子系统主版本号
WORD MinorSubsystemVersion; //要求最低子系统的次版本号
DWORD Win32VersionValue; //没有实际意义。不被利用的情况下,一般为0
DWORD SizeOfImage; //映像装入内存后的总尺寸
DWORD SizeOfHeaders; //所有头+区块表的尺寸大小
DWORD CheckSum; //映像的校验和
WORD Subsystem; //可执行文件期望的子系统
WORD DllCharacteristics; //DllMain函数何时被调用。默认为0
DWORD SizeOfStackReserve; //初始化时的栈大小
DWORD SizeOfStackCommit; //初始化时实际提交的栈大小
DWORD SizeOfHeapReserve; //初始化时保留的堆大小
DWORD SizeOfHeapCommit; //初始化时实际提交的堆大小
DWORD LoaderFlags; //与调试相关的值,默认为0
DWORD NumberOfRvaAndSizes; //下面数据目录的项数,自Windows NT发布以来,一直是16
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
地址名词相关
- 虚拟内存地址(VA)
PE文件对应的进程支配了自己独立的4GB虚拟空间,在这个空间定位的地址是VA,VA的范围是4GB。VA=进程基地址+RVA - 相对虚拟内存地址(RVA)
每个模块都有一个基地址。如果两个模块的基地址是相同的,就由操作系统来决定模块的具体位置。
RVA是针对于模块的概念,用来定位某个特殊位置距离某个模块基地址的偏移量。
模块:同时加载到进程空间的文件
- 文件偏移地址(FOA)
FOA和内存无关,是指某个位置距离头文件的偏移。