《Windows PE》3.2.3 NT头-扩展头

news2024/11/23 21:16:57

扩展头(可选标头仅限映像文件)

OptionalHeader字段描述了可执行文件的更多细节和布局信息,如图像基址、入口点、数据目录、节表等。它的具体结构取决于文件的机器架构,可以是IMAGE_OPTIONAL_HEADER32(32位)或IMAGE_OPTIONAL_HEADER64(64位)结构体。

PE文件的扩展头位于文件头之后,其结构可以根据具体的文件类型和操作系统的架构而有所不同。

每个映像文件都有一个用于向加载程序提供信息的可选标头。 此标头是可选标头,因为某些文件(特别是obj对象文件)没有此标头。 对于映像文件,此标头是必需的。对象文件可以具有可选标头,但通常此标头在对象文件中没有函数,只是为了增加其大小。

 注意

1.可选标头的大小不是固定的。 COFF 标头中的 SizeOfOptionalHeader 字段必须用于验证对特定数据目录的文件的探测是否未超出 SizeOfOptionalHeader。 有关详细信息,请参阅MSDN COFF 文件标头(对象和映像)。

2.还应该使用可选标头的 NumberOfRvaAndSizes 字段(数据目录的项目数量)来确保对特定数据目录条目的探测不会超出可选标头。 此外,请务必验证可选标头魔数,以确保格式兼容性。

可选标头魔数确定映像是 PE32 还是 PE32+ (64位PE可执行文件。

PE 格式

0x10b

PE32

0x20b

PE32+

PE32+ 映像允许使用 64 位地址空间,同时会将映像大小限制为 2 GB。 其他 PE32+ 修改会在各自的部分中进行介绍。

可选标头本身具有三个主要部分。

偏移量 (PE32/PE32+)

大小 (PE32/PE32+)

标头部分

说明

0

28/24

标准字段

为 COFF 的所有实现(包括 UNIX)定义的字段。

28/24

68/88

特定于 Windows 的字段

用于支持 Windows(例如子系统)的特定功能的其他字段。

96/112

变量

数据目录

在映像文件中找到并由操作系统使用的特殊表(例如,导入表和导出表)的地址/大小对。

●可选标头标准字段(仅限映像)

可选标头的前八个字段是为 COFF 的每个实现定义的标准字段。 这些字段包含可用于加载和运行可执行文件的常规信息。 对于 PE32+ 格式,它们保持不变。

Offset

大小

字段

说明

0

2

Magic

标识映像文件状态的无符号整数。 最常见的数字是 0x10B,它将映像文件标识为普通可执行文件。 0x107 将映像文件标识为 ROM 映像,0x20B 将映像文件标识为 PE32+ 可执行文件。

2

1

MajorLinkerVersion

链接器主版本号。

3

1

MinorLinkerVersion

链接器次要版本号。

4

4

SizeOfCode

代码(文本)段的大小,或者如果有多个部分,则是所有代码段的和。

8

4

SizeOfInitializedData

初始化数据部分的大小,或者如果有多个数据部分,则是所有此类部分的和。

12

4

SizeOfUninitializedData

未初始化数据部分 (BSS) 的大小,或者如果有多个 BSS 部分,则是所有此类部分的和。

16

4

AddressOfEntryPoint

可执行文件加载到内存中时相对于映像基址的入口点地址。 对于程序映像,这是起始地址。 对于设备驱动程序,这是初始化函数的地址。 入口点对于 DLL 是可选的。 不存在入口点时,此字段必须为零。

20

4

BaseOfCode

加载到内存中后相对于代码开头部分映像基址的地址。

【注】PE32 包含位于 BaseOfCode 之后的此附加字段,此字段在 PE32+ 中不存在。

Offset

大小

字段

说明

24

4

BaseOfData

加载到内存中后相对于数据开头部分映像基址的地址。

●可选标头 Windows 特定字段(仅限映像)

接下来的 21 个字段是 COFF 可选标头格式的扩展。 它们包含 Windows 中的链接器和加载程序所需的其他信息。

偏移量 (PE32/PE32+)

大小(PE32/PE32+)

字段

说明

28/24

4/8

ImageBase

映像加载到内存中后第一个字节的首选地址;必须是 64 K 的倍数。DLL 的默认值为 0x10000000 Windows CE EXE 的默认值为 0x00010000。 Windows NT、Windows 2000、Windows XP、Windows 95、Windows 98 和 Windows Me 的默认值为 0x00400000。

32/32

4

SectionAlignment

各部分加载到内存中时的对齐值(以字节为单位)。 它必须大于或等于 FileAlignment(4KB)。 默认值为体系结构的页面大小。

36/36

4

FileAlignment

用于使映像文件中各部分的原始数据一致的对齐系数(以字节为单位)。 该值应为 2 的幂次方,介于 512 和 64K 之间(含)。 默认值为 512。 如果 SectionAlignment 小于体系结构的页面大小,则 FileAlignment 必须与 SectionAlignment 匹配。

40/40

2

MajorOperatingSystemVersion

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

42/42

2

MinorOperatingSystemVersion

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

44/44

2

MajorImageVersion

映像的主版本号。

46/46

2

MinorImageVersion

映像的次要版本号。

48/48

2

MajorSubsystemVersion

子系统的主版本号。

50/50

2

MinorSubsystemVersion

子系统的次要版本号。

52/52

4

Win32VersionValue

保留,必须为零。

56/56

4

SizeOfImage

映像加载到内存中时的映像大小(以字节为单位),包括所有标头。 它必须是 SectionAlignment (4KB)的倍数。

60/60

4

SizeOfHeaders

MS DOS 存根、PE 标头和节标头的组合大小,其向上舍入到 FileAlignment (200H)的倍数。

64/64

4

CheckSum

映像文件的校验和。 用于计算校验和的算法已合并到 IMAGHELP.DLL 中。 加载时会检查以下内容是否有效:所有驱动程序、启动时加载的任何 DLL 以及加载到关键 Windows 进程中的任何 DLL。链接器选项可设置。

68/68

2

子系统

运行此映像所需的子系统。 有关详细信息,请参阅MSDN Windows 子系统。

70/70

2

DllCharacteristics

有关详细信息,请参阅MSDN此规范后面的 DLL 特征。

72/72

4/8

SizeOfStackReserve

要保留的堆栈的大小。 仅提交 SizeOfStackCommit;其余部分一次提供一页,直到达到保留大小。默认1MB大小。

76/80

4/8

SizeOfStackCommit

要提交的堆栈的大小。默认4KB大小。

80/88

4/8

SizeOfHeapReserve

要保留的本地堆空间的大小。 仅提交 SizeOfHeapCommit;其余部分一次提供一页,直到达到保留大小。默认1MB大小。

84/96

4/8

SizeOfHeapCommit

要提交的本地堆空间的大小。默认4KB大小。

88/104

4

LoaderFlags

保留,必须为零。

92/108

4

NumberOfRvaAndSizes

可选标头剩余部分中数据目录项的数目。 每项都描述位置和大小。

下面是在winnt.h头文件中扩展头结构体的定义:

●IMAGE_OPTIONAL_HEADER32

typedef struct _IMAGE_OPTIONAL_HEADER {

    //

    // Standard fields.

    //

    WORD    Magic;                   // PE文件的魔数,标识文件类型和操作系统架构

    BYTE    MajorLinkerVersion;        //链接器的主版本号

    BYTE    MinorLinkerVersion;        //链接器的次版本号

    DWORD   SizeOfCode;               //执行代码的大小(字节)

    DWORD   SizeOfInitializedData;     //已初始化数据的大小(字节)

    DWORD   SizeOfUninitializedData;   //未初始化数据的大小(字节)

    DWORD   AddressOfEntryPoint;       //程序的入口点(相对于映像基址的偏移量)

    DWORD   BaseOfCode;               //代码节的起始虚拟地址

    DWORD   BaseOfData;               //数据节的起始虚拟地址

    //

    // NT additional fields.

    //

    DWORD   ImageBase;                //可执行文件的首选基址(32位虚拟内存地址)

    DWORD   SectionAlignment;         //节在内存中对齐的大小

    DWORD   FileAlignment;            //节在文件中对齐的大小

    WORD    MajorOperatingSystemVersion;//操作系统的主版本号要求

    WORD    MinorOperatingSystemVersion;//操作系统的次版本号要求

    WORD    MajorImageVersion;        //可执行文件的主要版本号

    WORD    MinorImageVersion;        //可执行文件的次要版本号

    WORD    MajorSubsystemVersion;     //子系统的主要版本号要求

    WORD    MinorSubsystemVersion;     //子系统的次要版本号要求

    DWORD   Win32VersionValue;        //保留字段,用于兼容性

    DWORD   SizeOfImage;              //可执行文件在内存中的大小

    DWORD   SizeOfHeaders;            //文件头和节表的总大小(字节)

    DWORD   CheckSum;                 // PE文件的校验和

    WORD    Subsystem;                //可执行文件所依赖的子系统

    WORD    DllCharacteristics;        // DLL文件的特性

    DWORD   SizeOfStackReserve;        //为堆栈保留的内存大小(32位,1MB)

    DWORD   SizeOfStackCommit;        //实际分配给堆栈的内存大小(32位,4KB)

    DWORD   SizeOfHeapReserve;        //为堆保留的内存大小(32位,1MB)

    DWORD   SizeOfHeapCommit;         //实际分配给堆的内存大小(32位,4KB)

    DWORD   LoaderFlags;              //加载器标志

    DWORD   NumberOfRvaAndSizes;       //数据目录项的数量

    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//数据目录表

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

●IMAGE_OPTIONAL_HEADER64

typedef struct _IMAGE_OPTIONAL_HEADER64 {

    //

    // Standard fields.

    //

    WORD    Magic;                  // PE文件的魔数,标识文件类型和操作系统架构

    BYTE    MajorLinkerVersion;      //链接器的主版本号

    BYTE    MinorLinkerVersion;      //链接器的次版本号

    DWORD   SizeOfCode;              //执行代码的大小(字节)

    DWORD   SizeOfInitializedData;    //已初始化数据的大小(字节)

    DWORD   SizeOfUninitializedData;  //未初始化数据的大小(字节)

    DWORD   AddressOfEntryPoint;     //程序的入口点(相对于映像基址的偏移量)

    DWORD   BaseOfCode;              //代码节的起始虚拟地址

    //DWORD   BaseOfData;             //数据节的起始虚拟地址(缺失字段

    //

    // NT additional fields.

    //

    ULONGLONG ImageBase;                   //可执行文件的首选基址(64位虚拟内存地址)

    DWORD   SectionAlignment;            //节在内存中对齐的大小

    DWORD   FileAlignment;               //节在文件中对齐的大小

    WORD    MajorOperatingSystemVersion;  //操作系统的主版本号要求

    WORD    MinorOperatingSystemVersion;  //操作系统的次版本号要求

    WORD    MajorImageVersion;           //可执行文件的主要版本号

    WORD    MinorImageVersion;           //可执行文件的次要版本号

    WORD    MajorSubsystemVersion;        //子系统的主要版本号要求

    WORD    MinorSubsystemVersion;        //子系统的次要版本号要求

    DWORD   Win32VersionValue;           //保留字段,用于兼容性

    DWORD   SizeOfImage;                 //可执行文件在内存中的大小

    DWORD   SizeOfHeaders;               //文件头和节表的总大小(字节)

    DWORD   CheckSum;                   // PE文件的校验和

    WORD    Subsystem;                   //可执行文件所依赖的子系统

    WORD    DllCharacteristics;          // DLL文件的特性

    ULONGLONG SizeOfStackReserve;          //为堆栈保留的内存大小(64位,1MB)

    ULONGLONG SizeOfStackCommit;           //实际分配给堆栈的内存大小(64位,4KB)

    ULONGLONG SizeOfHeapReserve;           //为堆保留的内存大小(64位,1MB)

    ULONGLONG SizeOfHeapCommit;            //实际分配给堆的内存大小(64位,4KB)

    DWORD   LoaderFlags;                 //加载器标志

    DWORD   NumberOfRvaAndSizes;         //数据目录项的数量

    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//数据目录表

} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

●Magic Number(魔数):一个2字节的字段,指示文件类型和操作系统架构。常见的值有:

1.PE32(32位):0x10B

2.PE32+(64位):0x20B

我们可以通过这个字段来判断一个PE文件是32位PE文件还是64位PE文件。

●MajorLinkerVersion、MinorLinkerVersion:链接器的版本号。指示用于创建PE文件的链接器的主要和次要版本号。对执行PE文件没有任何影响。

●SizeOfCode:代码段的大小,以字节为单位。指示代码段的实际大小。该大小是基于文件对齐后的大小,而非内存对齐后的大小。PE文件以200H(512)字节为单位对齐。

●SizeOfInitializedData:已初始化数据段的大小,以字节为单位。指示已初始化数据段的实际大小。同样是基于文件对齐后的大小。

●SizeOfUninitializedData:未初始化数据段的大小,以字节为单位。指示未初始化数据段的实际大小。同样是基于文件对齐后的大小。

●AddressOfEntryPoint:程序入口点的RVA地址,相对于映像基址的偏移量。它指示PE文件在加载到内存后执行的第一条指令的地址。

程序的入口地址+ImageBase基址=程序在内存中开始执行的首地址(虚拟内存地址)。

●BaseOfCode:代码段的起始虚拟RVA地址。它指示代码段在内存中的起始位置。

●BaseOfData:数据段的起始虚拟RVA地址。它指示数据段在内存中的起始位置。

●ImageBase:可执行文件的首选基址(虚拟内存地址)。它指示PE文件在内存中加载时的首选基址。

●SectionAlignment:节在内存中的对齐大小。它指示节在内存中的边界对齐方式。通常内存以1000H(4KB)为单位对齐。

●FileAlignment:节在文件中的对齐大小。它指示节在PE文件中的边界对齐方式。通常内存以2000H(512)字节为单位对齐。

●MajorOperatingSystemVersion、MinorOperatingSystemVersion:所需的主操作系统版本号和次操作系统版本号。指示PE文件所需的最低操作系统版本。

●MajorImageVersion、MinorImageVersion:可执行文件的主要版本号和次要版本号。本PE映像文件的版本号。如果在这里存放版本号,则软件更新,网络升级时可以用于比对版本号。

●MajorSubsystemVersion、MinorSubsystemVersion:所需的主子系统版本号和次子系统版本号。指示PE文件所需的最低子系统版本。

●Win32VersionValue:保留字段,必须设置为0,用于兼容性。

●SizeOfImage:映像在内存中的大小,以字节为单位。指示PE文件(包括所有节区)在内存中占用的总大小。

●SizeOfHeaders:文件头和节表的总大小,以字节为单位。指示PE文件头部和节表的实际大小。

●CheckSum:PE文件的校验和。用于验证文件的完整性。校验和,在大多数的PE文件中,该值是0。但在一些内核模式的驱动程序和系统DLL中,该值则是必须存在且是正确的,比如kernel32.dll中PE的校验和是 0011E97Eh。在VS编译器的“项目属性”>“链接器”>“高级”>“设置校验和”选项中默认是关闭的。

●Subsystem:可执行文件所依赖的子系统类型。常见的值有:IMAGE_SUBSYSTEM_WINDOWS_GUI(2)表示图形用户界面子系统。IMAGE_SUBSYSTEM_WINDOWS_CUI(3)表示控制台用户界面子系统等。

我们可以在winnt.h头文件中查到这个字段的值,如下所示:

常量

Value

说明

IMAGE_SUBSYSTEM_UNKNOWN

0

未知子系统

IMAGE_SUBSYSTEM_NATIVE

1

设备驱动程序和本机 Windows 进程

IMAGE_SUBSYSTEM_WINDOWS_GUI

2

Windows 图形用户界面 (GUI) 子系统

IMAGE_SUBSYSTEM_WINDOWS_CUI

3

Windows 字符子系统

IMAGE_SUBSYSTEM_OS2_CUI

5

OS/2 字符子系统

IMAGE_SUBSYSTEM_POSIX_CUI

7

Posix 字符子系统

IMAGE_SUBSYSTEM_NATIVE_WINDOWS

8

本机 Win9x 驱动程序

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

Windows 启动应用程序。

●DllCharacteristics:DLL文件的特性标志。这个字段指定了DLL文件的一些特性和行为,如是否支持ASLR(地址空间布局随机化)、是否支持DEP(数据执行保护)、是否终止线程时卸载DLL等。常见的标志值包括IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE(0x40)表示支持ASLR,IMAGE_DLLCHARACTERISTICS_NX_COMPAT(0x100)表示支持DEP等。

常量

Value

说明

0x0001

保留,必须为零。

0x0002

保留,必须为零。

0x0004

保留,必须为零。

0x0008

保留,必须为零。

IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA

0x0020

映像可处理高熵 64 位虚拟地址空间。

IMAGE_DLLCHARACTERISTICS_
DYNAMIC_BASE

0x0040

DLL 可以在加载时重定位。

IMAGE_DLLCHARACTERISTICS_
FORCE_INTEGRITY

0x0080

强制实施了代码完整性检查。

IMAGE_DLLCHARACTERISTICS_
NX_COMPAT

0x0100

该映像与 NX 兼容。

IMAGE_DLLCHARACTERISTICS_ NO_ISOLATION

0x0200

隔离感知,但不隔离映像。

IMAGE_DLLCHARACTERISTICS_ NO_SEH

0x0400

不使用结构化异常 (SE) 处理。 该映像中无法调用任何 SE 处理程序。

IMAGE_DLLCHARACTERISTICS_ NO_BIND

0x0800

请勿绑定此映像。

IMAGE_DLLCHARACTERISTICS_APPCONTAINER

0x1000

映像必须在 AppContainer 中执行。

IMAGE_DLLCHARACTERISTICS_ WDM_DRIVER

0x2000

WDM 驱动程序。

IMAGE_DLLCHARACTERISTICS_GUARD_CF

0x4000

映像支持控制流保护。

IMAGE_DLLCHARACTERISTICS_ TERMINAL_SERVER_AWARE

0x8000

终端服务器感知。

   

以HelloWorld32.exe为例,其PE文件该字段的值为8140H,即支持终端服务器,应在AppContainer中执行,DLL可以被加载器基址随机化,例如X64 PE文件如果使用固定基址,则需要将DllCharacteristics字段改为8120H。而X86 PE文件改为8100H

以VS2017版本为例,在使用VS编译时,关于基址的设置如图3-8所示。默认为随机基址。我们也可以将其改为“否”,设置固定基址。

基址随机化是一种安全机制,旨在增加系统的抵抗力,防止恶意攻击者利用已知的内存布局来定位和执行恶意代码。基址随机化通过在每次加载可执行文件时随机分配基址(基地址)来实现。这意味着可执行文件的代码和数据的实际内存位置在每次加载时都会发生变化。

为了支持基址随机化,PE文件中的重定位节区记录了需要进行地址重定位的位置和方式。重定位节区包含了可执行文件中使用绝对地址或固定偏移的位置,这些位置需要在加载时进行动态调整,以适应新的基址。当加载器加载PE文件时,会根据重定位节区的信息,计算并更新这些位置的值,使它们指向正确的内存位置。

因此,在Windows 10环境下编译的PE文件会包含重定位节区,以便在加载时进行地址重定位,实现基址随机化的安全机制。这有助于提高系统的安全性,减少恶意攻击的成功率。

图3-8 VS链接器关于基址的设置选项

●SizeOfStackReserve:为栈保留的内存大小。指定在进程初始化时为栈分配的虚拟内存大小。

●SizeOfStackCommit:实际分配给栈的内存大小。指定在进程运行时实际使用的栈内存大小。

●SizeOfHeapReserve:为堆保留的内存大小。指定在进程初始化时为堆分配的虚拟内存大小。

●SizeOfHeapCommit:实际分配给堆的内存大小。指定在进程运行时实际使用的堆内存大小。

图3-9 修改链接器选项设置堆栈大小

通常编译器初始化时保留栈和堆的大小为1MB,而实际为栈和堆提交的大小为4KB。

这4个值可以在链接时修改的,如图3-9所示。在VS项目属性“链接器”可以设置。例如我们观察WinHex中的32位和64位记事本程序堆和栈的大小。

1.32位记事本

    DWORD   SizeOfStackReserve;        //为堆栈保留的内存大小(32位,256KB)

    DWORD   SizeOfStackCommit;        //实际分配给堆栈的内存大小(32位,68KB)

    DWORD   SizeOfHeapReserve;        //为堆保留的内存大小(32位,1MB)

    DWORD   SizeOfHeapCommit;         //实际分配给堆的内存大小(32位,4KB)

2.64位记事本

    ULONGLONG SizeOfStackReserve;      //为堆栈保留的内存大小(64位,512KB)

    ULONGLONG SizeOfStackCommit;       //实际分配给堆栈的内存大小(64位,68KB)

    ULONGLONG SizeOfHeapReserve;       //为堆保留的内存大小(64位,1MB)

    ULONGLONG SizeOfHeapCommit;        //实际分配给堆的内存大小(64位,4KB)

练习

       请读者将HelloWorld.c分别编译生成32位和64位程序,然后在WinHex中观察默认堆和栈的大小。

●LoaderFlags:加载器标志。这个字段保留供操作系统使用,用于指定加载器的一些行为和配置。

●NumberOfRvaAndSizes:数据目录项的数量。指示数据目录表中的目录项数量。

在32位和64位PE文件中,扩展头中的数据目录表中的目录项数量都是16个。这个字段的值是可以修改的。接下来我们就动手修改并测试。

实验十四:验证并修改32位和64位PE文件数据目录项的数量

我们分别在Windows10和XP两个不同操作系统环境中测试32位和64位HelloWorld.exe PE文件。我们分别在Windows10和XP系统中,分别编译HelloWorld.exe的汇编版本和C语言版本。在Windows10中编译环境为masm32和VS2017,XP系统中使用的编译环境为masm32和VC6.0。

●Windows 10操作系统测试环境

1.32位HelloWorld.exe(Win10汇编版本)文件偏移地址00000164H地址处,将默认0010H修改为0000~0010H之间的任一值,我们会发现,当数据目录项的数目大于等于6时,PE文件可以在Windows 10系统正常运行。如果数据目录项的数目小于6时,PE文件可以在Windows 10系统则不能正常运行。

2.32位HelloWorld32.exe(Win10 C语言版本)同样如此。

3.64位HelloWorld32.exe(Win10 C语言版本)同样如此。

4.32位HelloWorld.exe(Win XP汇编版本)文件偏移地址0000013CH地址处,将默认0010H修改为0000~0010H之间的任一值,我们会发现,当数据目录项的数目大于等于2时,PE文件可以在Windows 10系统正常运行。如果数据目录项的数目小于2时,PE文件可以在Windows 10系统则不能正常运行。

5.32位HelloWorld32.exe(Win XP C语言版本)同样如此。

●Windows XP操作系统测试环境

1.32位HelloWorld.exe(Win XP汇编版本)文件偏移地址0000013CH地址处,将默认0010H修改为0000~0010H之间的任一值,我们会发现,当数据目录项的数目大于等于2时,PE文件可以在Windows 10系统正常运行。如果数据目录项的数目小于2时,PE文件可以在Windows 10系统则不能正常运行。

2.32位HelloWorld32.exe(Win XP C语言版本)同样如此。

练习

       请读者分别修改测试32位和64位记事本程序数据目录表中的目录项数量。

 

结论

       1.数据目录表中的目录项数量是可以被修改的。

       2.数据目录表中的目录项数量的最小值与编译器的版本和操作系统的运行环境相关。

       3.PE文件所需数据目录项与具体的PE文件相关,不同的PE文件所依赖的数据目录项有所不同。

       稍后我们将详细分析各个数据目录项所代表的含义。

●DataDirectory:数据目录表。这是一个由IMAGE_DATA_DIRECTORY结构组成的数组,用于指定PE文件中各个数据结构的位置和大小

每个数据目录都提供 Windows 使用的表或字符串的地址和大小。 这些数据目录条目已全部加载到内存中,以便系统可以在运行时使用它们。数据目录是具有以下声明的 8 字节字段:

1.IMAGE_DATA_DIRECTORY结构

struct IMAGE_DATA_DIRECTORY

{

    public uint VirtualAddress;  // 数据结构的虚拟地址

    public uint Size;                 // 数据结构的大小

};

第一个字段 (VirtualAddress) 实际上是表的 RVA。 RVA 是加载表后相对于映像基址的表地址。 第二个字段提供以字节为单位的大小。 下表中列出了构成可选标头的最后一部分的数据目录。

 注意

目录数不是固定的。在查找特定目录之前,请检查可选标头中的 NumberOfRvaAndSizes 字段。此外,不要假定此表中的 RVA 指向节的开头,或者包含特定表的节具有特定名称。

偏移量 (PE/PE32+)

大小

字段

说明

96/112

8

导出表

导出表地址和大小。 有关详细信息,请参阅MSDN .edata 部分(仅限映像)

104/120

8

导入表

导入表地址和大小。 有关详细信息,请参阅MSDN  .idata 部分

112/128

8

资源表

资源表地址和大小。 有关详细信息,请参阅MSDN  .rsrc 部分

120/136

8

异常表

异常表地址和大小。 有关详细信息,请参阅MSDN  .pdata 部分

128/144

8

证书表

属性证书表地址和大小。 有关详细信息,请参阅MSDN  属性证书表(仅限映像)

136/152

8

基址重定位表

基址重定位表地址和大小。 有关详细信息,请参阅MSDN  .reloc 部分(仅限映像)

144/160

8

调试

调试数据起始地址和大小。 有关详细信息,请参阅 MSDN  .debug 部分

152/168

8

体系结构

已保留,必须为 0

160/176

8

全局指针

要存储在全局指针寄存器中的值的 RVA 此结构的大小成员必须设置为零。

168/184

8

TLS

线程本地存储 (TLS) 表地址和大小。 有关详细信息,请参阅 MSDN  .tls 部分

176/192

8

加载配置表

加载配置表地址和大小。 有关详细信息,请参阅MSDN  加载配置结构(仅限映像)

184/200

8

绑定导入

绑定导入表地址和大小。

192/208

8

IAT

导入地址表地址和大小。 有关详细信息,请参阅MSDN  导入地址表

200/216

8

延迟导入描述符

延迟导入描述符地址和大小。 有关详细信息,请参阅MSDN  延迟加载导入表(仅限映像)

208/224

8

CLR 运行时标头

CLR 运行时标头地址和大小。 有关详细信息,请参阅MSDN  .cormeta 部分(仅限对象)

216/232

8

保留,必须为零

3.16个数据目录表的目录项说明

■导出表(Export Table)

存储可执行文件导出的函数和符号信息,使其他模块可以访问这些导出。

■导入表(Import Table)

存储可执行文件导入的函数和符号信息,描述了可执行文件所依赖的其他模块和它们所提供的函数。

■资源表(Resource Table)

存储可执行文件使用的资源(如图标、位图、字符串等)的位置和大小信息。

■异常表(Exception Table)

存储可执行文件中的异常处理程序信息,用于处理程序中可能发生的异常情况。

■安全表(Security Table)

存储有关可执行文件的安全性设置和数字签名等信息。

■基址重定位表(Base Relocation Table)

存储基址重定位信息,用于处理可执行文件在加载时的基址变化,以便正确地调整内存中的地址。

■调试表(Debug Table)

存储调试符号和调试信息,用于程序的调试和错误追踪。

■体系结构相关(Architecture-specific)

存储与特定体系结构相关的数据,如IA-32特定的扩展数据。

■全局指针寄存器表(Global Pointer Register Table)

存储全局指针寄存器(如GP)的位置和大小信息。

■TLS表(Thread Local Storage Table)

存储线程本地存储(Thread Local Storage)相关的数据结构和信息。

■加载配置表(Load Configuration Table)

存储可执行文件的加载配置信息,如安全设置、堆栈大小等。

■绑定导入表(Binding Table)

存储可执行文件中的模块绑定信息,用于实现延迟绑定(lazy binding)和符号决议。

■导入函数地址表(Import Address Table)

存储导入函数的地址信息,用于在运行时解析和更新导入函数的地址。

■延迟加载导入表(Delay Load Import Table)

存储延迟加载导入函数的信息,用于在需要时才加载并解析导入函数。

■ CLR运行时头(CLR Runtime Header)

存储与托管代码和CLR(Common Language Runtime)相关的信息。

■保留(Reserved)

保留未使用的数据目录项。

 注意

具体的数据目录表的目录项可能会因不同的可执行文件格式而有所不同。上述列表是PE格式下常见的数据目录表的目录项,其他格式可能具有不同的目录项和描述。在实际使用中,建议参考相应可执行文件格式的文档以获得准确的目录项注释和描述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2182026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单线性回归分析-基于R语言

本题中&#xff0c;在不含截距的简单线性回归中&#xff0c;用零假设对统计量进行假设检验。首先&#xff0c;我们使用下面方法生成预测变量x和响应变量y。 set.seed(1) x <- rnorm(100) y <- 2*xrnorm(100) &#xff08;a&#xff09;不含截距的线性回归模型构建。 &…

如何选择合适的跨境网络专线?

选择合适的跨境网络专线对于保障企业的国际业务顺畅运行至关重要。以下是一些选择跨境网络专线时可以参考的关键点&#xff1a; 服务商的信誉和经验&#xff1a;首先考察服务商的市场声誉和行业经验。一个好的服务商应该拥有良好的客户评价和成功案例&#xff0c;这表明他们有能…

心觉:如何抓住宇宙送来的运气和机会?

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作186/1000天 赚钱需要系统学习吗 你会发现生活中没什么学历&#xff0c;知道的也没你多&#xff0c;行动力也不一定有你强&#x…

【Orange Pi 5嵌入式应用编程】-用户空间GPIO控制

用户空间GPIO控制 文章目录 用户空间GPIO控制1、嵌入式Linux的GPIO子系统介绍1.1 sysfs文件访问GPIO1.2 通过字符设备访问GPIO1.3 库与工具2、RK3588的GPIO介绍3、用户空间操作GPIO编程3.1 硬件准备3.2 通过libgpio操作GPIO3.2.1 GPIO输出3.2.3 GPIO输入3.2.3 边沿事件检测(中断…

Tomcat监控与调优:比Tomcat Manager更加强大的Psi-Probe

这是一款 Tomcat 管理和监控工具&#xff0c;前身是 Lambda Probe。由于 Lambda Probe 2006不再更新&#xff0c;所以 PSI Probe 算是对其的一个 Fork 版本并一直更新至今。 Probe psi-probe是在相同的开源许可证(GPLV2)下分发的社区驱动的 Lambda Probe &#xff0c;psi-pro…

笔记整理—linux进程部分(4)进程状态与守护进程

进程的几种重要状态&#xff0c;就绪态&#xff1b;运行态&#xff1b;僵尸态&#xff1b;等待态&#xff08;浅度睡眠、深度睡眠&#xff09;&#xff1b;停止态。 就单核CPU而言&#xff0c;在同一时间只能运行一个进程&#xff0c;但实际上要运行的进程不止一个&#xff0c;…

手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告)

手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告) 前言 在去年的差不多这个时候&#xff0c;我们做了一遍外置配件的选型&#xff0c;筛选过滤了一批USB蓝牙配件和type-c转usb的模块。详情可参考《外置配件的电商价格和下载链接的选型.docx》一文&#xff1a;蓝牙电话…

Chainlit集成LlamaIndex并使用通义千问实现和数据库交互的网页对话应用(text2sql)

前言 我在之前的几篇文章中写了如何使用Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用&#xff0c;但是发现Langchain的几种和数据库交互的组件都不够让我满意&#xff0c;虽然已经满足了大部分场景的需求&#xff0c;但是问题还是很多&#xff0c;比如…

Frp服务部署

我这里使用的0.44版本部署如果有其他版本需求范我跟github自行下载 https://github.com/fatedier/frp/releases 相关中文文档可以查看 https://github.com/fatedier/frp/blob/dev/README_zh.md 为了方便我这里使用了同一台服务器部署的 如果需要内网穿透 Frps部署在公网 Frp…

亚洲市场|人工智能对固态硬盘SSD需求影响

随着人工智能(AI)技术的快速发展&#xff0c;对于高效能存储的需求也在日益增长。在亚洲市场中&#xff0c;固态硬盘(SSD)作为关键的数据存储设备&#xff0c;其重要性不言而喻。 扩展阅读&#xff1a; 内存&#xff1a;生成式AI带来全新挑战与机遇 这可能是最清晰的AI存储数…

数学语言符号汇总

&#xff08;任意&#xff09; &#xff08;存在&#xff09; 子集和真子集 一些集合关系符号的Latex写法&#xff1a; 的Latex写法为\not\subset 的Latex写法是\subsetneqq&#xff0c;否定式写法是\subseteqq 1&#xff09;子集 注意&#xff1a;子集只有两种&#xff1…

php email功能实现:详细步骤与配置技巧?

php email发送功能详细教程&#xff1f;如何使用php email服务&#xff1f; 无论是用户注册、密码重置&#xff0c;还是订单确认&#xff0c;电子邮件都是与用户沟通的重要手段。AokSend将详细介绍如何实现php email功能&#xff0c;并提供一些配置技巧&#xff0c;帮助你更好…

C/C++逆向:数据类型识别

在逆向工程中&#xff0c;数据类型识别是理解程序逻辑的重要步骤&#xff0c;因为它直接影响对程序逻辑和功能的理解&#xff0c;识别出数据类型有助于确定变量的含义和函数的行为。在分析恶意软件或者寻找安全漏洞时&#xff0c;识别数据类型能够帮助发现代码中的潜在问题。例…

CTFshow 命令执行 web29~web36(正则匹配绕过)

目录 web29 方法一&#xff1a;include伪协议包含文件读取 方法二&#xff1a;写入文件 方法三&#xff1a;通识符 web30 方法一&#xff1a;filter伪协议文件包含读取 方法二&#xff1a;命令执行函数绕过 方法三&#xff1a;写入文件 web31 方法一&#xff1a;filter伪…

等保测评:企业数字安全的坚实盾牌

1.1 企业数字化转型的浪潮 在当今时代&#xff0c;企业数字化转型的浪潮正以前所未有的速度席卷全球&#xff0c;据IDC预测&#xff0c;到2023年&#xff0c;全球数字化转型支出将达到惊人的2.3万亿美元。这一趋势不仅重塑了企业的运营模式&#xff0c;更对企业的信息安全提出…

redis面试-2024

1、Redis的基本数据结构类型 string、list、set、hash、zet。还有三种特殊类型&#xff1a;Geospatial、Hyperloglog、bitMap。 2、各数据类型对应的场景 3、redis快的原因 *基于内存 内存读写效率远高于磁盘读写&#xff0c;省去磁盘IO操作 *存储形式 Redis作为K-V键值对…

从一到无穷大 #36 Lindorm 宽表:东西互联,南北互联,AI一体

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言索引列存索引全文索引向量索引二级索引 AI赋能时序宽表 LTS&#xff08;Lindorm …

面向MQTT基础物联网网络的Age-of-Information感知的保留消息策略

论文标题&#xff1a; 英文&#xff1a;AoI-aware Retained Message Policy in MQTT-based IoT Networks中文&#xff1a;面向MQTT基础物联网网络的Age-of-Information感知的保留消息策略 作者信息&#xff1a; Youngjun Kim 和 Yeunwoong Kyung工作单位&#xff1a;Youngju…

Unity3D播放GIF图片使用Animation来制作动画

系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、下载GIF动图,用PS制作导出帧动画图片👉二、使用Animation制作动画👉三、脚本控制动画播放👉壁纸分享👉总结👉前言 unity播放gif图片,本身是不支持的,但是可以使用其他方法来实现, 1.有一种使用System…

短链接生成-短链接-短网址-短链接生成接口-短链接转换接口-短网址URL生成-短链接地址-短网址-短域名-短链接【快证api】

短网址接口是指用于将长网址缩短为短网址的应用程序编程接口&#xff08;API&#xff09;。以下是关于短网址接口的详细介绍&#xff1a; 一、短网址接口的功能 短网址接口的主要功能是将冗长的网址缩短为简洁的短网址&#xff0c;便于在社交媒体、邮件、短信等渠道中分享和传…