A journey into PE executables - Part 1 - Introduction to PE
PE Executables
The PE stands for Portable Executable. PE is a modified version of the Common Object file format introduced in the previous post. For this reason, it is also known as PE/COFF. It's used in windows executables, drivers, dynamic libraries, etc. Like other executables, a PE file has a structure to store some features for executing in the operating system. Let's Dive into it.
Structure
DOS Header and DOS Stub
typedef struct _IMAGE_DOS_HEADER { WORD e_magic; /* 00: MZ Header signature */ WORD e_cblp; /* 02: Bytes on the last page of file */ WORD e_cp; /* 04: Pages in file */ WORD e_crlc; /* 06: Relocations */ WORD e_cparhdr; /* 08: Size of header in paragraphs */ WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */ WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */ WORD e_ss; /* 0e: Initial (relative) SS value */ WORD e_sp; /* 10: Initial SP value */ WORD e_csum; /* 12: Checksum */ WORD e_ip; /* 14: Initial IP value */ WORD e_cs; /* 16: Initial (relative) CS value */ WORD e_lfarlc; /* 18: File address of relocation table */ WORD e_ovno; /* 1a: Overlay number */ WORD e_res[4]; /* 1c: Reserved words */ WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */ WORD e_oeminfo; /* 26: OEM information; e_oemid specific */ WORD e_res2[10]; /* 28: Reserved words */ DWORD e_lfanew; /* 3c: Offset to extended header */ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
NT Headers
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; typedef struct _IMAGE_NT_HEADERS64 { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
- PE Signature
- PE File Header
- PE Optional Header
PE Signature
The PE signature is a 4-byte (DWORD) value that is located at a fixed offset in the NT header of a Windows executable file. Its purpose is to identify the file as a valid PE file, which is the standard file format for executables, DLLs, and other binary files in Windows. The signature is represented as the ASCII characters 'P', 'E', '\0', and '\0', which are followed by two bytes indicating the machine type for which the file was compiled. This format allows Windows to determine whether the file can be executed on the current system.
PE File Header
PE file header is a data structure that contains information about the structure and content of the file, including the location and size of various sections, as well as information about how the file should be loaded and executed. The PE file header is used by the operating system to load and execute the program.
typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Machine Type: The machine type field specifies the target architecture for which the object file was compiled. Examples include x86, x64, ARM, MIPS, and others. This field is essential for the operating system to properly load and execute the code within the PE file.
Number of Sections: The number of sections field indicates the number of sections in the PE file. Each section contains a different part of the executable code or data, and the operating system uses this information to properly load the file into memory.
Time and Date Stamp: This field contains the time and date when the PE file was created. This information is useful for debugging and version control purposes.
Pointer to Symbol Table: This field points to the file's symbol table, which contains information about the file's functions, variables, and other symbols. This information is used by the linker to resolve external references and by debuggers to display symbol information during debugging sessions.
Number of Symbols: This field indicates the number of symbols in the file's symbol table.
Size of Optional Header: The size of the optional header field specifies the size of the optional header section that follows the COFF header. The optional header contains additional information about the PE file's properties and is required for executable files but not for object files.
Characteristics: The characteristics field contains a set of flags that specify various attributes of the PE file, such as whether it is a DLL (dynamic-link library) or an executable file, whether it is a system file, and whether it can be relocated.
Machine Type: The machine type field specifies the target architecture for which the object file was compiled. Examples include x86, x64, ARM, MIPS, and others. This field is essential for the operating system to properly load and execute the code within the PE file.
Number of Sections: The number of sections field indicates the number of sections in the PE file. Each section contains a different part of the executable code or data, and the operating system uses this information to properly load the file into memory.
Time and Date Stamp: This field contains the time and date when the PE file was created. This information is useful for debugging and version control purposes.
Pointer to Symbol Table: This field points to the file's symbol table, which contains information about the file's functions, variables, and other symbols. This information is used by the linker to resolve external references and by debuggers to display symbol information during debugging sessions.
Number of Symbols: This field indicates the number of symbols in the file's symbol table.
Size of Optional Header: The size of the optional header field specifies the size of the optional header section that follows the COFF header. The optional header contains additional information about the PE file's properties and is required for executable files but not for object files.
Characteristics: The characteristics field contains a set of flags that specify various attributes of the PE file, such as whether it is a DLL (dynamic-link library) or an executable file, whether it is a system file, and whether it can be relocated.
PE Optional Header
The Optional Header is a data structure that contains additional information about the PE file. The Optional Header is located immediately after the file header in the PE file, and its size and contents vary depending on the target architecture and operating system. It contains information such as the target architecture, the entry point of the program, the size of the code and data sections, the location of the import and export tables, the base address where the program will be loaded into memory, and other important details about the executable file.
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic; /* 0x20b */
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;
- Magic number: A 2-byte field that identifies the target architecture of the executable file (e.g., 0x10b for 32-bit x86, 0x20b for 64-bit x86-64, etc.).
- Address of Entry Point: A 4-byte field that specifies the memory address of the program's entry point.
- Image Base: A 4-byte field that indicates the preferred base address where the program will be loaded into memory.
- Size of Image: A 4-byte field that specifies the size of the entire executable file, including all headers, sections, and resources.
- Subsystem: A 2-byte field that specifies the type of executable (e.g., console, GUI, driver, etc.).
Comments
Post a Comment