Optional Header

The Optional Header is the most important of the NT Headers and contains information allowing the PE file to be executed. It doesn’t have a fixed size, and the actual size can be found in the File Header’s SizeOfOptionalHeader element.

Although it’s called ‘optional’, this is only because some file types don’t contain it. The Optional Header is necessary for PE image files.

There are two versions of the Optional Header: one for 32-bit and one for 64-bit systems. The 32-bit version has one element that the 64-bit version (BaseOfData), and some of the elements are DWORD (4 bytes) in the 32-bit version and ULONGLONG (8 bytes) in the 64-bit version.

The following images show the Optional Header of a PE file as seen in PE-Bear:

PE File Optional Header
Fig 1: Optional Header, part 1
PE File Optional Header Part 2
Fig 2: Optional Header, part 2

The next sections will contain a copy of each version’s struct, followed by descriptions of the elements.

Optional Header Structures

32-Bit Optional Header

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-Bit Optional Header

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;

Optional Header Elements

Magic

The magic number is used to determine if the image is 32 or 64-bit executable or used for ROM. This table shows the three possible values of the magic number:

ValueDefinition
0x10BPE32 (32-bit) executable
0x20BPE32+ (64-bit) executable
0x107ROM image

MajorLinkerVersion/MinorLinkerVersion

The major and minor version numbers of the linker.

SizeOfCode

The size of the code (.text) section. If there are multiple sections, contains the sum of all code sections.

SizeOfInitializedData

Size of the initialized data (.data) section. If there are multiple sections, contains the sum of all initialized data sections.

SizeOfUninitializedData

The size of the uninitialized data (.bss) section. If there are multiple sections, contains the sum of all uninitialized data sections.

AddressOfEntryPoint

Address of the entry point, relative to the image base when the executable file is loaded into memory. Optional for DLLs. For program images, this points to the starting address. For device drivers, this points to the address of the initialization function. If there is no entry point then this field is zero.

BaseOfCode

Relative virtual address (RVA) of the start of the code (.text) section when the PE is loaded into memory.

BaseOfData (32-bit Only) 

Relative virtual address (RVA) of the start of the data (.data) section when the PE is loaded into memory.

ImageBase

The preferred address of the first byte of image when loaded into memory. Must be a multiple of 64K. This address is rarely used because Windows uses memory protection mechanisms like Address Space Layout Randomization (ASLR). As a result, it’s rare to see an image mapped to the preferred address. Instead, the Windows PE Loader maps the file to a different address with an unused memory range. This process would create issues because some addresses that would have been constant are now changed. The Loader addresses this via a process called PE relocation which fixes these constant addresses to work with the new image base. The relocation section (.reloc) holds data essential to this relocation process.

SectionAlignment

Holds a byte value used for section alignment in memory. This value must be greater than or equal to FileAlignment (the next element in the Optional Header structure). When loaded into memory, sections are aligned in memory boundaries that are multiples of this value. The default value of SectionAlignment is the page size for the architecture. If SectionAlignment is less than the page size then its value should match FileAlignment.

FileAlignment

This field holds a byte value that is used to align the raw data of sections on disk. The default value is 512 but it can be any number that is a power of 2 (i.e. 2x) between 512 and 64K (inclusive). However, it must be less than or equal to the value of SectionAlignment. If FileAlignment is less than SectionAlignment, then remainder will be padded with zeroes in order to maintain the alignment boundaries.

MajorOperatingSystemVersion

Major version number of the required operating system.

MinorOperatingSystemVersion

Minor version number of the required operating system.

MajorImageVersion

Major version number of the image.

MinorImageVersion

Minor version number of the image.

MajorSubsystemVersion

Major version number of the subsystem.

MinorSubsystemVersion

Minor version number of the subsystem.

Win32VersionValue

A reserved field that must be set to 0 (according to the Microsoft Docs).

SizeOfImage

The size of the image file (in bytes), including all headers. It gets rounded up to a multiple of SectionAlignment because this value is used when loading the image into memory.

SizeOfHeaders

The combined size of the MS-DOS stub, PE header(the NT Headers), and section headers. This number is rounded up to a multiple of FileAlignment.

CheckSum

The checksum of the image file, calculated using an algorithm incorporated into IMAGHELP.DLL.

Subsystem

The subsystem required to run the image. The following table contains the defined values, for reference:

ValueConstantDescription
0IMAGE_SUBSYSTEM_UNKNOWNUnknown subsystem
1IMAGE_SUBSYSTEM_NATIVEDevice drivers / native Windows processes
2IMAGE_SUBSYSTEM_WINDOWS_GUIThe Windows GUI subsystem
3IMAGE_SUBSYSTEM_WINDOWS_CUIThe Windows character subsystem
5IMAGE_SUBSYSTEM_OS2_CUIThe OS/2 character subsystem
7IMAGE_SUBSYSTEM_POSIX_CUIThe Posix character subsystem
8IMAGE_SUBSYSTEM_NATIVE_WINDOWSNative Win9x driver
9IMAGE_SUBSYSTEM_WINDOWS_CE_GUIWindows CE
10IMAGE_SUBSYSTEM_EFI_APPLICATIONAn EFI application
11IMAGE_SUBSYSTEM_EFI_BOOT_ SERVICE_DRIVERAn EFI driver with boot services
12IMAGE_SUBSYSTEM_EFI_RUNTIME_ DRIVERAn EFI driver with run-time services
13IMAGE_SUBSYSTEM_EFI_ROMAn EFI ROM image
14IMAGE_SUBSYSTEM_XBOXXBOX
16IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATIONWindows boot application.

DLLCharacteristics

Some characteristics of the image file. See the below table for the defined values.

ValueConstantDescription
0x001Reserved; must be zero.
0x002Reserved; must be zero.
0x004Reserved; must be zero.
0x008Reserved; must be zero.
0x0020IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VAThe Image can handle a high entropy 64-bit virtual address space.
0x0040IMAGE_DLLCHARACTERISTICS_
DYNAMIC_BASE
DLL can be relocated at load time.
0x0080IMAGE_DLLCHARACTERISTICS_
FORCE_INTEGRITY
Code Integrity checks are enforced.
0x0100IMAGE_DLLCHARACTERISTICS_
NX_COMPAT
Image is NX compatible.
0x0200IMAGE_DLLCHARACTERISTICS_ NO_ISOLATIONIsolation aware, but do not isolate the image.
0x0400IMAGE_DLLCHARACTERISTICS_ NO_SEHDoes not use structured exception handling.
0x0800IMAGE_DLLCHARACTERISTICS_ NO_BINDDo not bind the image.
0x1000IMAGE_DLLCHARACTERISTICS_APPCONTAINERImage must execute inside an AppContainer.
0x2000IMAGE_DLLCHARACTERISTICS_ WDM_DRIVERWDM driver.
0x4000IMAGE_DLLCHARACTERISTICS_GUARD_CFImage supports Control Flow Guard.
0x8000IMAGE_DLLCHARACTERISTICS_ TERMINAL_SERVER_AWARETerminal Server aware.

SizeOfStackReserve

The size of the stack to reserve. Note that only SizeOfStackCommit is committed. The rest is made available one page at a time until the reserve size is reached.

SizeOfStackCommit

The size of the stack to commit.

SizeOfHeapReserve

The size of local heap space to reserve. Note that only SizeOfHeapCommit is committed. The rest is made available one page at a time until the reserve size is reached.

SizeOfHeapCommit

The size of local heap space to commit.

LoaderFlags

Reserved; according to the Microsoft docs, this must be set to zero.

NumberOfRvaAndSizes

The number of entries in the data directory array.

DataDirectory

This is one of the most important members of the Optional Header. It contains an array of IMAGE_DATA_DIRECTORY structures. The Data Directory is important enough that it it has its own page.

Scroll to Top