PE/COFF File Format

The Portable Executable format is used by Windows executables (.exe), libraries (.dll), drivers (.sys) and UEFI binaries; COFF is the object file format it extends. This page describes every header with its offsets in PE32 and PE32+ files, then annotates every byte of a small working 64-bit executable.

Layout

On disk
IMAGE_DOS_HEADER "MZ" ... e_lfanew
DOS stub (+ Rich header)
"PE\0\0" + IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER + data directories
Section table
.text (FileAlignment 0x200)
.rdata
.data
.reloc, .rsrc...
Overlay: certificate, appended data (not mapped)
In memory (typical layout, ImageBase + RVA)
+0x0000 R--headers (one page)
+0x1000 R-X.text
+0x2000 R--.rdata: IAT, import tables, constants
+0x3000 RW-.data, .bss (VirtualSize > SizeOfRawData)
+0x4000 R--.reloc (discardable)

The loader maps the headers and then each section at ImageBase + VirtualAddress, rounded to SectionAlignment, with the protection given by its characteristics. Unlike ELF there is a single table: sections are both the linker and the loader unit.

Annotated sample (2048 bytes, PE32+ x64)

A console program that prints Hello, PE! with GetStdHandle, WriteFile and ExitProcess from KERNEL32.dll. Three sections: code, read-only data holding the import tables, and one base relocation for an absolute pointer. Every byte is described; zero padding is folded.

0x0IMAGE_DOS_HEADERe_lfanew = 0x8064 B
0x40DOS stub16-bit code64 B
0x80"PE\0\0" + IMAGE_FILE_HEADERMachine, sections24 B
0x98IMAGE_OPTIONAL_HEADER64+ 16 data directories240 B
0x188Section table3 × IMAGE_SECTION_HEADER120 B
0x200.textRVA 0x1000, R-X512 B
0x400.rdataRVA 0x2000: IAT, imports, message512 B
0x600.relocRVA 0x3000: base relocations512 B
000000004d5a90000300000004000000ffff0000MZ..............
00000010b8000000000000004000000000000000........@.......
0000002000000000000000000000000000000000................
0000003000000000000000000000000080000000................
000000400e1fba0e00b409cd21b8014ccd215468........!..L.!Th
0000005069732070726f6772616d2063616e6e6fis program canno
00000060742062652072756e20696e20444f5320t be run in DOS
000000706d6f64652e0d0d0a2400000000000000mode....$.......
0000008050450000648603000000006700000000PE..d......g....
0000009000000000f00022000b020e0000020000......".........
000000a000040000000000000010000000100000................
000000b000000040010000000010000000020000...@............
000000c006000000000000000600000000000000................
000000d0004000000002000064bd000003006081.@......d.....`.
000000e000001000000000000010000000000000................
000000f000001000000000000010000000000000................
0000010000000000100000000000000000000000................
0000011028200000280000000000000000000000( ..(...........
0000012000000000000000000000000000000000................
00000130003000000c0000000000000000000000.0..............
0000014000000000000000000000000000000000................
0000015000000000000000000000000000000000................
0000016000000000000000000020000020000000......... .. ...
0000017000000000000000000000000000000000................
0000018000000000000000002e74657874000000.........text...
000001903c000000001000000002000000020000<...............
000001a000000000000000000000000020000060............ ..`
000001b02e72646174610000b400000000200000.rdata....... ..
000001c000020000000400000000000000000000................
000001d000000000400000402e72656c6f630000....@..@.reloc..
000001e00c000000003000000002000000060000.....0..........
000001f000000000000000000000000040000042............@..B
000002004883ec38b9f5ffffffff15f10f000048H..8...........H
0000021089c1488b150710000041b80c0000004c..H......A.....L
000002208d4c243048c744242000000000ff15d5.L$0H.D$ .......
000002300f000031c9ff15d50f0000cc00000000...1............
00000240… 0x1c0 zero bytes …
0000040070200000000000008020000000000000p ....... ......
000004108c200000000000000000000000000000. ..............
00000420a8200040010000005020000000000000. .@....P ......
00000430000000009a2000000020000000000000..... ... ......
0000044000000000000000000000000000000000................
0000045070200000000000008020000000000000p ....... ......
000004608c200000000000000000000000000000. ..............
00000470000047657453746448616e646c650000..GetStdHandle..
000004800000577269746546696c650000004578..WriteFile...Ex
00000490697450726f63657373004b45524e454citProcess.KERNEL
000004a033322e646c6c000048656c6c6f2c205032.dll..Hello, P
000004b045210d0a000000000000000000000000E!..............
000004c0… 0x140 zero bytes …
00000600002000000c00000020a0000000000000. ...... .......
00000610… 0x1f0 zero bytes …

Hover a byte or a field to see what it is. Click to pin it.

IMAGE_DOS_HEADER 0x0
  • e_magic"MZ"
  • e_cblp0x90
  • e_cp3
  • e_crlc0
  • e_cparhdr4
  • e_minalloc0
  • e_maxalloc0xffff
  • e_ss0
  • e_sp0xb8
  • e_csum0
  • e_ip0
  • e_cs0
  • e_lfarlc0x40
  • e_ovno0
  • e_reszero
  • e_oemid0
  • e_oeminfo0
  • e_res2zero
  • e_lfanew0x80
DOS stub 0x40
  • stub codepush cs; pop ds; mov…
  • message"This program cannot…
Padding 0x79
  • paddingzeros
PE signature 0x80
  • Signature"PE\0\0"
IMAGE_FILE_HEADER 0x84
  • MachineIMAGE_FILE_MACHINE_A…
  • NumberOfSections3
  • TimeDateStamp0x67000000
  • PointerToSymbolTable0
  • NumberOfSymbols0
  • SizeOfOptionalHeader0xf0
  • CharacteristicsEXECUTABLE_IMAGE | L…
IMAGE_OPTIONAL_HEADER64 0x98
  • MagicPE32+
  • MajorLinkerVersion0xe
  • MinorLinkerVersion0
  • SizeOfCode0x200
  • SizeOfInitializedData0x400
  • SizeOfUninitializedData0
  • AddressOfEntryPoint0x1000
  • BaseOfCode0x1000
  • ImageBase0x140000000
  • SectionAlignment0x1000
  • FileAlignment0x200
  • MajorOperatingSystemVersion6
  • MinorOperatingSystemVersion0
  • MajorImageVersion0
  • MinorImageVersion0
  • MajorSubsystemVersion6
  • MinorSubsystemVersion0
  • Win32VersionValue0
  • SizeOfImage0x4000
  • SizeOfHeaders0x200
  • CheckSum0xbd64
  • SubsystemIMAGE_SUBSYSTEM_WIND…
  • DllCharacteristicsHIGH_ENTROPY_VA | DY…
  • SizeOfStackReserve0x100000
  • SizeOfStackCommit0x1000
  • SizeOfHeapReserve0x100000
  • SizeOfHeapCommit0x1000
  • LoaderFlags0
  • NumberOfRvaAndSizes0x10
Data directories 0x108
  • [0] Export RVA0
  • [0] Export Size0
  • [1] Import RVA0x2028
  • [1] Import Size0x28
  • [2] Resource RVA0
  • [2] Resource Size0
  • [3] Exception RVA0
  • [3] Exception Size0
  • [4] Security RVA0
  • [4] Security Size0
  • [5] Base Relocation RVA0x3000
  • [5] Base Relocation Size0xc
  • [6] Debug RVA0
  • [6] Debug Size0
  • [7] Architecture RVA0
  • [7] Architecture Size0
  • [8] Global Ptr RVA0
  • [8] Global Ptr Size0
  • [9] TLS RVA0
  • [9] TLS Size0
  • [10] Load Config RVA0
  • [10] Load Config Size0
  • [11] Bound Import RVA0
  • [11] Bound Import Size0
  • [12] IAT RVA0x2000
  • [12] IAT Size0x20
  • [13] Delay Import RVA0
  • [13] Delay Import Size0
  • [14] CLR Runtime Header RVA0
  • [14] CLR Runtime Header Size0
  • [15] Reserved RVA0
  • [15] Reserved Size0
Section header .text 0x188
  • Name".text"
  • VirtualSize0x3c
  • VirtualAddress0x1000
  • SizeOfRawData0x200
  • PointerToRawData0x200
  • PointerToRelocations0
  • PointerToLinenumbers0
  • NumberOfRelocations0
  • NumberOfLinenumbers0
  • CharacteristicsCNT_CODE | MEM_EXECU…
Section header .rdata 0x1b0
  • Name".rdata"
  • VirtualSize0xb4
  • VirtualAddress0x2000
  • SizeOfRawData0x200
  • PointerToRawData0x400
  • PointerToRelocations0
  • PointerToLinenumbers0
  • NumberOfRelocations0
  • NumberOfLinenumbers0
  • CharacteristicsCNT_INITIALIZED_DATA…
Section header .reloc 0x1d8
  • Name".reloc"
  • VirtualSize0xc
  • VirtualAddress0x3000
  • SizeOfRawData0x200
  • PointerToRawData0x600
  • PointerToRelocations0
  • PointerToLinenumbers0
  • NumberOfRelocations0
  • NumberOfLinenumbers0
  • CharacteristicsCNT_INITIALIZED_DATA…
.text (entry point) 0x200
  • sub rsp, 0x38sub rsp, 0x38
  • mov ecx, -11mov ecx, -11 ; STD_O…
  • call [rip+__imp_GetStdHandle]call [rip+__imp_GetS…
  • mov rcx, raxmov rcx, rax
  • mov rdx, [rip+msg_ptr]mov rdx, [rip+msg_ptr]
  • mov r8d, 12mov r8d, 12
  • lea r9, [rsp+0x30]lea r9, [rsp+0x30]
  • mov qword [rsp+0x20], 0mov qword [rsp+0x20]…
  • call [rip+__imp_WriteFile]call [rip+__imp_Writ…
  • xor ecx, ecxxor ecx, ecx
  • call [rip+__imp_ExitProcess]call [rip+__imp_Exit…
  • int3int3
Padding 0x23c
  • paddingzeros
Import Address Table 0x400
  • IAT[0] GetStdHandle0x2070
  • IAT[1] WriteFile0x2080
  • IAT[2] ExitProcess0x208c
  • IAT end0
msg_ptr 0x420
  • msg_ptr0x1400020a8
Import descriptor KERNEL32.dll 0x428
  • OriginalFirstThunk0x2050
  • TimeDateStamp0
  • ForwarderChain0
  • Name0x209a
  • FirstThunk0x2000
Import descriptor (null) 0x43c
  • terminator
Import Lookup Table 0x450
  • ILT[0] GetStdHandle0x2070
  • ILT[1] WriteFile0x2080
  • ILT[2] ExitProcess0x208c
  • ILT end0
IMAGE_IMPORT_BY_NAME GetStdHandle 0x470
  • Hint0
  • Name"GetStdHandle"
IMAGE_IMPORT_BY_NAME WriteFile 0x480
  • Hint0
  • Name"WriteFile"
IMAGE_IMPORT_BY_NAME ExitProcess 0x48c
  • Hint0
  • Name"ExitProcess"
DLL name 0x49a
  • Name"KERNEL32.dll"
Padding 0x4a7
  • paddingzeros
Message 0x4a8
  • msg"Hello, PE!\r\n"
Padding 0x4b4
  • paddingzeros
Base relocation block 0x600
  • VirtualAddress0x2000
  • SizeOfBlock0xc
  • entry 0DIR64 + 0x020
  • entry 1ABSOLUTE
Padding 0x60c
  • paddingzeros

DOS header

IMAGE_DOS_HEADER 64 (0x40) bytes

FieldOffsetSizeTypeMeaning
e_magic0x002WORD"MZ" (4d 5a), Mark Zbikowski.
e_cblp0x022WORDBytes on the last 512-byte page (DOS only).
e_cp0x042WORDPages in the file (DOS only).
e_crlc0x062WORDRelocations (DOS only).
e_cparhdr0x082WORDHeader size in 16-byte paragraphs (DOS only).
e_minalloc0x0a2WORDMinimum extra paragraphs (DOS only).
e_maxalloc0x0c2WORDMaximum extra paragraphs (DOS only).
e_ss0x0e2WORDInitial SS (DOS only).
e_sp0x102WORDInitial SP (DOS only).
e_csum0x122WORDChecksum (DOS only).
e_ip0x142WORDInitial IP (DOS only).
e_cs0x162WORDInitial CS (DOS only).
e_lfarlc0x182WORDOffset of the DOS relocation table (DOS only).
e_ovno0x1a2WORDOverlay number (DOS only).
e_res0x1c8WORD[4]Reserved.
e_oemid0x242WORDOEM identifier.
e_oeminfo0x262WORDOEM information.
e_res20x2820WORD[10]Reserved.
e_lfanew0x3c4LONGFile offset of the PE signature. The only field Windows needs besides e_magic.
Windows reads e_magic and e_lfanew and nothing else. The bytes between this header and the PE signature usually hold a 16-bit DOS stub that prints This program cannot be run in DOS mode., and, for files linked by Microsoft tools, the undocumented "Rich" header that lists the tool versions used.

File header

At e_lfanew + 4, right after the "PE\0\0" signature.

IMAGE_FILE_HEADER 20 (0x14) bytes

FieldOffsetSizeTypeMeaning
Machine0x002WORDTarget CPU (IMAGE_FILE_MACHINE_*).
NumberOfSections0x022WORDEntries in the section table.
TimeDateStamp0x044DWORDLink time (Unix time), or a hash for reproducible builds.
PointerToSymbolTable0x084DWORDFile offset of the COFF symbol table; 0 in images.
NumberOfSymbols0x0c4DWORDCOFF symbols; 0 in images.
SizeOfOptionalHeader0x102WORDSize of the optional header: 0xe0 (PE32) or 0xf0 (PE32+); 0 in object files. The section table follows it.
Characteristics0x122WORDFile flags (IMAGE_FILE_*).
Object files (.obj) start directly with this header; images (.exe, .dll, .sys) have it right after the "PE\0\0" signature.

Machine

NameValueMeaning
IMAGE_FILE_MACHINE_UNKNOWN0Any machine (resource-only DLLs).
IMAGE_FILE_MACHINE_I3860x14cIntel 386 and later.
IMAGE_FILE_MACHINE_ARMNT0x1c4ARM Thumb-2 (Windows on ARM 32-bit).
IMAGE_FILE_MACHINE_AMD640x8664x64.
IMAGE_FILE_MACHINE_ARM640xaa64ARM64.
IMAGE_FILE_MACHINE_ARM64EC0xa641ARM64EC: ARM64 code that interoperates with x64 code in the same process.
IMAGE_FILE_MACHINE_ARM64X0xa64eARM64X: one file with both ARM64 and ARM64EC code.

Characteristics

NameValueMeaning
IMAGE_FILE_RELOCS_STRIPPED1No base relocations: must load at ImageBase.
IMAGE_FILE_EXECUTABLE_IMAGE2Valid image (set for exe and dll).
IMAGE_FILE_LINE_NUMS_STRIPPED4Deprecated.
IMAGE_FILE_LOCAL_SYMS_STRIPPED8Deprecated.
IMAGE_FILE_AGGRESIVE_WS_TRIM0x10Obsolete.
IMAGE_FILE_LARGE_ADDRESS_AWARE0x20Can handle addresses above 2 GiB.
IMAGE_FILE_BYTES_REVERSED_LO0x80Obsolete.
IMAGE_FILE_32BIT_MACHINE0x10032-bit word machine.
IMAGE_FILE_DEBUG_STRIPPED0x200Debug information removed.
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP0x400Copy to swap if run from removable media.
IMAGE_FILE_NET_RUN_FROM_SWAP0x800Copy to swap if run from the network.
IMAGE_FILE_SYSTEM0x1000System file.
IMAGE_FILE_DLL0x2000DLL.
IMAGE_FILE_UP_SYSTEM_ONLY0x4000Uniprocessor only.
IMAGE_FILE_BYTES_REVERSED_HI0x8000Obsolete.

Optional header

Mandatory for images despite its name. PE32+ drops BaseOfData and widens ImageBase and the four stack/heap sizes to 64 bits, so it is 16 bytes larger.

IMAGE_OPTIONAL_HEADER32 / IMAGE_OPTIONAL_HEADER64 224 (0xe0) bytes / 240 (0xf0) bytes

FieldOff. PE32Off. PE32+Size PE32Size PE32+TypeMeaning
Magic0x000x0022WORD0x10b = PE32, 0x20b = PE32+ (64-bit). Selects the layout below.
MajorLinkerVersion0x020x0211BYTELinker version.
MinorLinkerVersion0x030x0311BYTELinker version.
SizeOfCode0x040x0444DWORDSum of the code sections (rounded to FileAlignment).
SizeOfInitializedData0x080x0844DWORDSum of the initialized data sections.
SizeOfUninitializedData0x0c0x0c44DWORDSum of the BSS sections.
AddressOfEntryPoint0x100x1044DWORDRVA of the entry point (mainCRTStartup, DllMain for DLLs; 0 = none).
BaseOfCode0x140x1444DWORDRVA of the first code section.
BaseOfData0x18—4—DWORDRVA of the first data section (PE32 only).
ImageBase0x1c0x1848PTRPreferred load address: 0x400000 (PE32 exe), 0x140000000 (PE32+ exe), 0x180000000 (PE32+ DLL). Randomized by ASLR when DYNAMIC_BASE is set.
SectionAlignment0x200x2044DWORDAlignment of sections in memory, usually the page size 0x1000.
FileAlignment0x240x2444DWORDAlignment of section data in the file, usually 0x200.
MajorOperatingSystemVersion0x280x2822WORDRequired OS version.
MinorOperatingSystemVersion0x2a0x2a22WORDRequired OS version.
MajorImageVersion0x2c0x2c22WORDImage version.
MinorImageVersion0x2e0x2e22WORDImage version.
MajorSubsystemVersion0x300x3022WORDRequired subsystem version (6.0 = Vista).
MinorSubsystemVersion0x320x3222WORDRequired subsystem version.
Win32VersionValue0x340x3444DWORDReserved, 0.
SizeOfImage0x380x3844DWORDSize of the image in memory, multiple of SectionAlignment.
SizeOfHeaders0x3c0x3c44DWORDSize of all headers rounded to FileAlignment; the first section starts here.
CheckSum0x400x4044DWORDImage checksum; only checked for drivers and boot-time DLLs.
Subsystem0x440x4422WORDSubsystem (IMAGE_SUBSYSTEM_*): console, GUI, native, EFI...
DllCharacteristics0x460x4622WORDSecurity flags (IMAGE_DLLCHARACTERISTICS_*): ASLR, DEP, CFG...
SizeOfStackReserve0x480x4848PTRStack reserved for the main thread.
SizeOfStackCommit0x4c0x5048PTRStack committed at start.
SizeOfHeapReserve0x500x5848PTRDefault process heap reserve.
SizeOfHeapCommit0x540x6048PTRDefault process heap commit.
LoaderFlags0x580x6844DWORDReserved, 0.
NumberOfRvaAndSizes0x5c0x6c44DWORDNumber of data directories that follow, normally 16.
DataDirectory0x600x70128128IMAGE_DATA_DIRECTORY[16]16 IMAGE_DATA_DIRECTORY entries (RVA + size), see below.

Subsystem

NameValueMeaning
IMAGE_SUBSYSTEM_UNKNOWN0Unknown.
IMAGE_SUBSYSTEM_NATIVE1Drivers and native processes (smss.exe).
IMAGE_SUBSYSTEM_WINDOWS_GUI2GUI application (WinMain, no console).
IMAGE_SUBSYSTEM_WINDOWS_CUI3Console application.
IMAGE_SUBSYSTEM_OS2_CUI5OS/2 console.
IMAGE_SUBSYSTEM_POSIX_CUI7POSIX console.
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI9Windows CE.
IMAGE_SUBSYSTEM_EFI_APPLICATION0xaUEFI application.
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER0xbUEFI boot service driver.
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER0xcUEFI runtime driver.
IMAGE_SUBSYSTEM_EFI_ROM0xdUEFI ROM image.
IMAGE_SUBSYSTEM_XBOX0xeXbox.
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION0x10Boot application (bootmgr).

DllCharacteristics

NameValueMeaning
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA0x2064-bit ASLR with full entropy.
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE0x40ASLR: can be relocated (/DYNAMICBASE).
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY0x80Code integrity checks enforced.
IMAGE_DLLCHARACTERISTICS_NX_COMPAT0x100DEP compatible (/NXCOMPAT).
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION0x200Do not use side-by-side manifests.
IMAGE_DLLCHARACTERISTICS_NO_SEH0x400No structured exception handlers (x86 SafeSEH context).
IMAGE_DLLCHARACTERISTICS_NO_BIND0x800Do not bind.
IMAGE_DLLCHARACTERISTICS_APPCONTAINER0x1000Must run in an AppContainer.
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER0x2000WDM driver.
IMAGE_DLLCHARACTERISTICS_GUARD_CF0x4000Control Flow Guard (/guard:cf).
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE0x8000Terminal Server aware.

Data directories

Each entry is an IMAGE_DATA_DIRECTORY (RVA, then size at +4). An entry that is not present is all zero. Offsets below are from the start of the optional header.

IMAGE_DATA_DIRECTORY 8 (0x8) bytes

FieldOffsetSizeTypeMeaning
VirtualAddress0x004DWORDRVA of the table (a file offset for the Certificate table).
Size0x044DWORDSize in bytes.
#DirectoryConstantOffset PE32Offset PE32+Points to
0ExportIMAGE_DIRECTORY_ENTRY_EXPORT0x600x70IMAGE_EXPORT_DIRECTORY: functions exported by name or ordinal.
1ImportIMAGE_DIRECTORY_ENTRY_IMPORT0x680x78Array of IMAGE_IMPORT_DESCRIPTOR, one per DLL.
2ResourceIMAGE_DIRECTORY_ENTRY_RESOURCE0x700x80Resource tree (.rsrc): icons, version info, manifest, dialogs.
3ExceptionIMAGE_DIRECTORY_ENTRY_EXCEPTION0x780x88.pdata: RUNTIME_FUNCTION entries for x64/ARM64 unwinding.
4SecurityIMAGE_DIRECTORY_ENTRY_SECURITY0x800x90Authenticode certificates (WIN_CERTIFICATE). A file offset, not mapped in memory.
5Base RelocationIMAGE_DIRECTORY_ENTRY_BASERELOC0x880x98.reloc: blocks of IMAGE_BASE_RELOCATION.
6DebugIMAGE_DIRECTORY_ENTRY_DEBUG0x900xa0Array of IMAGE_DEBUG_DIRECTORY: CodeView entry with the PDB path and GUID.
7ArchitectureIMAGE_DIRECTORY_ENTRY_ARCHITECTURE0x980xa8Reserved, 0.
8Global PtrIMAGE_DIRECTORY_ENTRY_GLOBALPTR0xa00xb0RVA of the global pointer (IA-64), size 0.
9TLSIMAGE_DIRECTORY_ENTRY_TLS0xa80xb8IMAGE_TLS_DIRECTORY: TLS template and callbacks.
10Load ConfigIMAGE_DIRECTORY_ENTRY_LOAD_CONFIG0xb00xc0IMAGE_LOAD_CONFIG_DIRECTORY: security cookie, SafeSEH table, CFG tables, CET metadata.
11Bound ImportIMAGE_DIRECTORY_ENTRY_BOUND_IMPORT0xb80xc8Pre-bound import addresses (legacy).
12IATIMAGE_DIRECTORY_ENTRY_IAT0xc00xd0Range of all the Import Address Tables, made writable during binding.
13Delay ImportIMAGE_DIRECTORY_ENTRY_DELAY_IMPORT0xc80xd8Delay-load descriptors: DLLs loaded on first call.
14CLR Runtime HeaderIMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR0xd00xe0.NET: IMAGE_COR20_HEADER, the managed metadata.
15Reserved—0xd80xe8Must be zero.

Sections

The section table follows the optional header: e_lfanew + 24 + SizeOfOptionalHeader.

IMAGE_SECTION_HEADER 40 (0x28) bytes

FieldOffsetSizeTypeMeaning
Name0x008BYTE[8]Name, NUL-padded, not necessarily NUL-terminated. In object files /123 means offset 123 in the string table.
VirtualSize0x084DWORDSize in memory (Misc.VirtualSize). Larger than SizeOfRawData: the rest is zero-filled.
VirtualAddress0x0c4DWORDRVA of the section, multiple of SectionAlignment.
SizeOfRawData0x104DWORDSize in the file, multiple of FileAlignment.
PointerToRawData0x144DWORDFile offset of the data, multiple of FileAlignment.
PointerToRelocations0x184DWORDFile offset of the COFF relocations (object files only).
PointerToLinenumbers0x1c4DWORDDeprecated, 0.
NumberOfRelocations0x202WORDCOFF relocations (object files only).
NumberOfLinenumbers0x222WORDDeprecated, 0.
Characteristics0x244DWORDContent and permissions (IMAGE_SCN_*).

Characteristics

NameValueMeaning
IMAGE_SCN_CNT_CODE0x20Contains code.
IMAGE_SCN_CNT_INITIALIZED_DATA0x40Contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_DATA0x80Contains uninitialized data (BSS).
IMAGE_SCN_LNK_INFO0x200Comments or linker directives (.drectve), object files only.
IMAGE_SCN_LNK_REMOVE0x800Not part of the image, object files only.
IMAGE_SCN_LNK_COMDAT0x1000COMDAT section (C++ inline functions, templates), object files only.
IMAGE_SCN_ALIGN_1BYTES .. 8192BYTES0x100000 .. 0xe00000Alignment in object files: (log2(align) + 1) << 20, e.g. 16 bytes = 0x500000.
IMAGE_SCN_MEM_DISCARDABLE0x2000000Can be discarded after loading (.reloc, debug).
IMAGE_SCN_MEM_SHARED0x10000000Shared between all processes that load the image.
IMAGE_SCN_MEM_EXECUTE0x20000000Executable.
IMAGE_SCN_MEM_READ0x40000000Readable.
IMAGE_SCN_MEM_WRITE0x80000000Writable.
Usual values: .text 0x60000020 (code, execute, read), .rdata 0x40000040, .data 0xc0000040 (read, write), .reloc 0x42000040 (discardable). Common section names: .text, .rdata, .data, .pdata (unwind), .tls, .rsrc, .reloc, .idata (imports, when not merged into .rdata), .edata (exports). Names mean nothing to the loader: packers use UPX0, .vmp0 and so on.

RVA and file offsets

Three kinds of addresses
  • File offset: position in the file on disk.
  • RVA (relative virtual address): offset from the image base once mapped. Almost every pointer in the headers is an RVA.
  • VA: ImageBase + RVA, the real address in memory. Only found in code, data and a few tables (TLS, load config), and fixed by base relocations.
RVA → file offset

Find the section with VirtualAddress ≤ rva < VirtualAddress + VirtualSize, then:

offset = rva - VirtualAddress + PointerToRawData

In the sample, the IAT is at RVA 0x2000, in .rdata (VirtualAddress 0x2000, PointerToRawData 0x400): 0x2000 - 0x2000 + 0x400 = 0x400.

An RVA below SizeOfHeaders maps to the same file offset.

How imports are resolved

For each descriptor the loader loads Name, walks the ILT, looks every name up in the DLL export table, and writes the address in the matching IAT slot. Code calls through the IAT: call [rip+__imp_WriteFile] (ff 15). Hooking the IAT is the classic user-mode hooking technique.

Imports

Import directoryIMAGE_IMPORT_DESCRIPTOR[]
OriginalFirstThunk →Name →FirstThunk →
ILTRVA → hint/name, never changes
"KERNEL32.dll"
IATsame as ILT on disk, function addresses at run time
→
IMAGE_IMPORT_BY_NAMEWORD Hint, "WriteFile"

IMAGE_IMPORT_DESCRIPTOR 20 (0x14) bytes

FieldOffsetSizeTypeMeaning
OriginalFirstThunk0x004DWORDRVA of the Import Lookup Table (ILT, also called INT): names or ordinals, never modified.
TimeDateStamp0x044DWORD0, or -1 if bound.
ForwarderChain0x084DWORDOld binding mechanism, usually 0 or -1.
Name0x0c4DWORDRVA of the DLL name ("KERNEL32.dll").
FirstThunk0x104DWORDRVA of the Import Address Table (IAT): same content as the ILT on disk, overwritten with the function addresses by the loader.
One descriptor per DLL, terminated by an all-zero descriptor.

IMAGE_THUNK_DATA32 / IMAGE_THUNK_DATA64 (ILT and IAT entries) 4 (0x4) bytes / 8 (0x8) bytes

FieldOff. PE32Off. PE32+Size PE32Size PE32+TypeMeaning
u10x000x0048PTRIf the top bit (IMAGE_ORDINAL_FLAG: bit 31 or bit 63) is set, import by ordinal (low 16 bits); otherwise RVA of an IMAGE_IMPORT_BY_NAME (WORD Hint + NUL-terminated name, padded to an even size). A zero entry ends the table.

Exports

IMAGE_EXPORT_DIRECTORY 40 (0x28) bytes

FieldOffsetSizeTypeMeaning
Characteristics0x004DWORDReserved, 0.
TimeDateStamp0x044DWORDCreation time.
MajorVersion0x082WORDUser version.
MinorVersion0x0a2WORDUser version.
Name0x0c4DWORDRVA of the DLL name.
Base0x104DWORDFirst ordinal, usually 1.
NumberOfFunctions0x144DWORDEntries in AddressOfFunctions.
NumberOfNames0x184DWORDEntries in AddressOfNames and AddressOfNameOrdinals.
AddressOfFunctions0x1c4DWORDRVA of an array of function RVAs (Export Address Table), indexed by ordinal - Base. An RVA that falls inside the export directory is a forwarder string such as "NTDLL.RtlAllocateHeap".
AddressOfNames0x204DWORDRVA of an array of name RVAs, sorted for binary search.
AddressOfNameOrdinals0x244DWORDRVA of an array of WORD indexes into AddressOfFunctions, parallel to AddressOfNames.
GetProcAddress(h, "name"): binary search name in AddressOfNames → index i → AddressOfNameOrdinals[i] → AddressOfFunctions[that].

Base relocations

IMAGE_BASE_RELOCATION 8 (0x8) bytes

FieldOffsetSizeTypeMeaning
VirtualAddress0x004DWORDRVA of the 4 KiB page the entries apply to.
SizeOfBlock0x044DWORDSize of the block including this header; (SizeOfBlock - 8) / 2 WORD entries follow.
Each WORD entry is type << 12 | offset, where offset is relative to the page. If the image is not loaded at ImageBase, the loader adds the difference to every location listed here.
NameValueMeaning
IMAGE_REL_BASED_ABSOLUTE0Skipped; pads a block to a multiple of 4 bytes.
IMAGE_REL_BASED_HIGH1Add the high 16 bits of the delta to a WORD.
IMAGE_REL_BASED_LOW2Add the low 16 bits of the delta to a WORD.
IMAGE_REL_BASED_HIGHLOW3Add the delta to a 32-bit location (PE32).
IMAGE_REL_BASED_HIGHADJ4High 16 bits with adjustment; uses the next entry.
IMAGE_REL_BASED_DIR640xaAdd the delta to a 64-bit location (PE32+).

TLS callbacks

IMAGE_TLS_DIRECTORY32 / IMAGE_TLS_DIRECTORY64 24 (0x18) bytes / 40 (0x28) bytes

FieldOff. PE32Off. PE32+Size PE32Size PE32+TypeMeaning
StartAddressOfRawData0x000x0048PTRVA of the TLS template start (.tls).
EndAddressOfRawData0x040x0848PTRVA of the template end.
AddressOfIndex0x080x1048PTRVA of the DWORD that receives the TLS slot index (_tls_index).
AddressOfCallBacks0x0c0x1848PTRVA of a NULL-terminated array of PIMAGE_TLS_CALLBACK, called on process and thread attach/detach, before the entry point.
SizeOfZeroFill0x100x2044DWORDZero bytes after the template.
Characteristics0x140x2444DWORDAlignment of the TLS block (IMAGE_SCN_ALIGN_* bits).
TLS callbacks run before main and even before a debugger stops at the entry point, which is why malware and anti-debugging code like them. All addresses here are VAs, not RVAs, so they have base relocations.

COFF object files

A .obj file is a COFF file: IMAGE_FILE_HEADER at offset 0 (no DOS header, no optional header), the section table, raw data, per-section relocations, then the symbol table and the string table.

IMAGE_RELOCATION 10 (0xa) bytes

FieldOffsetSizeTypeMeaning
VirtualAddress0x004DWORDOffset of the patched location in the section.
SymbolTableIndex0x044DWORDIndex of the target symbol.
Type0x082WORDRelocation type (IMAGE_REL_AMD64_*, IMAGE_REL_ARM64_*...).
Object files only. The struct is packed (#pragma pack(2)): 10 bytes, not 12.

IMAGE_SYMBOL 18 (0x12) bytes

FieldOffsetSizeTypeMeaning
Name0x008BYTE[8]Short name, or 4 zero bytes followed by a DWORD offset in the string table.
Value0x084DWORDOffset in the section, or size for common symbols.
SectionNumber0x0c2SHORT1-based section index; 0 = undefined or common, -1 = absolute.
Type0x0e2WORD0x20 = function, 0 = not a function.
StorageClass0x101BYTE2 EXTERNAL, 3 STATIC, 103 FILE, 105 WEAK_EXTERNAL...
NumberOfAuxSymbols0x111BYTEAuxiliary 18-byte records that follow.
Packed to 18 bytes. The string table follows the symbol table; it starts with its own DWORD size.

x64 relocation types

NameValueMeaning
IMAGE_REL_AMD64_ABSOLUTE0Ignored.
IMAGE_REL_AMD64_ADDR64164-bit VA.
IMAGE_REL_AMD64_ADDR32232-bit VA.
IMAGE_REL_AMD64_ADDR32NB332-bit RVA (.pdata, .xdata).
IMAGE_REL_AMD64_REL32432-bit PC-relative from the end of the field (call, lea rip).
IMAGE_REL_AMD64_REL32_15REL32 when 1 byte of immediate follows the field.
IMAGE_REL_AMD64_REL32_26REL32, 2 bytes follow.
IMAGE_REL_AMD64_REL32_37REL32, 3 bytes follow.
IMAGE_REL_AMD64_REL32_48REL32, 4 bytes follow.
IMAGE_REL_AMD64_REL32_59REL32, 5 bytes follow.
IMAGE_REL_AMD64_SECTION0xa16-bit section index (debug info).
IMAGE_REL_AMD64_SECREL0xb32-bit offset from the start of the section (TLS, debug info).

ARM64 relocation types

NameValueMeaning
IMAGE_REL_ARM64_ABSOLUTE0Ignored.
IMAGE_REL_ARM64_ADDR32132-bit VA.
IMAGE_REL_ARM64_ADDR32NB232-bit RVA.
IMAGE_REL_ARM64_BRANCH263b/bl 26-bit offset.
IMAGE_REL_ARM64_PAGEBASE_REL214adrp page.
IMAGE_REL_ARM64_REL215adr 21-bit offset.
IMAGE_REL_ARM64_PAGEOFFSET_12A6add low 12 bits.
IMAGE_REL_ARM64_PAGEOFFSET_12L7ldr/str low 12 bits (scaled).
IMAGE_REL_ARM64_SECREL832-bit section offset.
IMAGE_REL_ARM64_ADDR640xe64-bit VA.
IMAGE_REL_ARM64_BRANCH190xfConditional branch, 19-bit offset.
IMAGE_REL_ARM64_BRANCH140x10tbz/tbnz 14-bit offset.
IMAGE_REL_ARM64_REL320x1132-bit PC-relative.

Tools

TaskCommand
Headers, data directoriesdumpbin /headers a.exe   llvm-objdump -p a.exe
Imports / exportsdumpbin /imports a.exe   dumpbin /exports a.dll
Base relocationsdumpbin /relocations a.exe   llvm-readobj --coff-basereloc a.exe
Load config (CFG, cookie)dumpbin /loadconfig a.exe   llvm-readobj --coff-load-config a.exe
Sectionsllvm-objdump -h a.exe
Disassemblellvm-objdump -d --x86-asm-syntax=intel a.exe
Pythonpefile.PE("a.exe").dump_info()
GUIPE-bear, CFF Explorer, PE Studio, Detect It Easy