Every image file has an Optional Header that provides information to the loader. This header is also referred to the PE Header. This header is optional in the sense that some files (specifically, object files) do not have it. For image files, this header is required. An object file may have an optional header, but generally this header has no function in an object file except to increase size.
Note that the size of the optional header is not fixed. The Optional Header Size in the COFF Header (see Section 3.3 COFF File Header (Object & Image)) must be used in conjunction with the Optional Header’s Number of Data Directories field to accurately calculate the size of the header. In addition, it is important to validate the Optional Header’s Magic number for format compatibility.
The Optional Header’s Magic number determines whether an image is a PE32 or PE32+ executable:
Magic Number | PE Format |
0x10b | PE32 |
0x20b | PE32+ |
PE32+ images allow for a 64-bit address space while limiting the image size to 4 Gigabytes. Other PE32+ modifications are addressed in their respective sections.
The Optional Header itself has three major parts:
Offset (PE32/PE32+) | Size (PE32/PE32+) | Header part | Description |
0 | 28/24 | Standard fields | These are defined for all implementations of COFF, including UNIX®. |
28/24 | 68 / 88 | Windows specific fields | These include additional fields to support specific features of Windows (for example, subsystem). |
96/112 | Variable | Data directories | These fields are address/size pairs for special tables, found in the image file and used by the operating system (for example, Import Table and Export Table). |
The first eight fields of the Optional Header are standard fields, defined for every implementation of COFF. These fields contain general information useful for loading and running an executable file, and are unchanged for the PE32+ format.
Offset | Size | Field | Description |
0 | 2 | Magic | Unsigned integer identifying the state of the image file. The most common number is 0413 octal (0x10B), identifying it as a normal executable file. 0407 (0x107) identifies a ROM image. |
2 | 1 | MajorLinkerVersion | Linker major version number. |
3 | 1 | MinorLinkerVersion | Linker minor version number. |
4 | 4 | SizeOfCode | Size of the code (text) section, or the sum of all code sections if there are multiple sections. |
8 | 4 | SizeOfInitializedData | Size of the initialized data section, or the sum of all such sections if there are multiple data sections. |
12 | 4 | SizeOfUninitializedData | Size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections. |
16 | 4 | AddressOfEntryPoint | Address of entry point, relative to image base, when executable file is loaded into memory. For program images, this is the starting address. For device drivers, this is the address of the initialization function. An entry point is optional for DLLs. When none is present this field should be 0. |
20 | 4 | BaseOfCode | Address, relative to image base, of beginning of code section, when loaded into memory. |
PE32 contains this additional field, absent in PE32+, following BaseOfCode:
24 | 4 | BaseOfData | Address, relative to image base, of beginning of data section, when loaded into memory. |
The next twenty-one fields are an extension to the COFF Optional Header format and contain additional information needed by the linker and loader in Windows NT.
Offset (PE32/PE32+) | Size (PE32/PE32+) | Field | Description |
28 / 24 | 4 / 8 | ImageBase | Preferred address of first byte of image when loaded into memory; must be a multiple of 64K. The default for DLLs is 0x10000000. The default for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 95, and Windows 98 is 0x00400000. |
32 / 32 | 4 | SectionAlignment | Alignment (in bytes) of sections when loaded into memory. Must greater or equal to File Alignment. Default is the page size for the architecture. |
36 / 36 | 4 | FileAlignment | Alignment factor (in bytes) used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64K inclusive. The default is 512. If the SectionAlignment is less than the architecture’s page size than this must match the SectionAlignment. |
40 / 40 | 2 | MajorOperatingSystemVersion | Major version number of required OS. |
42 / 42 | 2 | MinorOperatingSystemVersion | Minor version number of required OS. |
44 / 44 | 2 | MajorImageVersion | Major version number of image. |
46 / 46 | 2 | MinorImageVersion | Minor version number of image. |
48 / 48 | 2 | MajorSubsystemVersion | Major version number of subsystem. |
50 / 50 | 2 | MinorSubsystemVersion | Minor version number of subsystem. |
52 / 52 | 4 | Reserved | dd |
56 / 56 | 4 | SizeOfImage | Size, in bytes, of image, including all headers; must be a multiple of Section Alignment. |
60 / 60 | 4 | SizeOfHeaders | Combined size of MS-DOS stub, PE Header, and section headers rounded up to a multiple of FileAlignment. |
64 / 64 | 4 | CheckSum | Image file checksum. The algorithm for computing is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that ends up in the server. |
68 / 68 | 2 | Subsystem | Subsystem required to run this image. See “Windows NT Subsystem” below for more information. |
70 / 70 | 2 | DLL Characteristics | See “DLL Characteristics” below for more information. |
72 / 72 | 4 / 8 | SizeOfStackReserve | Size of stack to reserve. Only the Stack Commit Size is committed; the rest is made available one page at a time, until reserve size is reached. |
76 / 80 | 4 / 8 | SizeOfStackCommit | Size of stack to commit. |
80 / 88 | 4 / 8 | SizeOfHeapReserve | Size of local heap space to reserve. Only the Heap Commit Size is committed; the rest is made available one page at a time, until reserve size is reached. |
84 / 96 | 4 / 8 | SizeOfHeapCommit | Size of local heap space to commit. |
88 / 104 | 4 | LoaderFlags | Obsolete. |
92 / 108 | 4 | NumberOfRvaAndSizes | Number of data-dictionary entries in the remainder of the Optional Header. Each describes a location and size. |
The following values are defined for the Subsystem field of the Optional Header. They determine what, if any, Windows NT subsystem is required to run the image.
Constant | Value | Description |
IMAGE_SUBSYSTEM_UNKNOWN | 0 | Unknown subsystem. |
IMAGE_SUBSYSTEM_NATIVE | 1 | Used for device drivers and native Windows NT processes. |
IMAGE_SUBSYSTEM_WINDOWS_GUI | 2 | Image runs in the Windows™ graphical user interface (GUI) subsystem. |
IMAGE_SUBSYSTEM_WINDOWS_CUI | 3 | Image runs in the Windows character subsystem. |
IMAGE_SUBSYSTEM_POSIX_CUI | 7 | Image runs in the Posix character subsystem. |
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI | 9 | Image runs in on Windows CE. |
IMAGE_SUBSYSTEM_EFI_APPLICATION | 10 | Image is an EFI application. |
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_
DRIVER |
11 | Image is an EFI driver that provides boot services. |
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER | 12 | Image is an EFI driver that provides runtime services. |
The following values are defined for the DLLCharacteristics field of the Optional Header.
Constant | Value | Description |
0x0001 | Reserved | |
0x0002 | Reserved | |
0x0004 | Reserved | |
0x0008 | Reserved | |
IMAGE_DLLCHARACTERISTICS_NO_BIND | 0x0800 | Do not bind image |
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER | 0x2000 | Driver is a WDM Driver |
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | 0x8000 | Image is Terminal Server aware |
Each data directory gives the address and size of a table or string used by Windows NT. These are all loaded into memory so that they can be used by the system at run time. A data directory is an eight-byte field that has the following declaration:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD RVA;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
The first field, RVA, is the relative virtual address of the table. The RVA is the address of the table, when loaded, relative to the base address of the image. The second field gives the size in bytes. The data directories, which form the last part of the Optional Header, are listed below.
Note that the number of directories is not fixed. The NumberOfRvaAndSizes field in the optional header should be checked before looking for a specific directory.
Do not assume that the RVAs given in this table point to the beginning of a section or that the sections containing specific tables have specific names.
Offset
(PE/PE32+) |
Size | Field | Description |
96/112 | 8 | Export Table | Export Table address and size. |
104/120 | 8 | Import Table | Import Table address and size |
112/128 | 8 | Resource Table | Resource Table address and size. |
120/136 | 8 | Exception Table | Exception Table address and size. |
128/144 | 8 | Certificate Table | Attribute Certificate Table address and size. |
136/152 | 8 | Base Relocation Table | Base Relocation Table address and size. |
144/160 | 8 | Debug | Debug data starting address and size. |
152/168 | 8 | Architecture | Architecture-specific data address and size. |
160/176 | 8 | Global Ptr | Relative virtual address of the value to be stored in the global pointer register. Size member of this structure must be set to 0. |
168/184 | 8 | TLS Table | Thread Local Storage (TLS) Table address and size. |
176/192 | 8 | Load Config Table | Load Configuration Table address and size. |
184/200 | 8 | Bound Import | Bound Import Table address and size. |
192/208 | 8 | IAT | Import Address Table address and size. |
200/216 | 8 | Delay Import Descriptor | Address and size of the Delay Import Descriptor. |
208/224 | 8 | COM+ Runtime Header | COM+ Runtime Header address and size |
216/232 | 8 | Reserved |
The Certificate Table entry points to a table of attribute certificates. These certificates are not loaded into memory as part of the image. As such, the first field of this entry, which is normally an RVA, is a File Pointer instead.