Contents

PE文件学习一

前言

最近学了免杀,正好把之前零散的东西整合了一下,本篇文章就先把PE文件的结构记录一下。

PE文件总体结构

https://s1.ax1x.com/2022/10/02/xMZjhQ.png

DOS部首

DOS部首分为两部分,DOS HeaderDOS Stub

DOS Header

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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
    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
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

因为历史遗留问题,早期的Windows程序是运行在DOS系统(16位)上的,所以该部分主要是给DOS用的(向下兼容),目前在32位或64位Windows系统使用的成员是:

  1. e_magic
  2. e_lfanew
成员 数据宽度 注释 说明
e_magic WORD(2字节) Magic Number PE文件判断标识 4d 5a, ASCII = ‘MZ’
e_lfanew LONG(4字节) File address of new exe header 存储PE头首地址 不定

DOS Stub

DOS Stub在32位及以上的Windows系统中同样无效

PE文件头 (PE_NT_HEADER)

PE文件头主要由三部分组成:

  1. PE文件头标志
  2. PE文件表头/标准PE头
  3. PE文件表头可选部分/拓展PE头

32位结构体

1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                            //PE文件头标识
    IMAGE_FILE_HEADER FileHeader;               //标准PE头
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;     //扩展PE头 32位
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

64位结构体

1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;                            //PE文件头标识
    IMAGE_FILE_HEADER FileHeader;               //标准PE头 
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;     //扩展PE头 64位
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

PE文件头标志 (Signature)

PE文件头标志 对应C语言变量 数据宽度 说明
“PW”,0,0 Signature DWORD(4字节) 50 45 00 00,ASCII = “PE " PE文件标识符

PE文件表头 (PE_FILE_HEADER)

结构体代码

1
2
3
4
5
6
7
8
9
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;//可以运行在什么样的CPU上   任意:0    Intel 386以及后续:14C   x64:8664  
    WORD    NumberOfSections;//表示节的数量
    DWORD   TimeDateStamp;//编译器填写的时间戳 与文件属性里面(创建时间、修改时间)无关
    DWORD   PointerToSymbolTable;//调试相关
    DWORD   NumberOfSymbols;//调试相关
    WORD    SizeOfOptionalHeader;//可选PE头的大小(32位PE文件:0xE0  64位PE文件:0xF0)
    WORD    Characteristics;//文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

成员详情

成员 数据宽度 说明
Machine WORD(2字节) 程序支持的CPU 任意: 0;intel 386以及后续: 14C; x64: 8664
NumberOfSections WORD(2字节) 节的数量 不大于96
TimeDateStamp DWORD(4字节) 编译器填写的时间戳 与文件属性里面(创建时间、修改时间)无关
PointerToSymbolTable DWORD(4字节) 指向符号表 调试相关
NumberOfSymbols DWORD(4字节) 符号表中的符号个数 调试相关
SizeOfOptionalHeader WORD(2字节) 可选PE头大小 32位PE文件: 0xE0; 64位PE文件: 0xF0
Characteristics WORD(2字节) 文件属性 由数据位拼接而成

Machine

计算机的体系结构类型

含义
IMAGE_FILE_MACHINE_I386 = 0x014c x86
IMAGE_FILE_MACHINE_IA64 = 0x0200 Intel IPF
IMAGE_FILE_MACHINE_AMD64 = 0x8664 x64

NumberOfSections

节数。表示PE文件头后面节表的数量

TimeDateStamp

Image时间戳的低32位

PointerToSymbolTable

符号表的偏移量,以字节为单位,如果不存在COFF符号表,则为零

NumberOfSymbols

符号表中的符号数

SizeOfOptionalHeader

拓展PE头的大小,以字节为单位

Characteristics

Image的文件属性

数据位 常量符号 为1时的含义
0 IMAGE_FILE_RELOCS_STRIPPED 文件中不存在重定位信息
1 IMAGE_FILE_EXECUTABLE_IMAGE 文件是可执行的
2 IMAGE_FILE_LINE_NUMS_STRIPPED 不存在行信息
3 IMAGE_FILE_LOCAL_SYMS_STRIPPED 不存在符号信息
4 IMAGE_FILE_AGGRESSIVE_WS_TRIM 调整工作集
5 IMAGE_FILE_LARGE_ADDRESS_AWARE 应用程序可处理大于2GB的地址
6 保留
7 IMAGE_FILE_BYTES_REVERSED_LO 小尾方式
8 IMAGE_FILE_32BIT_MACHINE 只在32位平台上运行
9 IMAGE_FILE_DEBUG_STRIPPED 不包含调试信息
10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 不能从移动硬盘运行
11 IMAGE_FILE_NET_RUN_FROM_SWAP 不能从网络运行
12 IMAGE_FILE_SYSTEM 系统文件(如驱动程序),不能直接运行
13 IMAGE_FILE_DLL 这是一个DLL文件
14 IMAGE_FILE_UP_SYSTEM_ONLY 文件不能在多处理器计算机上运行
15 IMAGE_FILE_BYTES_REVERSED_HI 大尾方式

PE文件拓展头 (PE_OPTIONAL_HEADER)

32位结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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;

64位结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef struct _IMAGE_OPTIONAL_HEADER64 {
    WORD        Magic;
    BYTE        MajorLinkerVersion;
    BYTE        MinorLinkerVersion;
    DWORD       SizeOfCode;
    DWORD       SizeOfInitializedData;
    DWORD       SizeOfUninitializedData;
    DWORD       AddressOfEntryPoint;
    DWORD       BaseOfCode;
    ULONGLONG   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;
    ULONGLONG   SizeOfStackReserve;
    ULONGLONG   SizeOfStackCommit;
    ULONGLONG   SizeOfHeapReserve;
    ULONGLONG   SizeOfHeapCommit;
    DWORD       LoaderFlags;
    DWORD       NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

成员详情

成员 数据宽度 说明
Magic WORD(2字节) 镜像文件的状态,可用于判断程序是32位还是64位
MajorLinkerVersion BYTE(1字节) 链接器的主要版本号
MinorLinkerVersion BYTE(1字节) 链接器的次要版本号
SizeOfCode DWORD(4字节) 代码段的大小
SizeOfInitializedData DWORD(4字节) 初始化数据段的大小
SizeOfUninitializedData DWORD(4字节) 未初始化数据段的大小
AddressOfEntryPoint DWORD(4字节) 程序入口
BaseOfCode DWORD(4字节) 代码开始的基址
BaseOfData DWORD(4字节) 数据开始的基址
ImageBase DWORD(4字节) 内存镜像的基址
SectionAlignment DWORD(4字节) 内存对齐
FileAlignment WORD(2字节) 文件对齐
MajorOperatingSystemVersion WORD(2字节) 标识操作系统版本号,主版本号
MinorOperatingSystemVersion WORD(2字节) 标识操作系统版本号,次版本号
MajorImageVersion WORD(2字节) PE文件自身的版本号
MinorImageVersion WORD(2字节) PE文件自身的版本号
MajorSubsystemVersion WORD(2字节) 运行所需子系统版本号
MinorSubsystemVersion WORD(2字节) 运行所需子系统版本号
Win32VersionValue DWORD(4字节) 子系统版本的值,必须为0
SizeOfImage DWORD(4字节) Image大小
SizeOfHeaders DWORD(4字节) 所有头+节表按照文件对齐后的大小
CheckSum DWORD(4字节) 校验和
Subsystem WORD(2字节) 子系统
DllCharacteristic WORD(2字节) 文件特性,不只是针对DLL文件的
SizeOfStackReserve DWORD(4字节) 初始化时保留的栈大小
SizeOfStackCommit DWORD(4字节) 初始化时实际提交的栈大小
SizeOfHeapReserve DWORD(4字节) 初始化时保留的堆大小
SizeOfHeapCommit DWORD(4字节) 初始化时提交的堆大小
LoaderFlags DWORD(4字节) 调试相关
NumberOfRvaAndSizes DWORD(4字节) 目录项数目
DataDirectory[16] IMAGE_DATA_DIRECTORY[16]=128字节 指向数据目录中第一个IMAGE_DATA_DIRECTORY结构的指针(数据目录项)

Magic

镜像文件的状态,该成员可以是以下值

含义
IMAGE_NT_OPTIONAL_HDR_MAGIC 该文件是一个可执行的映像
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b 该文件是一个可执行的映像(32位)
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b 该文件是一个可执行的映像(64位)
IMAGE_ROM_OPTIONAL_HDR_MAGIC = 0x107 该文件是ROM镜像

MajorLinkerVersion

链接器版本号

MinorLinkerVersion

链接器次要版本

SizeOfCode

代码段的大小(以字节为单位),如果有多个代码段,则为所有这些代码段的综合。是文件对齐后的大小,编译器填的

SizeOfInitializedData

初始化数据段的大小(以字节为单位),如果有多个代码段,则为所有这些数据段的总和。是文件对齐后的大小,编译器填的

SizeOfUninitializedData

未初始化数据段的大小(以字节为单位),如果有多个未初始化数据段,则为所有这些数据段的总和。是文件对齐后的大小,编译器填的

AddressOfEntryPoint

一个指向入口点函数的指针,相对于Image的基址

  1. 对于可执行文件,这是起始地址
  2. 对于设备驱动程序,这是初始化函数的地址
  3. 入口点函数对于dll是可选。当没有入口点存在时,该成员为零

BaseOfCode

指向代码段开头的指针,相当于ImageBase。编译器填的

BaseOfData

指向数据段开头的指针,相对于ImageBase。编译器填的

ImageBase

Image(PE文件)载入内存时第一个字节的首选地址。该值是64K字节的倍数

  • dll的默认值是0x10000000
  • 应用程序的默认值0x00400000
  • Windows CE上的默认值0x00010000

SectionAlignment

加载到内存中的节的对齐方式,以字节为单位

FileAlignment

Image(PE文件)中各节的原始数据(以字节为单位)的对齐方式。该值应该是512到64k(包括)之间2的幂。

MajorOperatingSystemVersion

所需操作系统的主要版本号

MinorOperatingSystemVersion

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

MajorImageVersion

镜像(PE文件)的主版本号

MinorImageVersion

镜像(PE文件)的次要版本号

MajorSubsystemVersion

子系统的主要版本号

Win32VersionValue

该成员保留的,并且必须为0

SizeOfImage

Image的大小,以字节为单位,包括所有头。必须是多个SectionAlignment

内存中整个PE文件的映射的尺寸,可比实际的值大,必须是SectionAlignment的整数倍

SizeOfHeaders

DOS部首+PE文件头+节表按照文件对齐后的大小

CheckSum

Image(PE文件)校验和

Subsystem

运行此映像所需的子系统。

宏定义 含义
IMAGE_SUBSYSTEM_UNKNOWN 0 未知的子系统
IMAGE_SUBSYSTEM_NATIVE 1 不需要子系统(设备驱动程序和本机系统进程)
IMAGE_SUBSYSTEM_WINDOWS_GUI 2 Windows图形用户界面子系统
IMAGE_SUBSYSTEM_WINDOWS_CUI 3 Windows字符模式用户界面(CUI)子系统
IMAGE_SUBSYSTEM_OS2_CUI 5 OS/2 CUI子系统
IMAGE_SUBSYSTEM_POSIX_CUI 7 POSIX CUI子系统
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 Windows CE系统
IMAGE_SUBSYSTEM_EFI_APPLICATION 10 可扩展固件接口(EFI)应用程序
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 带有引导服务的EFI驱动程序
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 带有运行时服务的EFI驱动程序
IMAGE_SUBSYSTEM_EFI_ROM 13 EFI ROM镜像
IMAGE_SUBSYSTEM_XBOX 14 Xbox系统
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 启动应用程序

DllCharacteristics

Image的DLL特性

宏定义 含义
0x0001 保留,必须为0
0x0002 保留,必须为0
0x0004 保留,必须为0
0x0008 保留,必须为0
IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 具有64位地址空间的ASLR
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 DLL可以在加载时重新定位
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 强制进行代码完整性检查。如果你设置了这个标志,并且section只包含未初始化的数据,那么将该section的IMAGE_SECTION_HEADER的PointerToRawData成员设置为0;否则,由于无法验证数字签名,Image将无法加载
IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 该映像与数据执行预防(DEP)兼容
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 映像可以被隔离,但不应该被隔离
IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 该映像不使用结构化异常处理(SEH)。在此映像中不能调用任何处理程序
IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 不要绑定映像
IMAGE_DLL_CHARACTERISTICS_APPCONTAINER 0x1000 映像应该在AppContainer中执行
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 一个WDM驱动
IMAGE_DLL_CHARACTERISTICS_GUARD_CF 0x4000 映像支持控制流保护(Control Flow Guard)
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 该映像是终端服务器感知的

SizeOfStackReserve

为堆栈保留的字节数

SizeOfStackCommit

要提交给堆栈的字节数

SizeOfHeapReserve

为本地保留的字节数

SizeOfHeapCommit

要为本地堆提交的字节数

LoaderFlags

null

NumberOfRvaAndSizes

可选头的其余部分中的目录条目数

DataDirectory

指向数据目录第一个IMAGE_DATA_DIRECTORY结构的指针

所需目录条目的索引号,该参数可以是以下值之一

宏定义 含义
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 特定于体系结构的数据,预留为0
IMAGE_DIRECTORY_ENTRY_BASERELOC 5 基地址重定位表
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 绑定导入表
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 COM描述符表
IMAGE_DIRECTORY_ENTRY_DEBUG 6 调试表
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 延迟导入表
IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 异常表
IMAGE_DIRECTORY_ENTRY_EXPORT 0 导出表
MAGE_DIRECTORY_ENTRY_GLOBALPTR 8 全局指针的相对虚拟地址
IMAGE_DIRECTORY_ENTRY_IAT 12 导入地址表
IMAGE_DIRECTORY_ENTRY_IMPORT 1 导入表
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 加载配置表
IMAGE_DIRECTORY_ENTRY_RESOURCE 2 资源表
IMAGE_DIRECTORY_ENTRY_SECURITY 4 安全表
IMAGE_DIRECTORY_ENTRY_TLS 9 线程本地存储表

节表 (PE_SECTION_HEADER)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#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

成员详情

成员 数据宽度 说明
Name BYTE[8]=8字节 节名称
Misc.PhysicalAddress DWORD(4字节) 节的文件地址
Misc.VirtualSize DWORD(4字节) 节的虚拟大小
VirtualAddress DWORD(4字节) 节在内存中的偏移地址
SizeOfRawData DWORD(4字节) 节在文件中对齐后的尺寸
PointerToRawData DWORD(4字节) 节区在文件中的偏移
PointerToRelocations DWORD(4字节) .obj文件有效
PointerToLinenumbers DWORD(4字节) 调试相关
NumberOfRelocations WORD(2字节) .obj文件有效
NumberOfLinenumbers WORD(2字节) 行号表中行号的数量
Characteristics DWORD(4字节) 节的属性

Name

ASCII字符串,代表节的名字

Misc.PhysicalAddress

文件地址

Misc.VirtualSize

节加载到内存时的大小,以字节为单位

VirualAddress

在内存中的偏移地址,加上ImageBase才是内存中的真正地址

SizeOfRawData

磁盘上初始化数据的大小,以字节为单位。这个值必须是IMAGE_OPTIONAL_HEADER结构文件对齐FileAlignment成员的倍数。如果该值小于VirtualSize成员,则节的其余部分将被填充为0.如果该节只包含未初始化的数据,则该成员为零

PointerToRawData

节区在文件中的偏移,又被称为FOA: File Offset Address文件偏移地址

PointerToRelocations

指向该节重定位项开始的文件指针。在.obj文件中使用,指向重定位表的指针

PointerToLinenumbers

行号表的位置

NumberOfRelocations

重定位表的个数

NumberOfLinenumbers

行号表中行号的数量

Characteristics

节的特征

宏定义 含义
0x00000000 保留
0x00000001 保留
0x00000002 保留
0x00000004 保留
IMAGE_SCN_TYPE_NO_PAD 0x00000008 该节不得填塞至下一边界线。这个标志过时了,被IMAGE_SCN_ALIGN_1BYTES取代
0x00000010 保留
IMAGE_SCN_CNT_CODE 0x00000020 该节包含可执行代码
IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 该节包含初始化的数据
IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 该节包含未初始化的数据
IMAGE_SCN_LNK_OTHER 0x00000100 保留
IMAGE_SCN_LNK_INFO 0x00000200 该节包含解释或其他信息。这只对object files有效
0x00000400 保留
IMAGE_SCN_LNK_REMOVE 0x00000800 该节将不会成为image的一部分。这只对object files有效
IMAGE_SCN_LNK_COMDAT 0x00001000 该节包含COMDAT数据。这只对object files有效。
0x00002000 保留
IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 该节包含重置TLB项中的speculative异常处理位
IMAGE_SCN_GPREL 0x00008000 该节包含通过全局指针引用的数据
0x00010000 保留
IMAGE_SCN_MEM_PURGEABLE 0x00020000 保留
IMAGE_SCN_MEM_LOCKED 0x00040000 保留
IMAGE_SCN_MEM_PRELOAD 0x00080000 保留
IMAGE_SCN_ALIGN_1BYTES 0x00100000 在1字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_2BYTES 0x00200000 在2字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_4BYTES 0x00300000 在4字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_8BYTES 0x00400000 在8字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_16BYTES 0x00500000 在16字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_32BYTES 0x00600000 在32字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_64BYTES 0x00700000 在64字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_128BYTES 0x00800000 在128字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_256BYTES 0x00900000 在256字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_512BYTES 0x00A00000 在512字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 在1024字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 在2048字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 在4096字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 在8192字节的边界上对齐数据。这只对object files有效
IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 该节包含扩展的重新定位。该节的重定位计数超过了节头中为其保留的16位。如果节头中的NumberOfRelocations字段为0xffff,则实际的重定位计数存储在第一次重定位的VirtualAddress字段中。如果设置了IMAGE_SCN_LNK_NRELOC_OVFL,并且该section中的重定位值小于0xffff,则会产生错误
IMAGE_SCN_MEM_DISCARDABLE 0x02000000 该节可以根据需要丢弃
IMAGE_SCN_MEM_NOT_CACHED 0x04000000 不能缓存该节
IMAGE_SCN_MEM_NOT_PAGED 0x08000000 该节不能分页
IMAGE_SCN_MEM_SHARED 0x10000000 该节可以在内存中共享
IMAGE_SCN_MEM_EXECUTE 0x20000000 该节可以作为代码执行
IMAGE_SCN_MEM_READ 0x40000000 该节可以读
IMAGE_SCN_MEM_WRITE 0x80000000 该节可以写

导出表 (DataDirectory[0])

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     // RVA from base of image
    DWORD   AddressOfNames;         // RVA from base of image
    DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

成员详情

成员 数据宽度 说明
Characteristics DWORD(4字节) 标志,未用
TimeDateStamp DWORD(4字节) 时间戳
MajorVersion WORD(2字节) 未用
MinorVersion WORD(2字节) 未用
Name DWORD(4字节) 指向该导出表的文件名字符串
Base DWORD(4字节) 导出函数起始序号
NumberOfFunctions DWORD(4字节) 所有导出函数的个数
NumberOfNames DWORD(4字节) 以函数名字导出的函数个数
AddressOfFunctions DWORD(4字节) 导出函数地址表RVA
AddressOfNames DWORD(4字节) 导出函数名称表RVA
AddressOfNameOrdinals DWORD(4字节) 导出函数序号表RVA

Characteristics

未使用,固定填充为0

TimeDateStamp

Image时间戳的低32位。表示链接器创建Image的日期和时间

MajorVersion

未使用,固定值填充0

MinorVersion

null

Name

指示的地址指向了一个"\0"结尾的字符串,字符串记录了导出表所在的文件的最初文件名

Base

导出函数号的起始值。DLL中第一个导出函数并不是从0开始,相当于是个偏移量,需要加上AddressOfFunctions才是最终的函数地址

NumberOfFunctions

该字段定义了文件中导出函数的总个数

NumberOfNames

该字段记录了所有定义名字函数的个数,如果该值位0,则表示所有的函数都没有定义名字

AddressOfFunctions

该指针指向了全部导出函数的入口地址的起始

AddressOfNames

该指针指向一连串的DWORD值,这些值指向了对应的定义了函数名的字符串地址

AddressOfNameOrdinals

该值也是个指针,与AddressOfNames是一一对应关系。AddressOfNameOrdinals指向了该函数在AddressOfFunctions中的索引值

https://s1.ax1x.com/2022/10/03/xQGRo9.png

导入表 (DataDirectory[1])

导入表通常包含多个模块,所以导入表可能有多个。程序运行时,需要依赖几个模块,就对应几张导入表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            // 0 for terminating null import descriptor
        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    };
    DWORD   TimeDateStamp;                  // 0 if not bound,
                                            // -1 if bound, and real date\time stamp
                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                            // O.W. date/time stamp of DLL bound to (Old BIND)

    DWORD   ForwarderChain;                 // -1 if no forwarders
    DWORD   Name;
    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;

成员详情

成员 数据宽度 说明
Characteristics DWORD(4字节) 标志 为0表示结束 没有导入描述符了
OriginalFirstThunk DWORD(4字节) RVA指向IMAGE_THUNK_DATA结构数组(桥1)
TimeDateStamp DWORD(4字节) 时间戳
ForwarderChain DWORD(4字节) 链表的前一个结构
Name DWORD(4字节) RVA,指向DLL名字,该名字以’’\0’‘结尾
FirstThunk DWORD(4字节) RVA指向IMAGE_THUNK_DATA结构数组(桥2)

Characteristics

标志位0表示结束,没有导入描述符

IMAGE_THUNK_DATA

OriginalFirstThunkFirstThunk都指向IMAGE_THUNK_DATA结构数组

https://s1.ax1x.com/2022/10/03/xQYWgx.png

IMAGE_THUNK_DATA有两种解释:

  1. DWORD最高位为0,那么该数值是一个RVA,指向IMAGE_IMPORT_BY_NAME结构,表示函数是以字符串类型的函数名导入的
  2. DWORD最高位为1,那么该数值的低31位就是函数的导出函数的序号

IMAGE_IMPORT_BY_NAME结构

1
2
3
4
typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;
    BYTE    Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
  • Hint: 导出函数地址表的索引编号,可能为空不一定准确,由编译器决定
  • Name: 这个是一个以"\0"结尾的字符串,表示函数名

OriginalFirstThunk

该字段指向一个包含了一些列结构的数组:IMAGE_THUNK_DATA,简称为桥1

桥1所指向的地址列表被定义为INT(Import Name Table)导入名称表

TimeDateStamp

时间戳

ForwarderChain

链表的前一个结构

Name

这里的Name是一个RVA,它指向该结构对应的DLL文件的名称,而这个名称是以"\0"结尾的ANSI字符串

ANSI编码是一种对ASCII码的拓展

FirstThunk

与OriginalFirstThunk相同,它指向的链表定义了针对Name这个动态链接库引入的所有导入函数,简称桥2

桥2所指向的地址列表被定义为: IAT (Import Address Table) 导入地址表

重定位表 (DataDirectory[5])

1
2
3
4
typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;                //重定位内存页的起始RVA
    DWORD   SizeOfBlock;                //重定位块的长度
} IMAGE_BASE_RELOCATION;