.EXE
Windows Portable Executable (PE)
Introduction
PE, the Portable Executable format, is the format of programs and libraries on 32-bit and 64-bit Windows, introduced with Windows NT 3.1 in 1993. It is built on COFF, the object file format, and holds the program’s code and data in sections, a list of the functions it imports and exports, its resources, and the information Windows needs to load it at any address.
The same format is used under many extensions: programs (.exe), libraries
(.dll), drivers (.sys), ActiveX controls (.ocx),
screen savers (.scr) and UEFI firmware applications (.efi).
.NET programs are PE files too, with their bytecode in a section of the file. See
all the .EXE variations.
Software
- Windows, which runs them
- Wine (Linux, macOS)
- Ghidra (Windows, macOS, Linux)
- IDA Pro (Windows, macOS, Linux)
- x64dbg (Windows)
- PE-bear (Windows, Linux)
- Resource Hacker (Windows)
- Dependencies (Windows)
- 7-Zip, which can open a PE file’s sections and resources (Windows)
Structure
A PE file begins with an MS-DOS MZ header and stub program. The 32-bit offset at
0x3C points to the signature PE\0\0, followed by the 20-byte
COFF file header: the target machine, the number of sections, a timestamp and flags.
The optional header comes next, which despite its name every program has. Its first two
bytes say whether the file is PE32 (0x10B, 32-bit) or PE32+
(0x20B, 64-bit). It holds the entry point, the preferred load address, the
alignments, the target subsystem, and a table of data directories that locate the
imports, exports, resources, relocations, debug data and more.
The section table follows, one 40-byte entry per section, giving each section’s name, its place in memory and its place in the file. Addresses inside the program are relative virtual addresses (RVAs): offsets from the load address, which the section table maps back to file offsets.
0x00MZ header and DOS stub, withe_lfanewat0x3Cvariese_lfanewsignaturePE\0\04 bytes+4COFF file header: machine, section count, timestamp, flags20 bytes+24optional header: entry point, image base, subsystem, data directories224 or 240 bytes…section table: name, address, size and file position of each section40 bytes each…sections, such as.textcode,.rdataimports,.data,.rsrcresources,.relocvaries
Telling .EXE files apart
An MS-DOS program, a 16-bit Windows program and a modern Windows program all start with
MZ. Windows programs add a 32-bit offset, e_lfanew, at
0x3C, pointing to a second header. Read the bytes there:
PE\0\0means a Windows PE program, this format.NEmeans a 16-bit Windows NE program.- Anything else, or an offset past the end of the file, means a plain MS-DOS program.
Within PE, the IMAGE_FILE_DLL flag (0x2000) in the COFF
header marks a library, and the optional header’s magic number tells 32-bit from 64-bit.