打开HxD,页面如下
研究对象为HxD.exe

观察DOS头部数据
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number: 0x5a4d
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header 0x3c
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
e_magic的数值为0x5A4D,偏移量为0x0000e_lfanew的数值为0x00000100,偏移量为0x003C
查看PE头数据
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; // Signature == 0x00004550, 4字节
IMAGE_FILE_HEADER FileHeader; // 20(0x14)字节
IMAGE_OPTIONAL_HEADER32 OptionalHeader; // 96 + 8x16 = 224(0xE0)
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; // 0xF8
Signature(签名)数值为0x4550,偏移量为0x003C + 0x0000
看FileHeader文件头和OptionalHeader可选头
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //每个CPU都拥有的唯一的Machine码,兼容32位Intel x86芯片的Machine码为14C
WORD NumberOfSections; //★指出文件中存在的节区数量
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; //指出结构体IMAGE_OPTIONAL_HEADER32(32位系统)的长度★
WORD Characteristics; //标识文件属性,是否可运行、是否为DLL等,以bit OR形式进行组合
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; //IMAGE_OPTIONAL_HEADER32为0x10B,IMAGE_OPTIONAL_HEADER64为0x20B
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint; //★RVA值,指出程序最先执行的代码起始地址
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase; //★指出文件的优先装入地址(32位进程虚拟内存范围为:0~7FFFFFFF)
DWORD SectionAlignment; //★节区在内存中的最小单位
DWORD FileAlignment; //★节区在磁盘文件中的最小单位
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage; //指定了PE Image在虚拟内存中所占空间的大小
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem; //区分系统驱动文件和普通可执行文件
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes; //指定Data Directory数组的大小
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //★数据目录数组
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
具体含义看官方文档
https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header
关键属性
- Machine 计算机架构。 该字段表示PE文件执行的计算机架构环境,0x014c表示x86架构,而0x8664表示x64计算机架构环境。
值为0x8664,偏移量为0x0104 + 0x0004 - NumberOfSections ★节数 该字段表示在PE头部后面紧跟的“节表”的大小,也就是“节数”,在Windows环境下最大节数为96。
值为0x0009,偏移量为0x0104 + 0x0006 - SizeOfOptionalHeader ★可选头的大小,单位是字节。
值为0x000F,偏移量为0x0104 + 0x0010 - Characteristics 镜像特性
值为0x0023,偏移量为0x0104 + 0x0012 - Magic魔术字。该字段表示了文件的状态,可以使用表格 2查询其具体含义。
值为0x020B,偏移量为0x0118 + 0x0000
表示可执行文件映像 - AddressOfEntryPoint 入口地址★★★。相对于PE文件加载进入内存中,代码的起始入口地址,这个地址使用了相对地址,即相对于Image base地址的偏移地址。
值为0x005199C0,偏移量为0x0118 + 0x0010 - BaseOfCode 代码节入口地址,该地址是代码节的开始位置,使用了相对地址表示。
值为0x00001000,偏移量为0x0118 + 0x0014 - ImageBase 镜像基地址★★。镜像基地址就是以上叙述中提及的Image base地址,即当PE文件加载到内存中,PE文件内存中开始位置的地址。通常在PE头部中的各类地址都是相对这个地址的偏移量,所以这是其他地址的基础,称为基地址。这个地址是64K的整倍数,通常默认Windows可执行文件(EXE)使用0x00400000,动态链接库(DLL)使用0x10000000。
节区头和节区(Sections)
节区头紧跟在PE头后面
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //内存中节区所占大小
} Misc;
DWORD VirtualAddress; //内存中节区起始地址(RVA)
DWORD SizeOfRawData; //磁盘文件中节区所占大小
DWORD PointerToRawData; //磁盘文件中节区的偏移地址
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; //节区属性(bit OR)
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
节区头从本质上就是一个表格,表格的每一行是一个IMAGE_SECTION_HEADER结构体,表格长度就是PE头中NumberOfSections字段中的数值。