8 Portable Executable Format
8 Portable Executable Format
PE Structure
The diagram below shows a simplified structure of a Portable Executable. Every header shown in the image is defined as a
data structure that holds information about the PE file. Each data structure will be explained in detail in this module.
The most important members of the struct are e_magic and e_lfanew .
e_magic is 2 bytes with a fixed value of 0x5A4D or MZ .
e_lfanew is a 4-byte value that holds an offset to the start of the NT Header. Note that e_lfanew is always located at an offset
of 0x3C .
DOS Stub
Before moving on to the NT header structure, there is the DOS stub which is an error message that prints "This program
cannot be run in DOS mode" in case the program is loaded in DOS mode or "Disk Operating Mode". It is worth noting that the
error message can be changed by the programmer at compile time. This is not a PE header, but it's good to be aware of it.
NT Header (IMAGE_NT_HEADERS)
The NT header is essential as it incorporates two other image headers: FileHeader and OptionalHeader , which include a large
amount of information about the PE file. Similarly to the DOS header, the NT header contains a signature member that is used
to verify it. Usually, the signature element is equal to the "PE" string, which is represented by the 0x50 and 0x45 bytes. But
since the signature is of data type DWORD , the signature will be represented as 0x50450000 , which is still "PE", except that it is
padded with two null bytes. The NT header can be reached using the e_lfanew member inside of the DOS Header.
The NT header structure varies depending on the machine's architecture.
32-bit Version:
64-bit Version:
The only difference is the OptionalHeader data structure, IMAGE_OPTIONAL_HEADER32 and IMAGE_OPTIONAL_HEADER64 .
- Flags that specify certain attributes about the executable file, such as whether it is a dynamic-link library
Characteristics
Additional information about the file header can be found on the official documentation page.
64-bit Version:
The optional header contains a ton of information that can be used. Below are some of the struct members that are commonly
used:
Magic - Describes the state of the image file (32 or 64-bit image)
MajorOperatingSystemVersion - The major version number of the required operating system (e.g. 11, 10)
MinorOperatingSystemVersion - The minor version number of the required operating system (e.g. 1511, 1507, 1607)
AddressOfEntryPoint - Offset to the entry point of the file (Typically the main function)
ImageBase - It specifies the preferred address at which the application is to be loaded into memory when it is executed.
However, due to Window's memory protection mechanisms like Address Space Layout Randomization (ASLR), it's rare to
see an image mapped to its preferred address because the Windows PE Loader maps the file to a different address. This
random allocation done by the Windows PE loader will cause issues in the implementation of future techniques because
some addresses that are considered constant were changed. The Windows PE loader will then go through PE relocation to
fix these addresses.
- One of the most important members in the optional header. This is an array of IMAGE_DATA_DIRECTORY,
DataDirectory
Data Directory
The Data Directory can be accessed from the optional's header last member. This is an array of data
type IMAGE_DATA_DIRECTORY which has the following data structure:
The Data Directory array is of size IMAGE_NUMBEROF_DIRECTORY_ENTRIES which is a constant value of 16 . Each element in the array
represents a specific data directory which includes some data about a PE section or a Data Table (the place where specific
information about the PE is saved).
A specific data directory can be accessed using its index in the array.
The two sections below will briefly mention two important data directories, the Export Directory and Import Address Table .
Export Directory
A PE's export directory is a data structure that contains information about functions and variables that are exported from the
executable. It contains the addresses of the exported functions and variables, which can be used by other executable files to
access the functions and data. The export directory is generally found in DLLs that export functions
(e.g. kernel32.dll exporting CreateFileA ).
PE Sections
PE sections contain the code and data used to create an executable program. Each PE section is given a unique name and
typically contains executable code, data, or resource information. There is no constant number of PE sections because
different compilers can add, remove or merge sections depending on the configuration. Some sections can also be added later
on manually, therefore it is dynamic and the IMAGE_FILE_HEADER.NumberOfSections helps determine that number.
The following PE sections are the most important ones and exist in almost every PE.
.data - Contains initialized data which are variables initialized in the code.
.rdata - Contains read-only data. These are constant variables prefixed with const .
.idata- Contains the import tables. These are tables of information related to the functions called using the code. This is
used by the Windows PE Loader to determine which DLL files to load to the process, along with what functions are being
used from each DLL.
.reloc - Contains information on how to fix up memory addresses so that the program can be loaded into memory without
any errors.
Each PE section has an IMAGE_SECTION_HEADER data structure that contains valuable information about it. These
structures are saved under the NT headers in a PE file and are stacked above each other where each structure represents a
section.
Recall, the IMAGE_SECTION_HEADER structure is as follows:
looking at the elements, every single one is highly valuable and important:
Additional References
In case further clarification is required on certain sections, the following blog posts on 0xRick's Blog are highly recommended.
PE Overview - https://0xrick.github.io/win-internals/pe2/
NT Headers - https://0xrick.github.io/win-internals/pe4/