PE 文件格式详解

PE 文件格式详解

PE 文件结构全貌介绍

PE 文件结构全貌

PE 文件结构大致分为四大部分,每部分又可以细分。从数据管理角度来看,PE 文件大致分为两个部分,一是 DOS 头、PE 头和节表属于构成可执行文件的数据管理结构和数据组织结构部分,二是节表数据才是可执行文件真正的数据部分,包含着程序执行时真正的代码、数据、资源等内容。

DOS 头

MZ 头部

DOS 存根

PE 头

PE 标识符(PE\0\0)

文件头

可选头

节表

节表一

节表二

... ...

节表N

节表数据

节表数据一(可能是代码或者数据)

节表数据二(可能是代码或者数据)

... ...

节表数据N(可能是代码或者数据)

PE 结构各部分简介

一、DOS 头

DOS 头分为“MZ 头部”和“DOS 存根”。MZ 头部才是真正的DOS头部,由于开始处的两个字节为“MZ”,因此 DOS 头也可以叫做 MZ 头。该头部用于程序在 DOS 系统下加载,他的结构被定义为 IMAGE_DOS_HEADER。

DOS 存根是一段简单的 DOS 程序,主要用于输出类似“This program cannot be run in DOS mode.”的提示字符串。

DOS 头主要是为了可执行程序可以兼容 DOS 系统。DOS 存根程序可以通过连接参数进行修改,使可执行文件同时在 Windows 和 DOS 系统同时运行。

二、PE 头

PE 头部保存着 Windows 系统加载可执行文件的重要信息。PE 头部又 IMAGE_NT_HEADERS 定义。IMAGE_NT_HEADERS 是由 IMAGE_NT_SIGNATRUE(宏定义)、IMAGE_FILE_HEADER 和 IMAGE_OPTIONAL_HEADER 多个结构体组成。

PE 头部在 PE 文件中的位置是不固定的,由 DOS 头部的某个字段给出。

三、节表

程序的组织按照各属性的不同而保存在不同的节中,在 PE 头部之后就是一个结构体数组构成的节表。节表中描述了各个节在整个文件中的位置与加载入内存后的位置,同时定义了节的属性(只读、可读写、可执行等)。描述节表的结构体是 IMAGE_SECTION_HEADER,如果 PE 文件中有 N 个节,那么节表就是由 N 个 IMAGE_SECTION_HEADER 组成的数组。

四、节数据

可执行文件中的真正程序代码部分就保存在 PE 结构的节中,当然,数据、资源等内容也保存在节中。节表只是描述了节数据的起始地址、大小及属性等信息。

详解 PE 文件结构

PSDK(Platform Software Development Kits,平台软件开发包)的头文件 Winnt.h 中包含了 PE 文件结构的定义格式。PE 头文件分为 32 位和 64 位版本。64 位的 PE 结构是对 32 位 PE 结构进行了扩展。

DOS 头部详解 --- IMAGE_DOS_HEADER

PE 文件的最开始的位置就是一个 DOS 程序。DOS 程序包含了一个 DOS 头部和一个 DOS 程序体( DOS 存根或 DOS 残留)。DOS 头是用来装载 DOS 存根用的。

IMAGE_DOS_HEADER 定义如下:

#define IMAGE_DOS_SIGNATURE 0x5A4D

typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header

WORD e_magic; // Magic number 幻数(魔法数字)

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 初始(相对) SS 值

WORD e_sp; // Initial SP value 初始 SP 值

WORD e_csum; // Checksum 校验和

WORD e_ip; // Initial IP value 初始 IP 值

WORD e_cs; // Initial (relative) CS value 初始(相对) CS 值

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) OEM 标识符(用于 e_oeminfo)

WORD e_oeminfo; // OEM information; e_oemid specific OEM 信息;e_oemid 特定

WORD e_res2[10]; // Reserved words 保留字

LONG e_lfanew; // File address of new exe header PE 文件解析时用它找到 PE 头的位置

} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; // 结构体大小 64 字节

IMAGE_DOS_HEADER(汇编)

IMAGE_DOS_SIGNATURE equ 5A4Dh

IMAGE_DOS_HEADER STRUCT

e_magic 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 WORD 4 dup(?)

e_oemid WORD ?

e_oeminfo WORD ?

e_res2 WORD 10 dup(?)

e_lfanew DWORD ?

IMAGE_DOS_HEADER ENDS

该结构体中只需要记住 e_magic 和 e_lfanew 两个字段,e_magic 是 DOS 可执行文件的标识符,e_lfanew 保存着 PE 头的起始位置。

PE 头部详解 --- IMAGE_NT_HEADERS

PE 头部是真正用来装载 Windows 程序的头部,PE 头的定义为 IMAGE_NT_HEADERS,该结构体包含 PE 标识符、文件头 IMAGE_FILE_HEADER 和可选头 IMAGE_OPTIONAL_HEADER 三部分。IMAGE_NT_HEADERS 是一个宏定义,定义如下:

#ifdef _WIN64

typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;

typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;

#else

typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;

typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;

#endif

该头分为 32 位和 64 位,其定义依赖于是否定义了 _WIN64 宏。IMAGE_NT_HEADERS32 的定义如下:

#define IMAGE_NT_SIGNATURE 0x00004550 // PE00

typedef struct _IMAGE_NT_HEADERS {

DWORD Signature;

IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER32 OptionalHeader;

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

IMAGE_NT_HEADERS(汇编)

IMAGE_NT_SIGNATURE equ 00004550h

IMAGE_NT_HEADERS STRUCT

Signature DWORD ?

FileHeader IMAGE_FILE_HEADER <>

OptionalHeader IMAGE_OPTIONAL_HEADER32 <>

IMAGE_NT_HEADERS ENDS

该结构体的 Signature 就是 PE 标识符,标识该文件是否是 PE 文件。该部分占 4 个字节。该值非常重要,在判断一个文件是否是 PE 文件时,首先要判断文件的起始位置是否为“MZ”,在通过 DOS 头部的相应偏移找到 PE 头部,判断 PE 头部是否为 PE\x00\x00。

文件头部详解 --- IMAGE_FILE_HEADER

IMAGE_FILE_HEADER 结构体紧跟在 PE 标识符后面,大小为 20 个字节。IMAGE_FILE_HEADER 定义如下:

typedef struct _IMAGE_FILE_HEADER {

WORD Machine;

WORD NumberOfSections;

DWORD TimeDateStamp;

DWORD PointerToSymbolTable;

DWORD NumberOfSymbols;

WORD SizeOfOptionalHeader;

WORD Characteristics;

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

IMAGE_FILE_HEADER(汇编)

IMAGE_FILE_HEADER STRUCT

Machine WORD ?

NumberOfSections WORD ?

TimeDateStamp DWORD ?

PointerToSymbolTable DWORD ?

NumberOfSymbols DWORD ?

SizeOfOptionalHeader WORD ?

Characteristics WORD ?

IMAGE_FILE_HEADER ENDS

该结构体的各个字段:

Machine( WORD ):该字段表示可执行文件的目标 CPU 类型。

Machine 的取值

#define IMAGE_FILE_MACHINE_UNKNOWN 0

#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.

#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.

#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian

#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian

#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian

#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2

#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP

#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian

#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3

#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian

#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian

#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5

#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian

#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian

#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian

#define IMAGE_FILE_MACHINE_AM33 0x01d3

#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian

#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1

#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64

#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS

#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64

#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS

#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS

#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64

#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon

#define IMAGE_FILE_MACHINE_CEF 0x0CEF

#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code

#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)

#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian

#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian

#define IMAGE_FILE_MACHINE_CEE 0xC0EE

NumberOfSections( WORD ):该字段表示 PE 文件的节表数量。

TimeDataStamp( DWORD ):该字段表示文件是何时被创建的。这个值是自 1970 年 1 月 1 日以来用格林尼威治时间计算的秒数。

PointerToSymbolTable( DWORD ):该字段表示符号表的偏移量(以字节为单位)或零(如果不存在 COFF 符号表)。

NumberOfSymbols( DWORD ):该字段表示符号表中的符号数。

SizeOfOptionalHeader( WORD ):该字段指定 IMAGE_OPTIONAL_HEADER 结构体的大小。PE 文件需要定位节表的位置的时候,计算 IMAGE_OPTIONAL_HEADER 的大小时,应该从 IMAGE_FILE_HEADER 结构体中的 SizeOfOptionalHeader 字段指定的值来获取,而不是 sizeo(IMAGE_OPTIONAL_HEADER)。

Characteristics( WORD ):该字段指定文件的类型。

Characteristics 的取值

#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. 从文件中去除了重定位信息。

#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references). 文件是可执行的(即没有未解析的外部引用)。

#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. COFF行号已从文件中删除。

#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. COFF 符号表条目已从文件中删除。

#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Aggressively trim working set 此值已过时。

#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses 应用程序可以处理大于 2 GB 的地址。

#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. 此标志已过时。

#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. 计算机支持 32 位字。

#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file 调试信息已删除并单独存储在另一个文件中。

#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. 如果映像位于可移动媒体上,请将其复制到交换文件并从交换文件运行它。

#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. 如果映像在网络上,请将其复制到交换文件并从中运行它。

#define IMAGE_FILE_SYSTEM 0x1000 // System File. 系统文件。

#define IMAGE_FILE_DLL 0x2000 // File is a DLL. DLL文件.

#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine 该文件应仅在单处理器计算机上运行。

#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. 此标志已过时。

可选头详解 --- IMAGE_OPTIONAL_HEADER

IMAGE_OPTIONAL_HEADER 虽然叫可选头,但并不表示是可有可无的,是必须存在的头部,该头部的数据目录部分是可选的。可选头是对文件头的一个补充。文件头主要描述文件的相关信息,而可选头主要用来管理 PE 文件被操作系统装载时所需要的信息,该头同样有32 位和 64 位。IMAGE_OPTIONAL_HEADER 是一个宏,定义如下:

#ifdef _WIN64

typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;

typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;

#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC

#else

typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;

typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;

#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC

#endif

32 位和 64 位的选择是根据是否定义 _WIN64 宏而决定的。在定义中能看到其他几个常量,分别定义如下:

#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b

#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b

IMAGE_OPTIONAL_HEADER32 结构体定义如下:

//

// Optional header format.

//

typedef struct _IMAGE_OPTIONAL_HEADER {

//

// Standard fields.

//

WORD Magic;

BYTE MajorLinkerVersion;

BYTE MinorLinkerVersion;

DWORD SizeOfCode;

DWORD SizeOfInitializedData;

DWORD SizeOfUninitializedData;

DWORD AddressOfEntryPoint;

DWORD BaseOfCode;

DWORD BaseOfData;

//

// NT additional fields.

//

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;

IMAGE_OPTIONAL_HEADER32(汇编)

IMAGE_OPTIONAL_HEADER32 STRUCT

Magic WORD ?

MajorLinkerVersion BYTE ?

MinorLinkerVersion BYTE ?

SizeOfCode DWORD ?

SizeOfInitializedData DWORD ?

SizeOfUninitializedData DWORD ?

AddressOfEntryPoint DWORD ?

BaseOfCode DWORD ?

BaseOfData DWORD ?

ImageBase DWORD ?

SectionAlignment DWORD ?

FileAlignment DWORD ?

MajorOperatingSystemVersion WORD ?

MinorOperatingSystemVersion WORD ?

MajorImageVersion WORD ?

MinorImageVersion WORD ?

MajorSubsystemVersion WORD ?

MinorSubsystemVersion WORD ?

Win32VersionValue DWORD ?

SizeOfImage DWORD ?

SizeOfHeaders DWORD ?

CheckSum DWORD ?

Subsystem WORD ?

DllCharacteristics WORD ?

SizeOfStackReserve DWORD ?

SizeOfStackCommit DWORD ?

SizeOfHeapReserve DWORD ?

SizeOfHeapCommit DWORD ?

LoaderFlags DWORD ?

NumberOfRvaAndSizes DWORD ?

DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)

IMAGE_OPTIONAL_HEADER32 ENDS

该结构体的各个字段:

Machine:文件的标识。

Machine 的取值

#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b // 32 位可执行文件

#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b // 64 位可执行文件

#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 // ROM 文件

MajorLinkerVersion:链接器的主要版本号

MinorLinkerVersion:链接器的次要版本号

SizeOfCode:代码部分的大小(以字节为单位)或所有此类部分的总和(如果有多个代码) 部分。

SizeOfInitializedData:初始化的数据部分的大小(以字节为单位)或所有此类部分的总和(如果有多个) 初始化的数据部分。

SizeOfUninitializedData:未初始化的数据部分的大小(以字节为单位)或所有此类部分的总和(如果有多个) 未初始化的数据部分。

AddressOfEntryPoint:程序执行的入口地址。该地址是一个相对虚拟地址,简称 EP(EntryPoint),这个值指向了程序第一条要执行的代码。程序如果被加壳后会修改该字段的值,成为壳的入口地址,这样壳就有机会先执行。在脱壳过程中找到了加壳前的入口地址,就说明找到了原始入口点,原始入口点称为 OEP。该字段的地址指向不是 main 函数的地址,也不是 WinMain 函数的地址,而是运行库的启动代码地址。对于 DLL 来说这个值的意义不大,因为 DLL 甚至可以没有 DllMain 函数,没有 DllMain 只是无法捕获装载和卸载 DLL 时的四条消息。如果在 DLL 装载或卸载时没有需要进行处理的事件,可以将 DllMain 函数省略。

BaseOfCode:代码节的起始相对虚拟地址。

BaseOfData:数据节的起始相对虚拟地址

ImageBase:文件被载入内存后第一个字节的首选地址。对于 EXE 文件来说,通常情况下该地址就是装载地址,默认值是 0x00400000;对于 DLL 文件来说,可能就不是装入内存后的地址,默认值是 0x10000000。

SectionAlignment:节表数据被装入内存后的对齐值,也就是节表数据被映射到内存中需要对齐的单位。在 Win32 下,通常情况下,该值为 0x1000 字节,也就是 4KB 大小。

FileAlignment:节表数据在文件中的对齐值,通常情况下,该值为 0x1000 字节或 0x200 字节。在文件对齐为 0x1000 字节时,由于与内存对齐值相同,可以加快操作系统对可执行文件装载入内存的速度。而文件对齐值为 0x200 字节时,可以占用相对较少的磁盘空间。0x200 字节是 512 字节,通常磁盘的一个扇区即为 512 字节。

MajorOperatingSystemVersion:所需操作系统的主版本号

MinorOperatingSystemVersion:所需操作系统的次要版本号。

MajorImageVersion:可执行文件的主版本号。

MinorImageVersion:可执行文件的次要版本号。

MajorSubsystemVersion:子系统的主要版本号。

MinorSubsystemVersion:子系统的次要版本号。

Win32VersionValue:此成员是保留的,必须为 0。

SizeOfImage:可执行文件装入内存后的总大小。该大小按内存对齐方式对齐。

SizeOfHeaders:整个 PE 头部的大小。这个 PE 头部指 DOS 头、PE 头、节表的总合大小。该大小按文件对齐方式对齐。

CheckSum:校验和。对于 EXE 文件通常为 0;对于 SYS 文件(驱动文件、内核文件),则必须有一个校验和。

Subsystem:可执行文件的子系统类型。

SubSystem 的取值

#define IMAGE_SUBSYSTEM_UNKNOWN 0 // 未知子系统。

#define IMAGE_SUBSYSTEM_NATIVE 1 // 无需子系统(设备驱动程序和本机系统进程)。

#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // 窗口图形用户界面 (GUI) 子系统。

#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Windows 控制台 (CUI) 子系统。

#define IMAGE_SUBSYSTEM_OS2_CUI 5 // OS/2 CUI 子系统。

#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // POSIX CUI 子系统。

#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8

#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Windows CE系统。

#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 // 可扩展固件接口 (EFI) 应用程序。

#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 // 具有启动服务的 EFI 驱动程序。

#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 // 具有运行时服务的 EFI 驱动程序。

#define IMAGE_SUBSYSTEM_EFI_ROM 13

#define IMAGE_SUBSYSTEM_XBOX 14 // Xbox 系统。

#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 // 启动应用程序。

#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17

DllCharacteristics:指定 DLL 文件的属性。

DllCharacteristics 取值

// IMAGE_LIBRARY_PROCESS_INIT 0x0001 // Reserved.

// IMAGE_LIBRARY_PROCESS_TERM 0x0002 // Reserved.

// IMAGE_LIBRARY_THREAD_INIT 0x0004 // Reserved.

// IMAGE_LIBRARY_THREAD_TERM 0x0008 // Reserved.

#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 // 具有 64 位地址空间的 ASLR。

#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 // DLL可以在加载时重定位。

#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 // 强制进行代码完整性校验

#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 // Image is NX compatible

#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 // Image understands isolation and doesn't want it

#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 // Image does not use SEH. No SE handler may reside in this image

#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 // Do not bind this image.

#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 // Image should execute in an AppContainer

#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 // Driver uses WDM model

#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 // Image supports Control Flow Guard.

#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000

SizeOfStackReserve:为线程保留的栈大小,以字节为单位。

SizeOfStackCommit: 为线程已提交的栈大小,以字节为单位。

SizeOfHeapReserve:为线程保留的堆大小。

SizeOfHeapCommit:为线程提交的堆大小。

LoaderFlags:保留字段,必须为 0。

NumberOfRvaAndSizes:数据目录项的个数。#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]:数据目录表,由 NumberOfRvaAndSizes 个 IMAGE_DATA_DIRECTORY 结构体组成的数组。该数组包含输入表、输出表、资源、重定位等数据目录项的 RVA(相对虚拟地址)和大小。IMAGE_DATA_DIRECTORY 结构体定义如下:

//

// Directory format.

//

typedef struct _IMAGE_DATA_DIRECTORY {

DWORD VirtualAddress; // 实际上数据目录的 RVA

DWORD Size; // 数据目录项的大小

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

IMAGE_DATA_DIRECTORY(汇编)

IMAGE_DATA_DIRECTORY STRUCT

VirtualAddress DWORD ?

isize DWORD ?

IMAGE_DATA_DIRECTORY ENDS

数据目录中的成员在数组中的索引

// Directory Entries

#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // 导出表

#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // 导入表

#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // 资源

#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory

#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory

#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // 重定位

#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory

// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)

#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data

#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP

#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS

#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory

#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers

#define IMAGE_DIRECTORY_ENTRY_IAT 12 // 导入地址表

#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors

#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor

节表详解 --- IMAGE_SECTION_HEADER

节表的位置在 IMAGE_OPTIONAL_HEADER 结构体后面,节表中的每个 IMAGE_SECTION_HEADER 中都存放着可执行文件被映射到内存中所在位置的信息,节的个数由 IMAGE_FILE_HEADER 中的 NumberOfSections 给出。IMAGE_SECTION_HEADER 的大小为 40 字节,IMAGE_SECTION_HEADER 定义如下:

//

// Section header format.

//

#define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _IMAGE_SECTION_HEADER {

BYTE Name[IMAGE_SIZEOF_SHORT_NAME];

union {

DWORD PhysicalAddress;

DWORD VirtualSize;

} Misc;

DWORD VirtualAddress;

DWORD SizeOfRawData;

DWORD PointerToRawData;

DWORD PointerToRelocations;

DWORD PointerToLinenumbers;

WORD NumberOfRelocations;

WORD NumberOfLinenumbers;

DWORD Characteristics;

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

#define IMAGE_SIZEOF_SECTION_HEADER 40

IMAGE_SECTION_HEADER(汇编)

IMAGE_SECTION_HEADER STRUCT

Name1 db IMAGE_SIZEOF_SHORT_NAME dup(?)

union Misc

PhysicalAddress dd ?

VirtualSize dd ?

ends

VirtualAddress dd ?

SizeOfRawData dd ?

PointerToRawData dd ?

PointerToRelocations dd ?

PointerToLinenumbers dd ?

NumberOfRelocations dw ?

NumberOfLinenumbers dw ?

Characteristics dd ?

IMAGE_SECTION_HEADER ENDS

该结构体的各个字段:

Name[IMAGE_SIZEOF_SHORT_NAME]:一个 8 字节、NULL 填充的 UTF-8 字符串。多余字节会被自动截断。

Misc.PhysicalAddress:文件地址。

Misc.VirtualSize:加载到内存中的节的总大小(以字节为单位)。如果此值大于 SizeOfRawData 成员,则该节将用零填充。此字段仅对可执行映像有效,对于目标文件应设置为 0。

VirtualAddress:节区数据装入内存后的相对虚拟地址,这个地址是按内存对齐的,该地址加上 IMAGE_OPTIONAL_HEADER 结构体中的 ImageBase 才是内存中的虚拟地址。

SizeOfRawData:节区数据在磁盘上的大小,该值是按照文件对齐进行对齐后的值,但是也有例外。

PointerToRawData:节区在磁盘文件上的偏移地址。

PointerToRelocations:A file pointer to the beginning of the relocation entries for the section. If there are no relocations, this value is zero.

PointerToLinenumbers:A file pointer to the beginning of the line-number entries for the section. If there are no COFF line numbers, this value is zero.

NumberOfRelocations:The number of relocation entries for the section. This value is zero for executable images.

NumberOfLinenumbers:The number of line-number entries for the section.

Characteristics:节区的属性。

Characteristics 取值

//

// Section characteristics.

//

// IMAGE_SCN_TYPE_REG 0x00000000 // Reserved.

// IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved.

// IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved.

// IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved.

#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.

// IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved.

#define IMAGE_SCN_CNT_CODE 0x00000020 // 部分包含代码。

#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // 部分包含初始化的数据。

#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // 部分包含未初始化的数据。

#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.

#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.

// IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved.

#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.

#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.

// 0x00002000 // Reserved.

// IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000

#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.

#define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP

#define IMAGE_SCN_MEM_FARDATA 0x00008000

// IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000

#define IMAGE_SCN_MEM_PURGEABLE 0x00020000

#define IMAGE_SCN_MEM_16BIT 0x00020000

#define IMAGE_SCN_MEM_LOCKED 0x00040000

#define IMAGE_SCN_MEM_PRELOAD 0x00080000

#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //

#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //

#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //

#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //

#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.

#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //

#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //

#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 //

#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 //

#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 //

#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 //

#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 //

#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 //

#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 //

// Unused 0x00F00000

#define IMAGE_SCN_ALIGN_MASK 0x00F00000

#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // 部分包含扩展的重定位。

#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // 节可以被丢弃。

#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // 节不可缓存。

#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // 节是不可分页的。

#define IMAGE_SCN_MEM_SHARED 0x10000000 // 节是可共享的。

#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // 节是可执行的。

#define IMAGE_SCN_MEM_READ 0x40000000 // 节是可读的。

#define IMAGE_SCN_MEM_WRITE 0x80000000 // 节是可写的。

相关推荐

请问各位老师,中间的AL1-1,AL-5等等是什么意思
365体育比分官网

请问各位老师,中间的AL1-1,AL-5等等是什么意思

📅 01-31 👁️ 3622
如何将机械硬盘的系统转移到固态硬盘?2种无损方法,不用重装!
罗技hub驱动最新免费版下载v2024.8.1856-Logitech G HUB官方版2025下载安装