标准PE头
32位和64位PE头结构体有点差异,但是差异不是很大。
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
扩展PE头
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
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;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
成员 | 大小(十进制) | 说明 |
---|---|---|
Magic | 2字节 | PE32:10B、PE32+(64):20B,可以用来确认是32位还是64位程序 |
MajorLinkerVersion | 1字节 | 链接器版本号 |
MinorLinkerVersion | 1字节 | 链接器版本号 |
SizeOfCode | 4字节 | 所有代码节的总和,文件对齐后的大小,由编译器填写 |
SizeOfInitializedData | 4字节 | 包含所有已经初始化数据的节的总大小,文件对齐后的大小,由编译器填写 |
SizeOfUninitializedData | 4字节 | 包含未初始化数据的节的总大小,文件对齐后的大小,由编译器填写 |
AddressOfEntryPoint | 4字节 | 程序入口,当前PE文件从哪个位置开始执行,配合ImageBase(内存镜像基址)来看 |
BaseOfCode | 4字节 | 代码开始的基址,由编译器填写 |
BaseOfData | 4字节 | 数据开始的基址,由编译器填写 |
ImageBase | 4字节 | 内存镜像基址,当前PE文件执行时从哪个内存位置展开 |
SectionAlignment | 4字节 | 内存对齐 |
FileAlignment | 4字节 | 文件对齐 |
MajorOperatingSystemVersion | 2字节 | 标识操作系统版本号,主版本号 |
MinorOperatingSystemVersion | 2字节 | 标识操作系统版本号,次版本号 |
MajorImageVersion | 2字节 | PE文件自身的版本号 |
MinorImageVersion | 2字节 | PE文件自身的版本号 |
MajorSubsystemVersion | 2字节 | 运行所需子系统版本号 |
MinorSubsystemVersion | 2字节 | 运行所需子系统版本号 |
Win32VersionValue | 4字节 | 子系统版本的值,必须为0 |
SizeOfImage | 4字节 | 内存中整个PE文件的映射尺寸,可以比实际的值大,必须是SectionAlignMent(内存对齐)的整数倍 |
SizeOfHeaders | 4字节 | 所有头+节表按照文件对齐后的大小,否则加载会出错 |
CheckSum | 4字节 | 校验和,一些系统文件由要求用来判断文件是否被修改,不是所有程序都有。 整个PE文件以2个字节相加,加完以后如果溢出不管,得到的结果+文件长度=校验和 |
Subsystem | 2字节 | 子系统,驱动程序:1、图形界面:2、控制台或者DLL:3 |
DllCharacteristics | 2字节 | 文件特征,不是针对DLL文件的 |
SizeOfStackReserve | 4字节 | 初始化时保留的栈大小 |
SizeOfStackCommit | 4字节 | 初始化时实际提交的栈的大小(初始化时真正使用的栈的大小) |
SizeOfHeapReserve | 4字节 | 初始化时保留的堆大小 |
SizeOfHeapCommit | 4字节 | 初始化时实践提交的堆的大小(初始化时真正使用的堆的大小) |
LoaderFlags | 4字节 | 调试相关 |
NumberOfRvaAndSizes | 4字节 | 目录项目数量,当前程序会用到各种表,如导入表导出表等,描述有多少个这种表 |
DataDirector | 不确定 | 结构体数组,NumberOfRvaAndSizes的长度是多少它的长度就是多少 |
注意:
AddressOfEntryPoint(程序入口)是相对的地址,也就是ImageBase(内存镜像基址) + AddressOfEntryPoint(程序入口)。
IMAGE_OPTIONAL_HEADER->DllCharacteristics
数据位 | 常量符号 | 为1时的含义 |
---|---|---|
0 | 保留,必须为0 | |
1 | 保留,必须为0 | |
2 | 保留,必须为0 | |
3 | 保留,必须为0 | |
6 | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | DLL可以在加载时被重定位 |
7 | IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY | 强制代码实施完整性验证 |
8 | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | 该映像兼容DEP(Intel的硬件层面修复漏洞的东西) |
9 | IMAGE_DLLCHARACTERISTICS_NO_ISOLATION | 可以隔离,但并不隔离此映像 |
10 | IMAGE_DLLCHARACTERISTICS_NO_SEH | 映像不适用SEH |
11 | IMAGE_DLLCHARACTERISTICS_NO_BIND | 不绑定映像 |
12 | 保留,必须为0 | |
13 | IMAGE_DLLCHARACTERISTICS_WDM_DRIVER | 该映像为一个WDM driver |
14 | 保留,必须为0 | |
15 | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWAR | 可用于终端服务器 |