blob: 71b7e6178ed18c5675b35f865b55f184d23d7ceb [file] [log] [blame]
/* Copyright 2017 - 2021 R. Thomas
* Copyright 2017 - 2021 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! The maximum number of sections that a COFF object can have (inclusive).
static const int32_t MaxNumberOfSections16 = 65279;
//! The PE signature bytes that follows the DOS stub header.
static const char PE_Magic[] = { 'P', 'E', '\0', '\0' };
static const char Rich_Magic[] = {'R', 'i', 'c', 'h'};
static const char DanS_Magic[] = {'D', 'a', 'n', 'S'};
static const uint32_t DanS_Magic_number = 0x536E6144;
static const char BigObjMagic[] = {
'\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b',
'\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8',
};
static const uint8_t DEFAULT_NUMBER_DATA_DIRECTORIES = 15;
#pragma pack(push,1)
struct pe_header {
char signature[sizeof(PE_Magic)];
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
};
struct pe_relocation {
uint32_t VirtualAddress;
uint32_t SymbolTableIndex;
uint16_t Type;
};
struct pe_base_relocation_block {
uint32_t PageRVA;
uint32_t BlockSize;
};
struct pe_symbol {
union {
char ShortName[8];
struct
{
uint32_t Zeroes;
uint32_t Offset;
} Name;
} Name;
uint32_t Value;
int16_t SectionNumber;
uint16_t Type;
uint8_t StorageClass;
uint8_t NumberOfAuxSymbols;
};
struct pe_section {
char Name[8];
uint32_t VirtualSize;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLineNumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLineNumbers;
uint32_t Characteristics;
};
struct AuxiliaryFunctionDefinition {
uint32_t TagIndex;
uint32_t TotalSize;
uint32_t PointerToLinenumber;
uint32_t PointerToNextFunction;
char unused[2];
};
struct AuxiliarybfAndefSymbol {
uint8_t unused1[4];
uint16_t Linenumber;
uint8_t unused2[6];
uint32_t PointerToNextFunction;
uint8_t unused3[2];
};
struct AuxiliaryWeakExternal {
uint32_t TagIndex;
uint32_t Characteristics;
uint8_t unused[10];
};
struct AuxiliarySectionDefinition {
uint32_t Length;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t CheckSum;
uint32_t Number;
uint8_t Selection;
char unused;
};
struct AuxiliaryCLRToken {
uint8_t AuxType;
uint8_t unused1;
uint32_t SymbolTableIndex;
char unused2[12];
};
union Auxiliary {
AuxiliaryFunctionDefinition FunctionDefinition;
AuxiliarybfAndefSymbol bfAndefSymbol;
AuxiliaryWeakExternal WeakExternal;
AuxiliarySectionDefinition SectionDefinition;
};
/// The Import Directory Table.
///
/// There is a single array of these and one entry per imported DLL.
struct pe_import {
uint32_t ImportLookupTableRVA;
uint32_t TimeDateStamp;
uint32_t ForwarderChain;
uint32_t NameRVA;
uint32_t ImportAddressTableRVA;
};
struct ImportLookupTableEntry32 {
uint32_t data;
};
struct ImportLookupTableEntry64 {
uint64_t data;
};
struct pe32_tls {
uint32_t RawDataStartVA;
uint32_t RawDataEndVA;
uint32_t AddressOfIndex;
uint32_t AddressOfCallback;
uint32_t SizeOfZeroFill;
uint32_t Characteristics;
};
struct pe64_tls {
uint64_t RawDataStartVA;
uint64_t RawDataEndVA;
uint64_t AddressOfIndex;
uint64_t AddressOfCallback;
uint32_t SizeOfZeroFill;
uint32_t Characteristics;
};
/// The DOS compatible header at the front of all PEs.
struct pe_dos_header {
uint16_t Magic;
uint16_t UsedBytesInTheLastPage;
uint16_t FileSizeInPages;
uint16_t NumberOfRelocationItems;
uint16_t HeaderSizeInParagraphs;
uint16_t MinimumExtraParagraphs;
uint16_t MaximumExtraParagraphs;
uint16_t InitialRelativeSS;
uint16_t InitialSP;
uint16_t Checksum;
uint16_t InitialIP;
uint16_t InitialRelativeCS;
uint16_t AddressOfRelocationTable;
uint16_t OverlayNumber;
uint16_t Reserved[4];
uint16_t OEMid;
uint16_t OEMinfo;
uint16_t Reserved2[10];
uint32_t AddressOfNewExeHeader;
};
struct pe64_optional_header {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint; // RVA
uint32_t BaseOfCode; // RVA
//uint32_t BaseOfData; // RVA
uint64_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DLLCharacteristics;
uint64_t SizeOfStackReserve;
uint64_t SizeOfStackCommit;
uint64_t SizeOfHeapReserve;
uint64_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSize;
};
struct pe32_optional_header {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint; // RVA
uint32_t BaseOfCode; // RVA
uint32_t BaseOfData; // RVA
uint32_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DLLCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSize;
};
struct pe_data_directory {
uint32_t RelativeVirtualAddress;
uint32_t Size;
};
struct pe_debug {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
uint16_t MinorVersion;
uint32_t Type;
uint32_t SizeOfData;
uint32_t AddressOfRawData;
uint32_t PointerToRawData;
};
struct pe_pdb_70 {
uint32_t cv_signature;
uint8_t signature[16];
uint32_t age;
char* filename;
};
struct pe_pdb_20 {
uint32_t cv_signature;
uint32_t offset;
uint32_t signature;
uint32_t age;
char* filename;
};
struct pe_pogo {
uint32_t start_rva;
uint32_t size;
char name[1];
};
struct pe_resource_directory_table {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
uint16_t MinorVersion;
uint16_t NumberOfNameEntries;
uint16_t NumberOfIDEntries;
};
struct pe_resource_directory_entries {
union {
uint32_t NameRVA;
uint32_t IntegerID;
} NameID;
uint32_t RVA;
};
struct pe_resource_data_entry {
uint32_t DataRVA;
uint32_t Size;
uint32_t Codepage;
uint32_t Reserved;
};
struct pe_resource_string {
int16_t Length;
uint16_t Name[1];
};
struct pe_resource_acceltableentry {
int16_t fFlags;
int16_t wAnsi;
int16_t wId;
int16_t padding;
};
//
// Export structures
//
struct pe_export_directory_table {
uint32_t ExportFlags; ///< Reserverd must be 0
uint32_t Timestamp; ///< The time and date that the export data was created
uint16_t MajorVersion; ///< The Major version number
uint16_t MinorVersion; ///< The Minor version number
uint32_t NameRVA; ///< The address of the ASCII DLL's name (RVA)
uint32_t OrdinalBase; ///< The starting ordinal number for exports. (Usually 1)
uint32_t AddressTableEntries; ///< Number of entries in the export address table
uint32_t NumberOfNamePointers; ///< Number of entries in the name pointer table
uint32_t ExportAddressTableRVA; ///< Address of the export address table (RVA)
uint32_t NamePointerRVA; ///< Address of the name pointer table (RVA)
uint32_t OrdinalTableRVA; ///< Address of the ordinal table (RVA)
};
struct pe_resource_fixed_file_info {
uint32_t signature; // e.g. 0xfeef04bd
uint32_t struct_version; // e.g. 0x00000042 = "0.42"
uint32_t file_version_MS; // e.g. 0x00030075 = "3.75"
uint32_t file_version_LS; // e.g. 0x00000031 = "0.31"
uint32_t product_version_MS; // e.g. 0x00030010 = "3.10"
uint32_t product_version_LS; // e.g. 0x00000031 = "0.31"
uint32_t file_flags_mask; // = 0x3F for version "0.42"
uint32_t file_flags; // e.g. VFF_DEBUG | VFF_PRERELEASE
uint32_t file_OS; // e.g. VOS_DOS_WINDOWS16
uint32_t file_type; // e.g. VFT_DRIVER
uint32_t file_subtype; // e.g. VFT2_DRV_KEYBOARD
uint32_t file_date_MS; // e.g. 0
uint32_t file_date_LS; // e.g. 0
};
struct pe_resource_version_info {
uint16_t length;
uint16_t sizeof_value;
uint16_t type;
char16_t key[16];
// uint16_t padding;
//
// uint16_t padding;
// uint16_t children
};
//! Resource icons directory structure
//! Based on https://docs.microsoft.com/en-us/windows/win32/menurc/resources-reference
//!
//! This is the begining of the RESOURCE_TYPES::GROUP_ICON content
struct pe_resource_icon_dir {
uint16_t reserved; ///< Reserved
uint16_t type; ///< Resource type (1 for icons)
uint16_t count; ///< Number of icons
};
//! Structure that follows pe_resource_icon_dir in a resource entry
struct pe_resource_icon_group {
uint8_t width; ///< Width, in pixels, of the image
uint8_t height; ///< Height, in pixels, of the image
uint8_t color_count; ///< Number of colors in image (0 if >=8bpp)
uint8_t reserved; ///< Reserved (must be 0)
uint16_t planes; ///< Color Planes
uint16_t bit_count; ///< Bits per pixel
uint32_t size; ///< Size of the image in bytes
uint16_t ID; ///< The associated ID
};
//! Structure that follows pe_resource_icon_dir in a icon **file**
struct pe_icon_header {
uint8_t width; ///< Width, in pixels, of the image
uint8_t height; ///< Height, in pixels, of the image
uint8_t color_count; ///< Number of colors in image (0 if >=8bpp)
uint8_t reserved; ///< Reserved (must be 0)
uint16_t planes; ///< Color Planes
uint16_t bit_count; ///< Bits per pixel
uint32_t size; ///< Size of the image in bytes
uint32_t offset; ///< Offset to the pixels
};
//! Extended dialog box template
struct pe_dialog_template_ext {
uint16_t version;
uint16_t signature;
uint32_t help_id;
uint32_t ext_style;
uint32_t style;
uint16_t nbof_items;
int16_t x;
int16_t y;
int16_t cx;
int16_t cy;
// sz_Or_Ord menu;
// sz_Or_Ord windowClass;
// char16_t title[titleLen];
// uint16_t pointsize;
// uint16_t weight;
// uint8_t italic;
// uint8_t charset;
// char16_t typeface[stringLen];
};
//! Dialog box template
struct pe_dialog_template {
uint32_t style;
uint32_t ext_style;
uint16_t nbof_items;
int16_t x;
int16_t y;
int16_t cx;
int16_t cy;
};
//! Extended dialog box template item
struct pe_dialog_item_template_ext {
uint32_t help_id;
uint32_t ext_style;
uint32_t style;
int16_t x;
int16_t y;
int16_t cx;
int16_t cy;
uint32_t id;
// sz_Or_Ord windowClass;
// sz_Or_Ord title;
// uint16_t extra_count;
};
//! Dialog box template item
struct pe_dialog_item_template {
uint32_t style;
uint32_t ext_style;
int16_t x;
int16_t y;
int16_t cx;
int16_t cy;
uint16_t id;
};
struct pe_code_integrity {
uint16_t Flags;
uint16_t Catalog;
uint32_t CatalogOffset;
uint32_t Reserved;
};
struct pe_exception_entry_x64 {
uint32_t address_start_rva;
uint32_t address_end_rva;
uint32_t unwind_info_rva;
};
struct pe_exception_entry_mips {
uint32_t address_start_va;
uint32_t address_end_va;
uint32_t exception_handler;
uint32_t handler_data;
uint32_t prolog_end_address;
};
struct pe_exception_entry_arm {
uint32_t address_start_va;
uint32_t data;
};
#pragma pack(pop)