diff --git a/dissect/executable/__init__.py b/dissect/executable/__init__.py index 43d2a88..f9c465a 100644 --- a/dissect/executable/__init__.py +++ b/dissect/executable/__init__.py @@ -1,5 +1,7 @@ -from dissect.executable.elf import ELF +from dissect.executable.elf.elf import ELF +from dissect.executable.pe.pe import PE __all__ = [ "ELF", + "PE", ] diff --git a/dissect/executable/pe/__init__.py b/dissect/executable/pe/__init__.py index e69de29..1c31270 100644 --- a/dissect/executable/pe/__init__.py +++ b/dissect/executable/pe/__init__.py @@ -0,0 +1,5 @@ +from dissect.executable.pe.pe import PE + +__all__ = [ + "PE", +] diff --git a/dissect/executable/pe/c_pe.py b/dissect/executable/pe/c_pe.py new file mode 100644 index 0000000..777a500 --- /dev/null +++ b/dissect/executable/pe/c_pe.py @@ -0,0 +1,2234 @@ +# References: +# - ntimage.h +# - winnt.h +from __future__ import annotations + +from dissect.cstruct import cstruct + +c_pe_def = """ +typedef BYTE BOOLEAN; + +// +// Image Format +// + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_VXD_SIGNATURE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + USHORT e_magic; // Magic number + USHORT e_cblp; // Bytes on last page of file + USHORT e_cp; // Pages in file + USHORT e_crlc; // Relocations + USHORT e_cparhdr; // Size of header in paragraphs + USHORT e_minalloc; // Minimum extra paragraphs needed + USHORT e_maxalloc; // Maximum extra paragraphs needed + USHORT e_ss; // Initial (relative) SS value + USHORT e_sp; // Initial SP value + USHORT e_csum; // Checksum + USHORT e_ip; // Initial IP value + USHORT e_cs; // Initial (relative) CS value + USHORT e_lfarlc; // File address of relocation table + USHORT e_ovno; // Overlay number + USHORT e_res[4]; // Reserved words + USHORT e_oemid; // OEM identifier (for e_oeminfo) + USHORT e_oeminfo; // OEM information; e_oemid specific + USHORT e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + USHORT ne_magic; // Magic number + CHAR ne_ver; // Version number + CHAR ne_rev; // Revision number + USHORT ne_enttab; // Offset of Entry Table + USHORT ne_cbenttab; // Number of bytes in Entry Table + LONG ne_crc; // Checksum of whole file + USHORT ne_flags; // Flag word + USHORT ne_autodata; // Automatic data segment number + USHORT ne_heap; // Initial heap allocation + USHORT ne_stack; // Initial stack allocation + LONG ne_csip; // Initial CS:IP setting + LONG ne_sssp; // Initial SS:SP setting + USHORT ne_cseg; // Count of file segments + USHORT ne_cmod; // Entries in Module Reference Table + USHORT ne_cbnrestab; // Size of non-resident name table + USHORT ne_segtab; // Offset of Segment Table + USHORT ne_rsrctab; // Offset of Resource Table + USHORT ne_restab; // Offset of resident name table + USHORT ne_modtab; // Offset of Module Reference Table + USHORT ne_imptab; // Offset of Imported Names Table + LONG ne_nrestab; // Offset of Non-resident Names Table + USHORT ne_cmovent; // Count of movable entries + USHORT ne_align; // Segment alignment shift count + USHORT ne_cres; // Count of resource segments + UCHAR ne_exetyp; // Target Operating system + UCHAR ne_flagsothers; // Other .EXE flags + USHORT ne_pretthunks; // offset to return thunks + USHORT ne_psegrefbytes; // offset to segment ref. bytes + USHORT ne_swaparea; // Minimum code swap area size + USHORT ne_expver; // Expected Windows version number +} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +typedef struct _IMAGE_VXD_HEADER { // Windows VXD header + USHORT e32_magic; // Magic number + UCHAR e32_border; // The byte ordering for the VXD + UCHAR e32_worder; // The word ordering for the VXD + ULONG e32_level; // The EXE format level for now = 0 + USHORT e32_cpu; // The CPU type + USHORT e32_os; // The OS type + ULONG e32_ver; // Module version + ULONG e32_mflags; // Module flags + ULONG e32_mpages; // Module # pages + ULONG e32_startobj; // Object # for instruction pointer + ULONG e32_eip; // Extended instruction pointer + ULONG e32_stackobj; // Object # for stack pointer + ULONG e32_esp; // Extended stack pointer + ULONG e32_pagesize; // VXD page size + ULONG e32_lastpagesize; // Last page size in VXD + ULONG e32_fixupsize; // Fixup section size + ULONG e32_fixupsum; // Fixup section checksum + ULONG e32_ldrsize; // Loader section size + ULONG e32_ldrsum; // Loader section checksum + ULONG e32_objtab; // Object table offset + ULONG e32_objcnt; // Number of objects in module + ULONG e32_objmap; // Object page map offset + ULONG e32_itermap; // Object iterated data map offset + ULONG e32_rsrctab; // Offset of Resource Table + ULONG e32_rsrccnt; // Number of resource entries + ULONG e32_restab; // Offset of resident name table + ULONG e32_enttab; // Offset of Entry Table + ULONG e32_dirtab; // Offset of Module Directive Table + ULONG e32_dircnt; // Number of module directives + ULONG e32_fpagetab; // Offset of Fixup Page Table + ULONG e32_frectab; // Offset of Fixup Record Table + ULONG e32_impmod; // Offset of Import Module Name Table + ULONG e32_impmodcnt; // Number of entries in Import Module Name Table + ULONG e32_impproc; // Offset of Import Procedure Name Table + ULONG e32_pagesum; // Offset of Per-Page Checksum Table + ULONG e32_datapage; // Offset of Enumerated Data Pages + ULONG e32_preload; // Number of preload pages + ULONG e32_nrestab; // Offset of Non-resident Names Table + ULONG e32_cbnrestab; // Size of Non-resident Name Table + ULONG e32_nressum; // Non-resident Name Table Checksum + ULONG e32_autodata; // Object # for automatic data object + ULONG e32_debuginfo; // Offset of the debugging information + ULONG e32_debuglen; // The length of the debugging info. in bytes + ULONG e32_instpreload; // Number of instance pages in preload section of VXD file + ULONG e32_instdemand; // Number of instance pages in demand load section of VXD file + ULONG e32_heapsize; // Size of heap - for 16-bit apps + UCHAR e32_res3[12]; // Reserved words + ULONG e32_winresoff; + ULONG e32_winreslen; + USHORT e32_devid; // Device ID for VxD + USHORT e32_ddkver; // DDK version for VxD +} IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER; + +// +// File header format. +// + +flag IMAGE_FILE : USHORT { + RELOCS_STRIPPED = 0x0001, // Relocation info stripped from file. + EXECUTABLE_IMAGE = 0x0002, // File is executable (i.e. no unresolved externel references). + LINE_NUMS_STRIPPED = 0x0004, // Line nunbers stripped from file. + LOCAL_SYMS_STRIPPED = 0x0008, // Local symbols stripped from file. + AGGRESSIVE_WS_TRIM = 0x0010, // Agressively trim working set + LARGE_ADDRESS_AWARE = 0x0020, // App can handle >2gb addresses + BYTES_REVERSED_LO = 0x0080, // Bytes of machine word are reversed. + 32BIT_MACHINE = 0x0100, // 32 bit word machine. + DEBUG_STRIPPED = 0x0200, // Debugging info stripped from file in .DBG file + REMOVABLE_RUN_FROM_SWAP = 0x0400, // If Image is on removable media, copy and run from the swap file. + NET_RUN_FROM_SWAP = 0x0800, // If Image is on Net, copy and run from the swap file. + SYSTEM = 0x1000, // System File. + DLL = 0x2000, // File is a DLL. + UP_SYSTEM_ONLY = 0x4000, // File should only be run on a UP machine + BYTES_REVERSED_HI = 0x8000, // Bytes of machine word are reversed. +}; + +enum IMAGE_FILE_MACHINE : USHORT { + UNKNOWN = 0, + TARGET_HOST = 0x0001, // Useful for indicating we want to interact with the host and not a WoW guest. + I386 = 0x014c, // Intel 386. + R3000 = 0x0162, // MIPS little-endian, 0x160 big-endian + R4000 = 0x0166, // MIPS little-endian + R10000 = 0x0168, // MIPS little-endian + WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2 + ALPHA = 0x0184, // Alpha_AXP + SH3 = 0x01a2, // SH3 little-endian + SH3DSP = 0x01a3, + SH3E = 0x01a4, // SH3E little-endian + SH4 = 0x01a6, // SH4 little-endian + SH5 = 0x01a8, // SH5 + ARM = 0x01c0, // ARM Little-Endian + THUMB = 0x01c2, // ARM Thumb/Thumb-2 Little-Endian + ARMNT = 0x01c4, // ARM Thumb-2 Little-Endian + AM33 = 0x01d3, + POWERPC = 0x01F0, // IBM PowerPC Little-Endian + POWERPCFP = 0x01f1, + IA64 = 0x0200, // Intel 64 + MIPS16 = 0x0266, // MIPS + ALPHA64 = 0x0284, // ALPHA64 + MIPSFPU = 0x0366, // MIPS + MIPSFPU16 = 0x0466, // MIPS + AXP64 = 0x0284, // IMAGE_FILE_MACHINE_ALPHA64 + TRICORE = 0x0520, // Infineon + CEF = 0x0CEF, + EBC = 0x0EBC, // EFI Byte Code + CHPE_X86 = 0x3A64, + RISCV32 = 0x5032, + RISCV64 = 0x5064, + RISCV128 = 0x5128, + AMD64 = 0x8664, // AMD64 (K8) + M32R = 0x9041, // M32R little-endian + ARM64 = 0xAA64, // ARM64 Little-Endian + CEE = 0xC0EE, +}; + +typedef struct _IMAGE_FILE_HEADER { + IMAGE_FILE_MACHINE Machine; + USHORT NumberOfSections; + ULONG TimeDateStamp; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + USHORT SizeOfOptionalHeader; + IMAGE_FILE Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + ULONG VirtualAddress; + ULONG Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +// Subsystem Values + +enum IMAGE_SUBSYSTEM : USHORT { + UNKNOWN = 0, // Unknown subsystem. + NATIVE = 1, // Image doesn't require a subsystem. + WINDOWS_GUI = 2, // Image runs in the Windows GUI subsystem. + WINDOWS_CUI = 3, // Image runs in the Windows character subsystem. + OS2_CUI = 5, // image runs in the OS/2 character subsystem. + POSIX_CUI = 7, // image runs in the Posix character subsystem. + NATIVE_WINDOWS = 8, // image is a native Win9x driver. + WINDOWS_CE_GUI = 9, // Image runs in the Windows CE subsystem. + EFI_APPLICATION = 10, + EFI_BOOT_SERVICE_DRIVER = 11, + EFI_RUNTIME_DRIVER = 12, + EFI_ROM = 13, + XBOX = 14, + WINDOWS_BOOT_APPLICATION = 16, + XBOX_CODE_CATALOG = 17, +}; + +// DllCharacteristics Entries + +flag IMAGE_DLLCHARACTERISTICS : USHORT { + PROCESS_INIT = 0x0001, // Reserved. (IMAGE_LIBRARY_PROCESS_INIT) + PROCESS_TERM = 0x0002, // Reserved. (IMAGE_LIBRARY_PROCESS_TERM) + THREAD_INIT = 0x0004, // Reserved. (IMAGE_LIBRARY_THREAD_INIT) + THREAD_TERM = 0x0008, // Reserved. (IMAGE_LIBRARY_THREAD_TERM) + HIGH_ENTROPY_VA = 0x0020, // Image can handle a high entropy 64-bit virtual address space. + DYNAMIC_BASE = 0x0040, // DLL can move. + FORCE_INTEGRITY = 0x0080, // Code Integrity Image + NX_COMPAT = 0x0100, // Image is NX compatible + NO_ISOLATION = 0x0200, // Image understands isolation and doesn't want it + NO_SEH = 0x0400, // Image does not use SEH. No SE handler may reside in this image + NO_BIND = 0x0800, // Do not bind this image. + APPCONTAINER = 0x1000, // Image should execute in an AppContainer + WDM_DRIVER = 0x2000, // Driver uses WDM model + GUARD_CF = 0x4000, // Image supports Control Flow Guard. + TERMINAL_SERVER_AWARE = 0x8000, +}; + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONG BaseOfData; + + // + // NT additional fields. + // + + ULONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + IMAGE_SUBSYSTEM Subsystem; + IMAGE_DLLCHARACTERISTICS DllCharacteristics; + ULONG SizeOfStackReserve; + ULONG SizeOfStackCommit; + ULONG SizeOfHeapReserve; + ULONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONGLONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + IMAGE_SUBSYSTEM Subsystem; + IMAGE_DLLCHARACTERISTICS DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS64 { + ULONG Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +typedef struct _IMAGE_NT_HEADERS { + ULONG Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; + +// Directory Entries + +enum IMAGE_DIRECTORY_ENTRY { + EXPORT = 0, // Export Directory + IMPORT = 1, // Import Directory + RESOURCE = 2, // Resource Directory + EXCEPTION = 3, // Exception Directory + SECURITY = 4, // Security Directory + BASERELOC = 5, // Base Relocation Table + DEBUG = 6, // Debug Directory + COPYRIGHT = 7, // (X86 usage) + ARCHITECTURE = 7, // Architecture Specific Data + GLOBALPTR = 8, // RVA of GP + TLS = 9, // TLS Directory + LOAD_CONFIG = 10, // Load Configuration Directory + BOUND_IMPORT = 11, // Bound Import Directory in headers + IAT = 12, // Import Address Table + DELAY_IMPORT = 13, // Delay Load Import Descriptors + COM_DESCRIPTOR = 14, // COM Runtime descriptor +}; + +// +// Section header format. +// + +flag IMAGE_SCN : ULONG { + TYPE_REG = 0x00000000, // Reserved. + TYPE_DSECT = 0x00000001, // Reserved. + TYPE_NOLOAD = 0x00000002, // Reserved. + TYPE_GROUP = 0x00000004, // Reserved. + TYPE_NO_PAD = 0x00000008, // Reserved. + TYPE_COPY = 0x00000010, // Reserved. + + CNT_CODE = 0x00000020, // Section contains code. + CNT_INITIALIZED_DATA = 0x00000040, // Section contains initialized data. + CNT_UNINITIALIZED_DATA = 0x00000080, // Section contains uninitialized data. + + LNK_OTHER = 0x00000100, // Reserved. + LNK_INFO = 0x00000200, // Section contains comments or some other type of information. + TYPE_OVER = 0x00000400, // Reserved. + LNK_REMOVE = 0x00000800, // Section contents will not become part of image. + LNK_COMDAT = 0x00001000, // Section contents comdat. +// // = 0x00002000, // Reserved. + NO_DEFER_SPEC_EXC = 0x00004000, // Reset speculative exceptions handling bits in the TLB entries for this section. + GPREL = 0x00008000, // Section content can be accessed relative to GP + MEM_FARDATA = 0x00008000, +// MEM_SYSHEAP = 0x00010000, // Obsolete + MEM_PURGEABLE = 0x00020000, + MEM_16BIT = 0x00020000, + MEM_LOCKED = 0x00040000, + MEM_PRELOAD = 0x00080000, + + ALIGN_1BYTES = 0x00100000, + ALIGN_2BYTES = 0x00200000, + ALIGN_4BYTES = 0x00300000, + ALIGN_8BYTES = 0x00400000, + ALIGN_16BYTES = 0x00500000, // Default alignment if no others are specified. + ALIGN_32BYTES = 0x00600000, + ALIGN_64BYTES = 0x00700000, + ALIGN_128BYTES = 0x00800000, + ALIGN_256BYTES = 0x00900000, + ALIGN_512BYTES = 0x00A00000, + ALIGN_1024BYTES = 0x00B00000, + ALIGN_2048BYTES = 0x00C00000, + ALIGN_4096BYTES = 0x00D00000, + ALIGN_8192BYTES = 0x00E00000, +// // Unused = 0x00F00000, + ALIGN_MASK = 0x00F00000, + + LNK_NRELOC_OVFL = 0x01000000, // Section contains extended relocations. + MEM_DISCARDABLE = 0x02000000, // Section can be discarded. + MEM_NOT_CACHED = 0x04000000, // Section is not cachable. + MEM_NOT_PAGED = 0x08000000, // Section is not pageable. + MEM_SHARED = 0x10000000, // Section is shareable. + MEM_EXECUTE = 0x20000000, // Section is executable. + MEM_READ = 0x40000000, // Section is readable. + MEM_WRITE = 0x80000000, // Section is writeable. +}; + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + CHAR Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + ULONG PhysicalAddress; + ULONG VirtualSize; + } Misc; + ULONG VirtualAddress; + ULONG SizeOfRawData; + ULONG PointerToRawData; + ULONG PointerToRelocations; + ULONG PointerToLinenumbers; + USHORT NumberOfRelocations; + USHORT NumberOfLinenumbers; + IMAGE_SCN Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +// +// Symbol format. +// + +/* TODO */ + +// +// Based relocation format. +// + +// +// Based relocation types. +// + +enum IMAGE_REL_BASED { + ABSOLUTE = 0, // The base relocation is skipped. This type can be used to pad a block. + HIGH = 1, // The base relocation adds the high 16 bits of the difference to the 16-bit field at offset. The 16-bit field represents the high value of a 32-bit word. + LOW = 2, // The base relocation adds the low 16 bits of the difference to the 16-bit field at offset. The 16-bit field represents the low half of a 32-bit word. + HIGHLOW = 3, // The base relocation applies all 32 bits of the difference to the 32-bit field at offset. + HIGHADJ = 4, // The base relocation adds the high 16 bits of the difference to the 16-bit field at offset. The 16-bit field represents the high value of a 32-bit word. The low 16 bits of the 32-bit value are stored in the 16-bit word that follows this base relocation. This means that this base relocation occupies two slots. + MIPS_JMPADDR = 5, // The relocation interpretation is dependent on the machine type. When the machine type is MIPS, the base relocation applies to a MIPS jump instruction. + ARM_MOV32 = 5, // This relocation is meaningful only when the machine type is ARM or Thumb. The base relocation applies the 32-bit address of a symbol across a consecutive MOVW/MOVT instruction pair. + RISCV_HIGH20 = 5, // This relocation is only meaningful when the machine type is RISC-V. The base relocation applies to the high 20 bits of a 32-bit absolute address. + MACHINE_SPECIFIC_5 = 5, // The relocation interpretation is dependent on the machine type. + RESERVED = 6, // Reserved, must be zero. + THUMB_MOV32 = 7, // This relocation is meaningful only when the machine type is Thumb. The base relocation applies the 32-bit address of a symbol to a consecutive MOVW/MOVT instruction pair. + RISCV_LOW12I = 7, // This relocation is only meaningful when the machine type is RISC-V. The base relocation applies to the low 12 bits of a 32-bit absolute address formed in RISC-V I-type instruction format. + REL32 = 7, + MACHINE_SPECIFIC_7 = 7, // The relocation interpretation is dependent on the machine type. + RISCV_LOW12S = 8, // This relocation is only meaningful when the machine type is RISC-V. The base relocation applies to the low 12 bits of a 32-bit absolute address formed in RISC-V S-type instruction format. + LOONGARCH32_MARK_LA = 8, // This relocation is only meaningful when the machine type is LoongArch 32-bit. The base relocation applies to a 32-bit absolute address formed in two consecutive instructions. + LOONGARCH64_MARK_LA = 8, // This relocation is only meaningful when the machine type is LoongArch 64-bit. The base relocation applies to a 64-bit absolute address formed in four consecutive instructions. + VXD_RELATIVE = 8, + MACHINE_SPECIFIC_8 = 8, // The relocation interpretation is dependent on the machine type. + MIPS_JMPADDR16 = 9, // The relocation is only meaningful when the machine type is MIPS. The base relocation applies to a MIPS16 jump instruction. + IA64_IMM64 = 9, + MACHINE_SPECIFIC_9 = 9, // The relocation interpretation is dependent on the machine type. + DIR64 = 10, // The base relocation applies the difference to the 64-bit field at offset. +}; + +typedef struct _IMAGE_BASE_RELOCATION { + ULONG VirtualAddress; + ULONG SizeOfBlock; +// USHORT TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START b"!\n" +#define IMAGE_ARCHIVE_END b"`\n" +#define IMAGE_ARCHIVE_PAD b"\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER b"/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER b"// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + CHAR Name[16]; // File member name - `/' terminated. + CHAR Date[12]; // File member date - decimal. + CHAR UserID[6]; // File member user id - decimal. + CHAR GroupID[6]; // File member group id - decimal. + CHAR Mode[8]; // File member mode - octal. + CHAR Size[10]; // File member size - decimal. + CHAR EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG Name; + ULONG Base; + ULONG NumberOfFunctions; + ULONG NumberOfNames; + ULONG AddressOfFunctions; // RVA from base of image + ULONG AddressOfNames; // RVA from base of image + ULONG AddressOfNameOrdinals; // RVA from base of image +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + USHORT Hint; + CHAR Name[]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA64 { + union { + ULONGLONG ForwarderString; // PUCHAR + ULONGLONG Function; // PULONG + ULONGLONG Ordinal; + ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64; + +typedef struct _IMAGE_THUNK_DATA32 { + union { + ULONG ForwarderString; // PUCHAR + ULONG Function; // PULONG + ULONG Ordinal; + ULONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA32, *PIMAGE_THUNK_DATA32; + +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000 +#define IMAGE_ORDINAL_FLAG32 0x80000000 + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + union { + ULONG Characteristics; // 0 for terminating null import descriptor + ULONG OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + }; + ULONG TimeDateStamp; // 0 if not bound, + // -1 if bound, and real date/time stamp + // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) + // O.W. date/time stamp of DLL bound to (Old BIND) + + ULONG ForwarderChain; // -1 if no forwarders + ULONG Name; + ULONG FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +// +// Thread Local Storage +// + +typedef struct _IMAGE_TLS_DIRECTORY64 { + ULONGLONG StartAddressOfRawData; + ULONGLONG EndAddressOfRawData; + ULONGLONG AddressOfIndex; // PULONG + ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; + ULONG SizeOfZeroFill; + union { + ULONG Characteristics; + struct { + ULONG Reserved0 : 20; + ULONG Alignment : 4; + ULONG Reserved1 : 8; + }; + }; +} IMAGE_TLS_DIRECTORY64, *PIMAGE_TLS_DIRECTORY64; + +typedef struct _IMAGE_TLS_DIRECTORY32 { + ULONG StartAddressOfRawData; + ULONG EndAddressOfRawData; + ULONG AddressOfIndex; // PULONG + ULONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * + ULONG SizeOfZeroFill; + union { + ULONG Characteristics; + struct { + ULONG Reserved0 : 20; + ULONG Alignment : 4; + ULONG Reserved1 : 8; + }; + }; +} IMAGE_TLS_DIRECTORY32, *PIMAGE_TLS_DIRECTORY32; + +// +// New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ] +// + +typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR { + ULONG TimeDateStamp; + USHORT OffsetModuleName; + USHORT NumberOfModuleForwarderRefs; +// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows +} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_BOUND_FORWARDER_REF { + ULONG TimeDateStamp; + USHORT OffsetModuleName; + USHORT Reserved; +} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; + +typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR { + union { + ULONG AllAttributes; + struct { + ULONG RvaBased : 1; // Delay load version 2 + ULONG ReservedAttributes : 31; + }; + } Attributes; + + ULONG DllNameRVA; // RVA to the name of the target library (NULL-terminate ASCII string) + ULONG ModuleHandleRVA; // RVA to the HMODULE caching location (PHMODULE) + ULONG ImportAddressTableRVA; // RVA to the start of the IAT (PIMAGE_THUNK_DATA) + ULONG ImportNameTableRVA; // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData) + ULONG BoundImportAddressTableRVA; // RVA to an optional bound IAT + ULONG UnloadInformationTableRVA; // RVA to an optional unload info table + ULONG TimeDateStamp; // 0 if not bound, + // Otherwise, date/time of the target DLL +} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR; + +// +// Resource Format. +// + +enum RT { + CURSOR = 1, + BITMAP = 2, + ICON = 3, + MENU = 4, + DIALOG = 5, + STRING = 6, + FONTDIR = 7, + FONT = 8, + ACCELERATOR = 9, + RCDATA = 10, + MESSAGETABLE = 11, + GROUP_CURSOR = 12, + GROUP_ICON = 14, + VERSION = 16, + DLGINCLUDE = 17, + PLUGPLAY = 19, + VXD = 20, + ANICURSOR = 21, + ANIICON = 22, + HTML = 23, + MANIFEST = 24, +}; + +// +// Resource directory consists of two counts, following by a variable length +// array of directory entries. The first count is the number of entries at +// beginning of the array that have actual names associated with each entry. +// The entries are in ascending order, case insensitive strings. The second +// count is the number of entries that immediately follow the named entries. +// This second count identifies the number of entries that have 16-bit integer +// Ids as their name. These entries are also sorted in ascending order. +// +// This structure allows fast lookup by either name or number, but for any +// given resource entry only one form of lookup is supported, not both. +// This is consistant with the syntax of the .RC file and the .RES file. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + USHORT NumberOfNamedEntries; + USHORT NumberOfIdEntries; + /* IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */ +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +// +// Each directory contains the 32-bit Name of the entry and an offset, +// relative to the beginning of the resource directory of the data associated +// with this directory entry. If the name of the entry is an actual text +// string instead of an integer Id, then the high order bit of the name field +// is set to one and the low order 31-bits are an offset, relative to the +// beginning of the resource directory of the string, which is of type +// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the +// low-order 16-bits are the integer Id that identify this resource directory +// entry. If the directory entry is yet another resource directory (i.e. a +// subdirectory), then the high order bit of the offset field will be +// set to indicate this. Otherwise the high bit is clear and the offset +// field points to a resource data entry. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { + ULONG NameOffset:31; + ULONG NameIsString:1; + }; + ULONG Name; + USHORT Id; + }; + union { + ULONG OffsetToData; + struct { + ULONG OffsetToDirectory:31; + ULONG DataIsDirectory:1; + }; + }; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +// +// For resource directory entries that have actual string names, the Name +// field of the directory entry points to an object of the following type. +// All of these string objects are stored together after the last resource +// directory entry and before the first resource data object. This minimizes +// the impact of these variable length objects on the alignment of the fixed +// size directory entry objects. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + USHORT Length; + CHAR NameString[Length]; +} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + USHORT Length; + WCHAR NameString[Length]; +} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; + +// +// Each resource data entry describes a leaf node in the resource directory +// tree. It contains an offset, relative to the beginning of the resource +// directory of the data for the resource, a size field that gives the number +// of bytes of data at that offset, a CodePage that should be used when +// decoding code point values within the resource data. Typically for new +// applications the code page would be the unicode code page. +// + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + ULONG OffsetToData; + ULONG Size; + ULONG CodePage; + ULONG Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + +typedef struct _VS_FIXEDFILEINFO { + DWORD dwSignature; + DWORD dwStrucVersion; + DWORD dwFileVersionMS; + DWORD dwFileVersionLS; + DWORD dwProductVersionMS; + DWORD dwProductVersionLS; + DWORD dwFileFlagsMask; + DWORD dwFileFlags; + DWORD dwFileOS; + DWORD dwFileType; + DWORD dwFileSubtype; + DWORD dwFileDateMS; + DWORD dwFileDateLS; +} VS_FIXEDFILEINFO, *PVS_FIXEDFILEINFO; + +flag VS_FF { + DEBUG = 0x00000001, // The file contains debugging information or is compiled with debugging features enabled. + PRERELEASE = 0x00000002, // The file is a development version, not a commercially released product. + PATCHED = 0x00000004, // The file has been modified and is not identical to the original shipping file of the same version number. + PRIVATEBUILD = 0x00000008, // The file was not built using standard release procedures. If this flag is set, the StringFileInfo structure should contain a PrivateBuild entry. + INFOINFERRED = 0x00000010, // The file's version structure was created dynamically; therefore, some of the members in this structure may be empty or incorrect. This flag should never be set in a file's VS_VERSIONINFO data. + SPECIALBUILD = 0x00000020, // The file was built by the original company using standard release procedures but is a variation of the normal file of the same version number. If this flag is set, the StringFileInfo structure should contain a SpecialBuild entry. +}; + +enum VOS { + UNKNOWN = 0x00000000, // The operating system for which the file was designed is unknown to the system. + WINDOWS16 = 0x00000001, // The file was designed for 16-bit Windows. + PM16 = 0x00000002, // The file was designed for 16-bit Presentation Manager. + PM32 = 0x00000003, // The file was designed for 32-bit Presentation Manager. + WINDOWS32 = 0x00000004, // The file was designed for 32-bit Windows. + DOS = 0x00010000, // The file was designed for MS-DOS. + OS216 = 0x00020000, // The file was designed for 16-bit OS/2. + OS232 = 0x00030000, // The file was designed for 32-bit OS/2. + NT = 0x00040000, // The file was designed for Windows NT. +}; + +enum VFT { + UNKNOWN = 0x00000000, // The file type is unknown to the system. + APP = 0x00000001, // The file contains an application. + DLL = 0x00000002, // The file contains a DLL. + DRV = 0x00000003, // The file contains a device driver. If dwFileType is VFT_DRV, dwFileSubtype contains a more specific description of the driver. + FONT = 0x00000004, // The file contains a font. If dwFileType is VFT_FONT, dwFileSubtype contains a more specific description of the font file. + VXD = 0x00000005, // The file contains a virtual device. + STATIC_LIBRARY = 0x00000007, // The file contains a static-link library. +}; + +enum VFT2_DRV { + UNKNOWN = 0x00000000, // The driver type is unknown by the system. + PRINTER = 0x00000001, // The file contains a printer driver. + KEYBOARD = 0x00000002, // The file contains a keyboard driver. + LANGUAGE = 0x00000003, // The file contains a language driver. + DISPLAY = 0x00000004, // The file contains a display driver. + MOUSE = 0x00000005, // The file contains a mouse driver. + NETWORK = 0x00000006, // The file contains a network driver. + SYSTEM = 0x00000007, // The file contains a system driver. + INSTALLABLE = 0x00000008, // The file contains an installable driver. + SOUND = 0x00000009, // The file contains a sound driver. + COMM = 0x0000000A, // The file contains a communications driver. + INPUTMETHOD = 0x0000000B, + VERSIONED_PRINTER = 0x0000000C, // The file contains a versioned printer driver. +}; + +enum VFT2_FONT { + UNKNOWN = 0x00000000, // The font type is unknown by the system. + RASTER = 0x00000001, // The file contains a raster font. + VECTOR = 0x00000002, // The file contains a vector font. + TRUETYPE = 0x00000003, // The file contains a TrueType font. +}; + +/* + * Virtual Keys, Standard Set + */ +enum VK { + LBUTTON = 0x01, + RBUTTON = 0x02, + CANCEL = 0x03, + MBUTTON = 0x04, /* NOT contiguous with L & RBUTTON */ + XBUTTON1 = 0x05, /* NOT contiguous with L & RBUTTON */ + XBUTTON2 = 0x06, /* NOT contiguous with L & RBUTTON */ + +/* + * 0x07 : reserved + */ + + BACK = 0x08, + TAB = 0x09, + +/* + * 0x0A - 0x0B : reserved + */ + + CLEAR = 0x0C, + RETURN = 0x0D, + +/* + * 0x0E - 0x0F : unassigned + */ + + SHIFT = 0x10, + CONTROL = 0x11, + MENU = 0x12, + PAUSE = 0x13, + CAPITAL = 0x14, + + KANA = 0x15, + HANGEUL = 0x15, /* old name - should be here for compatibility */ + HANGUL = 0x15, + IME_ON = 0x16, + JUNJA = 0x17, + FINAL = 0x18, + HANJA = 0x19, + KANJI = 0x19, + IME_OFF = 0x1A, + + ESCAPE = 0x1B, + + CONVERT = 0x1C, + NONCONVERT = 0x1D, + ACCEPT = 0x1E, + MODECHANGE = 0x1F, + + SPACE = 0x20, + PRIOR = 0x21, + NEXT = 0x22, + END = 0x23, + HOME = 0x24, + LEFT = 0x25, + UP = 0x26, + RIGHT = 0x27, + DOWN = 0x28, + SELECT = 0x29, + PRINT = 0x2A, + EXECUTE = 0x2B, + SNAPSHOT = 0x2C, + INSERT = 0x2D, + DELETE = 0x2E, + HELP = 0x2F, + +/* + * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) + * 0x3A - 0x40 : unassigned + * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) + */ + + 0 = 0x30, + 1 = 0x31, + 2 = 0x32, + 3 = 0x33, + 4 = 0x34, + 5 = 0x35, + 6 = 0x36, + 7 = 0x37, + 8 = 0x38, + 9 = 0x39, + A = 0x41, + B = 0x42, + C = 0x43, + D = 0x44, + E = 0x45, + F = 0x46, + G = 0x47, + H = 0x48, + I = 0x49, + J = 0x4A, + K = 0x4B, + L = 0x4C, + M = 0x4D, + N = 0x4E, + O = 0x4F, + P = 0x50, + Q = 0x51, + R = 0x52, + S = 0x53, + T = 0x54, + U = 0x55, + V = 0x56, + W = 0x57, + X = 0x58, + Y = 0x59, + Z = 0x5A, + LWIN = 0x5B, + RWIN = 0x5C, + APPS = 0x5D, + +/* + * 0x5E : reserved + */ + + SLEEP = 0x5F, + + NUMPAD0 = 0x60, + NUMPAD1 = 0x61, + NUMPAD2 = 0x62, + NUMPAD3 = 0x63, + NUMPAD4 = 0x64, + NUMPAD5 = 0x65, + NUMPAD6 = 0x66, + NUMPAD7 = 0x67, + NUMPAD8 = 0x68, + NUMPAD9 = 0x69, + MULTIPLY = 0x6A, + ADD = 0x6B, + SEPARATOR = 0x6C, + SUBTRACT = 0x6D, + DECIMAL = 0x6E, + DIVIDE = 0x6F, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7A, + F12 = 0x7B, + F13 = 0x7C, + F14 = 0x7D, + F15 = 0x7E, + F16 = 0x7F, + F17 = 0x80, + F18 = 0x81, + F19 = 0x82, + F20 = 0x83, + F21 = 0x84, + F22 = 0x85, + F23 = 0x86, + F24 = 0x87, + +/* + * 0x88 - 0x8F : UI navigation + */ + + NAVIGATION_VIEW = 0x88, // reserved + NAVIGATION_MENU = 0x89, // reserved + NAVIGATION_UP = 0x8A, // reserved + NAVIGATION_DOWN = 0x8B, // reserved + NAVIGATION_LEFT = 0x8C, // reserved + NAVIGATION_RIGHT = 0x8D, // reserved + NAVIGATION_ACCEPT = 0x8E, // reserved + NAVIGATION_CANCEL = 0x8F, // reserved + + NUMLOCK = 0x90, + SCROLL = 0x91, + +/* + * NEC PC-9800 kbd definitions + */ + OEM_NEC_EQUAL = 0x92, // '=' key on numpad + +/* + * Fujitsu/OASYS kbd definitions + */ + OEM_FJ_JISHO = 0x92, // 'Dictionary' key + OEM_FJ_MASSHOU = 0x93, // 'Unregister word' key + OEM_FJ_TOUROKU = 0x94, // 'Register word' key + OEM_FJ_LOYA = 0x95, // 'Left OYAYUBI' key + OEM_FJ_ROYA = 0x96, // 'Right OYAYUBI' key + +/* + * 0x97 - 0x9F : unassigned + */ + +/* + * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. + * Used only as parameters to GetAsyncKeyState() and GetKeyState(). + * No other API or message will distinguish left and right keys in this way. + */ + LSHIFT = 0xA0, + RSHIFT = 0xA1, + LCONTROL = 0xA2, + RCONTROL = 0xA3, + LMENU = 0xA4, + RMENU = 0xA5, + + BROWSER_BACK = 0xA6, + BROWSER_FORWARD = 0xA7, + BROWSER_REFRESH = 0xA8, + BROWSER_STOP = 0xA9, + BROWSER_SEARCH = 0xAA, + BROWSER_FAVORITES = 0xAB, + BROWSER_HOME = 0xAC, + + VOLUME_MUTE = 0xAD, + VOLUME_DOWN = 0xAE, + VOLUME_UP = 0xAF, + MEDIA_NEXT_TRACK = 0xB0, + MEDIA_PREV_TRACK = 0xB1, + MEDIA_STOP = 0xB2, + MEDIA_PLAY_PAUSE = 0xB3, + LAUNCH_MAIL = 0xB4, + LAUNCH_MEDIA_SELECT = 0xB5, + LAUNCH_APP1 = 0xB6, + LAUNCH_APP2 = 0xB7, + +/* + * 0xB8 - 0xB9 : reserved + */ + + OEM_1 = 0xBA, // ';:' for US + OEM_PLUS = 0xBB, // '+' any country + OEM_COMMA = 0xBC, // ',' any country + OEM_MINUS = 0xBD, // '-' any country + OEM_PERIOD = 0xBE, // '.' any country + OEM_2 = 0xBF, // '/?' for US + OEM_3 = 0xC0, // '`~' for US + +/* + * 0xC1 - 0xC2 : reserved + */ + + /* + * 0xC3 - 0xDA : Gamepad input + */ + + GAMEPAD_A = 0xC3, // reserved + GAMEPAD_B = 0xC4, // reserved + GAMEPAD_X = 0xC5, // reserved + GAMEPAD_Y = 0xC6, // reserved + GAMEPAD_RIGHT_SHOULDER = 0xC7, // reserved + GAMEPAD_LEFT_SHOULDER = 0xC8, // reserved + GAMEPAD_LEFT_TRIGGER = 0xC9, // reserved + GAMEPAD_RIGHT_TRIGGER = 0xCA, // reserved + GAMEPAD_DPAD_UP = 0xCB, // reserved + GAMEPAD_DPAD_DOWN = 0xCC, // reserved + GAMEPAD_DPAD_LEFT = 0xCD, // reserved + GAMEPAD_DPAD_RIGHT = 0xCE, // reserved + GAMEPAD_MENU = 0xCF, // reserved + GAMEPAD_VIEW = 0xD0, // reserved + GAMEPAD_LEFT_THUMBSTICK_BUTTON = 0xD1, // reserved + GAMEPAD_RIGHT_THUMBSTICK_BUTTON = 0xD2, // reserved + GAMEPAD_LEFT_THUMBSTICK_UP = 0xD3, // reserved + GAMEPAD_LEFT_THUMBSTICK_DOWN = 0xD4, // reserved + GAMEPAD_LEFT_THUMBSTICK_RIGHT = 0xD5, // reserved + GAMEPAD_LEFT_THUMBSTICK_LEFT = 0xD6, // reserved + GAMEPAD_RIGHT_THUMBSTICK_UP = 0xD7, // reserved + GAMEPAD_RIGHT_THUMBSTICK_DOWN = 0xD8, // reserved + GAMEPAD_RIGHT_THUMBSTICK_RIGHT = 0xD9, // reserved + GAMEPAD_RIGHT_THUMBSTICK_LEFT = 0xDA, // reserved + + OEM_4 = 0xDB, // '[{' for US + OEM_5 = 0xDC, // '|' for US + OEM_6 = 0xDD, // ']}' for US + OEM_7 = 0xDE, // ''"' for US + OEM_8 = 0xDF, + +/* + * 0xE0 : reserved + */ + +/* + * Various extended or enhanced keyboards + */ + OEM_AX = 0xE1, // 'AX' key on Japanese AX kbd + OEM_102 = 0xE2, // "<>" or "|" on RT 102-key kbd. + ICO_HELP = 0xE3, // Help key on ICO + ICO_00 = 0xE4, // 00 key on ICO + + PROCESSKEY = 0xE5, + + ICO_CLEAR = 0xE6, + + PACKET = 0xE7, + +/* + * 0xE8 : unassigned + */ + +/* + * Nokia/Ericsson definitions + */ + OEM_RESET = 0xE9, + OEM_JUMP = 0xEA, + OEM_PA1 = 0xEB, + OEM_PA2 = 0xEC, + OEM_PA3 = 0xED, + OEM_WSCTRL = 0xEE, + OEM_CUSEL = 0xEF, + OEM_ATTN = 0xF0, + OEM_FINISH = 0xF1, + OEM_COPY = 0xF2, + OEM_AUTO = 0xF3, + OEM_ENLW = 0xF4, + OEM_BACKTAB = 0xF5, + + ATTN = 0xF6, + CRSEL = 0xF7, + EXSEL = 0xF8, + EREOF = 0xF9, + PLAY = 0xFA, + ZOOM = 0xFB, + NONAME = 0xFC, + PA1 = 0xFD, + OEM_CLEAR = 0xFE, + +/* + * 0xFF : reserved + */ +}; + +flag ACCEL_F { + VIRTKEY = 0x01, // Assumed to be == TRUE + LASTKEY = 0x80, // Indicates last key in the table + NOINVERT = 0x02, + SHIFT = 0x04, + CONTROL = 0x08, + ALT = 0x10, +}; + +// +// Code Integrity in loadconfig (CI) +// + +typedef struct _IMAGE_LOAD_CONFIG_CODE_INTEGRITY { + USHORT Flags; // Flags to indicate if CI information is available, etc. + USHORT Catalog; // 0xFFFF means not available + ULONG CatalogOffset; + ULONG Reserved; // Additional bitmask to be defined later +} IMAGE_LOAD_CONFIG_CODE_INTEGRITY, *PIMAGE_LOAD_CONFIG_CODE_INTEGRITY; + +// +// Dynamic value relocation table in loadconfig +// + +typedef struct _IMAGE_DYNAMIC_RELOCATION_TABLE { + ULONG Version; + ULONG Size; +// IMAGE_DYNAMIC_RELOCATION DynamicRelocations[0]; +} IMAGE_DYNAMIC_RELOCATION_TABLE, *PIMAGE_DYNAMIC_RELOCATION_TABLE; + +// +// Dynamic value relocation entries following IMAGE_DYNAMIC_RELOCATION_TABLE +// + +typedef struct _IMAGE_DYNAMIC_RELOCATION32 { + ULONG Symbol; + ULONG BaseRelocSize; +// IMAGE_BASE_RELOCATION BaseRelocations[0]; +} IMAGE_DYNAMIC_RELOCATION32, *PIMAGE_DYNAMIC_RELOCATION32; + +typedef struct _IMAGE_DYNAMIC_RELOCATION64 { + ULONGLONG Symbol; + ULONG BaseRelocSize; +// IMAGE_BASE_RELOCATION BaseRelocations[0]; +} IMAGE_DYNAMIC_RELOCATION64, *PIMAGE_DYNAMIC_RELOCATION64; + +typedef struct _IMAGE_DYNAMIC_RELOCATION32_V2 { + ULONG HeaderSize; + ULONG FixupInfoSize; + ULONG Symbol; + ULONG SymbolGroup; + ULONG Flags; + // ... variable length header fields + // UCHAR FixupInfo[FixupInfoSize]; +} IMAGE_DYNAMIC_RELOCATION32_V2, *PIMAGE_DYNAMIC_RELOCATION32_V2; + +typedef struct _IMAGE_DYNAMIC_RELOCATION64_V2 { + ULONG HeaderSize; + ULONG FixupInfoSize; + ULONGLONG Symbol; + ULONG SymbolGroup; + ULONG Flags; + // ... variable length header fields + // UCHAR FixupInfo[FixupInfoSize] +} IMAGE_DYNAMIC_RELOCATION64_V2, *PIMAGE_DYNAMIC_RELOCATION64_V2; + +// +// Defined symbolic dynamic relocation entries. +// + +#define IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE 0x00000001 +#define IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE 0x00000002 +#define IMAGE_DYNAMIC_RELOCATION_GUARD_IMPORT_CONTROL_TRANSFER 0x00000003 +#define IMAGE_DYNAMIC_RELOCATION_GUARD_INDIR_CONTROL_TRANSFER 0x00000004 +#define IMAGE_DYNAMIC_RELOCATION_GUARD_SWITCHTABLE_BRANCH 0x00000005 +#define IMAGE_DYNAMIC_RELOCATION_ARM64X 0x00000006 +#define IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE 0x00000007 +#define IMAGE_DYNAMIC_RELOCATION_ARM64_KERNEL_IMPORT_CALL_TRANSFER 0x00000008 +#define IMAGE_DYNAMIC_RELOCATION_MM_SHARED_USER_DATA_VA 0x7FFE0000 +#define IMAGE_DYNAMIC_RELOCATION_KI_USER_SHARED_DATA64 0xFFFFF78000000000 + +typedef struct _IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER { + UCHAR PrologueByteCount; + // UCHAR PrologueBytes[PrologueByteCount]; +} IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER, *PIMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER; + +typedef struct _IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER { + ULONG EpilogueCount; + UCHAR EpilogueByteCount; + UCHAR BranchDescriptorElementSize; + USHORT BranchDescriptorCount; + // UCHAR BranchDescriptors[...]; + // UCHAR BranchDescriptorBitMap[...]; +} IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER, *PIMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER; + +typedef struct _IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION { + ULONG PageRelativeOffset : 12; + ULONG IndirectCall : 1; + ULONG IATIndex : 19; +} IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION, *PIMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION; + +// +// On ARM64, an optimized imported function uses the following data structure +// insted of a _IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION. +// + +typedef struct _IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION { + ULONG PageRelativeOffset : 10; // Offset to the call instruction shifted right by 2 (4-byte aligned instruction) + ULONG IndirectCall : 1; // 0 if target instruction is a BR, 1 if BLR. + ULONG RegisterIndex : 5; // Register index used for the indirect call/jump. + ULONG ImportType : 1; // 0 if this refers to a static import, 1 for delayload import + ULONG IATIndex : 15; // IAT index of the corresponding import. + // 0x7FFF is a special value indicating no index. +} IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION, *PIMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION; + +typedef struct _IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION { + USHORT PageRelativeOffset : 12; + USHORT IndirectCall : 1; + USHORT RexWPrefix : 1; + USHORT CfgCheck : 1; + USHORT Reserved : 1; +} IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION, *PIMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION; + +typedef struct _IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION { + USHORT PageRelativeOffset : 12; + USHORT RegisterNumber : 4; +} IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION, *PIMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION; + +typedef struct _IMAGE_FUNCTION_OVERRIDE_HEADER { + ULONG FuncOverrideSize; + // IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION FuncOverrideInfo[ANYSIZE_ARRAY]; // FuncOverrideSize bytes in size + // IMAGE_BDD_INFO BDDInfo; // BDD region, size in bytes: DVRTEntrySize - sizeof(IMAGE_FUNCTION_OVERRIDE_HEADER) - FuncOverrideSize +} IMAGE_FUNCTION_OVERRIDE_HEADER, *PIMAGE_FUNCTION_OVERRIDE_HEADER; + +typedef struct _IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION { + ULONG OriginalRva; // RVA of original function + ULONG BDDOffset; // Offset into the BDD region + ULONG RvaSize; // Size in bytes taken by RVAs. Must be multiple of sizeof(ULONG). + ULONG BaseRelocSize; // Size in bytes taken by BaseRelocs + +// ULONG RVAs[RvaSize / sizeof(ULONG)]; // Array containing overriding func RVAs. + +// IMAGE_BASE_RELOCATION BaseRelocs[ANYSIZE_ARRAY]; // Base relocations (RVA + Size + TO) + // Padded with extra TOs for 4B alignment + // BaseRelocSize size in bytes +} IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION, *PIMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION; + +typedef struct _IMAGE_BDD_INFO { + ULONG Version; // decides the semantics of serialized BDD + ULONG BDDSize; +// IMAGE_BDD_DYNAMIC_RELOCATION BDDNodes[ANYSIZE_ARRAY]; // BDDSize size in bytes. +} IMAGE_BDD_INFO, *PIMAGE_BDD_INFO; + +typedef struct _IMAGE_BDD_DYNAMIC_RELOCATION { + USHORT Left; // Index of FALSE edge in BDD array + USHORT Right; // Index of TRUE edge in BDD array + ULONG Value; // Either FeatureNumber or Index into RVAs array +} IMAGE_BDD_DYNAMIC_RELOCATION, *PIMAGE_BDD_DYNAMIC_RELOCATION; + +// Function override relocation types in DVRT records. + +#define IMAGE_FUNCTION_OVERRIDE_INVALID 0 +#define IMAGE_FUNCTION_OVERRIDE_X64_REL32 1 // 32-bit relative address from byte following reloc +#define IMAGE_FUNCTION_OVERRIDE_ARM64_BRANCH26 2 // 26 bit offset << 2 & sign ext. for B & BL +#define IMAGE_FUNCTION_OVERRIDE_ARM64_THUNK 3 + +// +// Load Configuration Directory Entry +// + +flag IMAGE_GUARD : ULONG { + CF_INSTRUMENTED = 0x00000100, // Module performs control flow integrity checks using system-supplied support + CFW_INSTRUMENTED = 0x00000200, // Module performs control flow and write integrity checks + CF_FUNCTION_TABLE_PRESENT = 0x00000400, // Module contains valid control flow target metadata + SECURITY_COOKIE_UNUSED = 0x00000800, // Module does not make use of the /GS security cookie + PROTECT_DELAYLOAD_IAT = 0x00001000, // Module supports read only delay load IAT + DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000, // Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected + CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000, // Module contains suppressed export information. This also infers that the address taken + // taken IAT table is also present in the load config. + CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000, // Module enables suppression of exports + CF_LONGJUMP_TABLE_PRESENT = 0x00010000, // Module contains longjmp target information + RF_INSTRUMENTED = 0x00020000, // Module contains return flow instrumentation and metadata + RF_ENABLE = 0x00040000, // Module requests that the OS enable return flow protection + RF_STRICT = 0x00080000, // Module requests that the OS enable return flow protection in strict mode + RETPOLINE_PRESENT = 0x00100000, // Module was built with retpoline support +// DO_NOT_USE = 0x00200000, // Was EHCont flag on VB (20H1) + EH_CONTINUATION_TABLE_PRESENT = 0x00400000, // Module contains EH continuation target information + XFG_ENABLED = 0x00800000, // Module was built with xfg + CASTGUARD_PRESENT = 0x01000000, // Module has CastGuard instrumentation present + MEMCPY_PRESENT = 0x02000000, // Module has Guarded Memcpy instrumentation present +}; + +#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK 0xF0000000 // Stride of Guard CF function table encoded in these bits (additional count of bytes per element) +#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT 28 // Shift to right-justify Guard CF function table stride + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32 { + ULONG Size; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONG DeCommitFreeBlockThreshold; + ULONG DeCommitTotalFreeThreshold; + ULONG LockPrefixTable; // VA + ULONG MaximumAllocationSize; + ULONG VirtualMemoryThreshold; + ULONG ProcessHeapFlags; + ULONG ProcessAffinityMask; + USHORT CSDVersion; + USHORT DependentLoadFlags; + ULONG EditList; // VA + ULONG SecurityCookie; // VA + ULONG SEHandlerTable; // VA + ULONG SEHandlerCount; + ULONG GuardCFCheckFunctionPointer; // VA + ULONG GuardCFDispatchFunctionPointer; // VA + ULONG GuardCFFunctionTable; // VA + ULONG GuardCFFunctionCount; + IMAGE_GUARD GuardFlags; + IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; + ULONG GuardAddressTakenIatEntryTable; // VA + ULONG GuardAddressTakenIatEntryCount; + ULONG GuardLongJumpTargetTable; // VA + ULONG GuardLongJumpTargetCount; + ULONG DynamicValueRelocTable; // VA + ULONG CHPEMetadataPointer; + ULONG GuardRFFailureRoutine; // VA + ULONG GuardRFFailureRoutineFunctionPointer; // VA + ULONG DynamicValueRelocTableOffset; + USHORT DynamicValueRelocTableSection; + USHORT Reserved2; + ULONG GuardRFVerifyStackPointerFunctionPointer; // VA + ULONG HotPatchTableOffset; + ULONG Reserved3; + ULONG EnclaveConfigurationPointer; // VA + ULONG VolatileMetadataPointer; // VA + ULONG GuardEHContinuationTable; // VA + ULONG GuardEHContinuationCount; + ULONG GuardXFGCheckFunctionPointer; // VA + ULONG GuardXFGDispatchFunctionPointer; // VA + ULONG GuardXFGTableDispatchFunctionPointer; // VA + ULONG CastGuardOsDeterminedFailureMode; // VA + ULONG GuardMemcpyFunctionPointer; // VA + ULONG UmaFunctionPointers; // VA +} IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64 { + ULONG Size; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONGLONG DeCommitFreeBlockThreshold; + ULONGLONG DeCommitTotalFreeThreshold; + ULONGLONG LockPrefixTable; // VA + ULONGLONG MaximumAllocationSize; + ULONGLONG VirtualMemoryThreshold; + ULONGLONG ProcessAffinityMask; + ULONG ProcessHeapFlags; + USHORT CSDVersion; + USHORT DependentLoadFlags; + ULONGLONG EditList; // VA + ULONGLONG SecurityCookie; // VA + ULONGLONG SEHandlerTable; // VA + ULONGLONG SEHandlerCount; + ULONGLONG GuardCFCheckFunctionPointer; // VA + ULONGLONG GuardCFDispatchFunctionPointer; // VA + ULONGLONG GuardCFFunctionTable; // VA + ULONGLONG GuardCFFunctionCount; + IMAGE_GUARD GuardFlags; + IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; + ULONGLONG GuardAddressTakenIatEntryTable; // VA + ULONGLONG GuardAddressTakenIatEntryCount; + ULONGLONG GuardLongJumpTargetTable; // VA + ULONGLONG GuardLongJumpTargetCount; + ULONGLONG DynamicValueRelocTable; // VA + ULONGLONG CHPEMetadataPointer; // VA + ULONGLONG GuardRFFailureRoutine; // VA + ULONGLONG GuardRFFailureRoutineFunctionPointer; // VA + ULONG DynamicValueRelocTableOffset; + USHORT DynamicValueRelocTableSection; + USHORT Reserved2; + ULONGLONG GuardRFVerifyStackPointerFunctionPointer; // VA + ULONG HotPatchTableOffset; + ULONG Reserved3; + ULONGLONG EnclaveConfigurationPointer; // VA + ULONGLONG VolatileMetadataPointer; // VA + ULONGLONG GuardEHContinuationTable; // VA + ULONGLONG GuardEHContinuationCount; + ULONGLONG GuardXFGCheckFunctionPointer; // VA + ULONGLONG GuardXFGDispatchFunctionPointer; // VA + ULONGLONG GuardXFGTableDispatchFunctionPointer; // VA + ULONGLONG CastGuardOsDeterminedFailureMode; // VA + ULONGLONG GuardMemcpyFunctionPointer; // VA + ULONGLONG UmaFunctionPointers; // VA +} IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; + +typedef struct _IMAGE_CHPE_METADATA_X86 { + ULONG Version; + ULONG CHPECodeAddressRangeOffset; + ULONG CHPECodeAddressRangeCount; + ULONG WowA64ExceptionHandlerFunctionPointer; + ULONG WowA64DispatchCallFunctionPointer; + ULONG WowA64DispatchIndirectCallFunctionPointer; + ULONG WowA64DispatchIndirectCallCfgFunctionPointer; + ULONG WowA64DispatchRetFunctionPointer; + ULONG WowA64DispatchRetLeafFunctionPointer; + ULONG WowA64DispatchJumpFunctionPointer; + ULONG CompilerIATPointer; // Present if Version >= 2 + ULONG WowA64RdtscFunctionPointer; // Present if Version >= 3 +} IMAGE_CHPE_METADATA_X86, *PIMAGE_CHPE_METADATA_X86; + +typedef struct _IMAGE_CHPE_RANGE_ENTRY { + union { + ULONG StartOffset; + struct { + ULONG NativeCode : 1; + ULONG AddressBits : 31; + }; + }; + ULONG Length; +} IMAGE_CHPE_RANGE_ENTRY, *PIMAGE_CHPE_RANGE_ENTRY; + +typedef struct _IMAGE_ARM64EC_METADATA { + ULONG Version; + ULONG CodeMap; + ULONG CodeMapCount; + ULONG CodeRangesToEntryPoints; + ULONG RedirectionMetadata; + ULONG tbd__os_arm64x_dispatch_call_no_redirect; + ULONG tbd__os_arm64x_dispatch_ret; + ULONG tbd__os_arm64x_dispatch_call; + ULONG tbd__os_arm64x_dispatch_icall; + ULONG tbd__os_arm64x_dispatch_icall_cfg; + ULONG AlternateEntryPoint; + ULONG AuxiliaryIAT; + ULONG CodeRangesToEntryPointsCount; + ULONG RedirectionMetadataCount; + ULONG GetX64InformationFunctionPointer; + ULONG SetX64InformationFunctionPointer; + ULONG ExtraRFETable; + ULONG ExtraRFETableSize; + ULONG __os_arm64x_dispatch_fptr; + ULONG AuxiliaryIATCopy; +} IMAGE_ARM64EC_METADATA, *PIMAGE_ARM64EC_METADATA; + +typedef struct _IMAGE_ARM64EC_METADATA_V2 { + ULONG Version; + ULONG CodeMap; + ULONG CodeMapCount; + ULONG CodeRangesToEntryPoints; + ULONG RedirectionMetadata; + ULONG tbd__os_arm64x_dispatch_call_no_redirect; + ULONG tbd__os_arm64x_dispatch_ret; + ULONG tbd__os_arm64x_dispatch_call; + ULONG tbd__os_arm64x_dispatch_icall; + ULONG tbd__os_arm64x_dispatch_icall_cfg; + ULONG AlternateEntryPoint; + ULONG AuxiliaryIAT; + ULONG CodeRangesToEntryPointsCount; + ULONG RedirectionMetadataCount; + ULONG GetX64InformationFunctionPointer; + ULONG SetX64InformationFunctionPointer; + ULONG ExtraRFETable; + ULONG ExtraRFETableSize; + ULONG __os_arm64x_dispatch_fptr; + ULONG AuxiliaryIATCopy; + + // + // Below are V2-specific + // + ULONG AuxDelayloadIAT; + ULONG AuxDelayloadIATCopy; + ULONG ReservedBitField; // reserved and unused by the linker +} IMAGE_ARM64EC_METADATA_V2, *PIMAGE_ARM64EC_METADATA_V2; + +typedef struct _IMAGE_ARM64EC_REDIRECTION_ENTRY { + ULONG Source; + ULONG Destination; +} IMAGE_ARM64EC_REDIRECTION_ENTRY, *PIMAGE_ARM64EC_REDIRECTION_ENTRY; + +typedef struct _IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT { + ULONG StartRva; + ULONG EndRva; + ULONG EntryPoint; +} IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT, *PIMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT; + +#define IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL 0 +#define IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE 1 +#define IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA 2 + +#define IMAGE_DVRT_ARM64X_FIXUP_SIZE_2BYTES 1 +#define IMAGE_DVRT_ARM64X_FIXUP_SIZE_4BYTES 2 +#define IMAGE_DVRT_ARM64X_FIXUP_SIZE_8BYTES 3 + +typedef struct _IMAGE_DVRT_ARM64X_FIXUP_RECORD { + USHORT Offset : 12; + USHORT Type : 2; + USHORT Size : 2; +} IMAGE_DVRT_ARM64X_FIXUP_RECORD, *PIMAGE_DVRT_ARM64X_FIXUP_RECORD; + +typedef struct _IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD { + USHORT Offset : 12; + USHORT Type : 2; + USHORT Sign : 1; + USHORT Scale : 1; +} IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD, *PIMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD; + +typedef struct _IMAGE_HOT_PATCH_INFO { + ULONG Version; + ULONG Size; + ULONG SequenceNumber; + ULONG BaseImageList; + ULONG BaseImageCount; + ULONG BufferOffset; // Version 2 and later + ULONG ExtraPatchSize; // Version 3 and later + ULONG MinSequenceNumber; // Version 4 and later + ULONG Flags; // Version 4 and later +} IMAGE_HOT_PATCH_INFO, *PIMAGE_HOT_PATCH_INFO; + +typedef struct _IMAGE_HOT_PATCH_BASE { + ULONG SequenceNumber; + ULONG Flags; + ULONG OriginalTimeDateStamp; + ULONG OriginalCheckSum; + ULONG CodeIntegrityInfo; + ULONG CodeIntegritySize; + ULONG PatchTable; + ULONG BufferOffset; // V2 and later +} IMAGE_HOT_PATCH_BASE, *PIMAGE_HOT_PATCH_BASE; + +typedef struct _IMAGE_HOT_PATCH_MACHINE { + struct { + ULONG _x86 : 1; + ULONG Amd64 : 1; + ULONG Arm64 : 1; + ULONG Amd64EC : 1; + }; +} IMAGE_HOT_PATCH_MACHINE, *PIMAGE_HOT_PATCH_MACHINE; + +typedef struct _IMAGE_HOT_PATCH_HASHES { + UCHAR SHA256[32]; + UCHAR SHA1[20]; +} IMAGE_HOT_PATCH_HASHES, *PIMAGE_HOT_PATCH_HASHES; + +#define IMAGE_HOT_PATCH_BASE_OBLIGATORY 0x00000001 +#define IMAGE_HOT_PATCH_BASE_CAN_ROLL_BACK 0x00000002 + +#define IMAGE_HOT_PATCH_BASE_MACHINE_I386 0x00000004 +#define IMAGE_HOT_PATCH_BASE_MACHINE_ARM64 0x00000008 +#define IMAGE_HOT_PATCH_BASE_MACHINE_AMD64 0x00000010 + +#define IMAGE_HOT_PATCH_CHUNK_INVERSE 0x80000000 +#define IMAGE_HOT_PATCH_CHUNK_OBLIGATORY 0x40000000 +#define IMAGE_HOT_PATCH_CHUNK_RESERVED 0x3FF03000 +#define IMAGE_HOT_PATCH_CHUNK_TYPE 0x000FC000 +#define IMAGE_HOT_PATCH_CHUNK_SOURCE_RVA 0x00008000 +#define IMAGE_HOT_PATCH_CHUNK_TARGET_RVA 0x00004000 +#define IMAGE_HOT_PATCH_CHUNK_SIZE 0x00000FFF + +enum IMAGE_HOT_PATCH { + NONE = 0x00000000, + FUNCTION = 0x0001C000, + ABSOLUTE = 0x0002C000, + REL32 = 0x0003C000, + CALL_TARGET = 0x00044000, + INDIRECT = 0x0005C000, + NO_CALL_TARGET = 0x00064000, + DYNAMIC_VALUE = 0x00078000, +}; + +// +// GFIDS table entry flags. +// + +#define IMAGE_GUARD_FLAG_FID_SUPPRESSED 0x01 // The containing GFID entry is suppressed +#define IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED 0x02 // The containing GFID entry is export suppressed +#define IMAGE_GUARD_FLAG_FID_LANGEXCPTHANDLER 0x04 +#define IMAGE_GUARD_FLAG_FID_XFG 0x08 + +// +// WIN CE Exception table format +// + +// +// Function table entry format. Function table is pointed to by the +// IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry. +// + +typedef struct _IMAGE_CE_RUNTIME_FUNCTION_ENTRY { + ULONG FuncStart; + ULONG PrologLen : 8; + ULONG FuncLen : 22; + ULONG ThirtyTwoBit : 1; + ULONG ExceptionFlag : 1; +} IMAGE_CE_RUNTIME_FUNCTION_ENTRY, *PIMAGE_CE_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + union { + ULONG UnwindData; + struct { + ULONG Flag : 2; + ULONG FunctionLength : 11; + ULONG Ret : 2; + ULONG H : 1; + ULONG Reg : 3; + ULONG R : 1; + ULONG L : 1; + ULONG C : 1; + ULONG StackAdjust : 10; + }; + }; +} IMAGE_ARM_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY; + +enum ARM64_FNPDATA_FLAGS { + PdataRefToFullXdata = 0, + PdataPackedUnwindFunction = 1, + PdataPackedUnwindFragment = 2, +}; + +enum ARM64_FNPDATA_CR { + PdataCrUnchained = 0, + PdataCrUnchainedSavedLr = 1, + PdataCrChainedWithPac = 2, + PdataCrChained = 3, +}; + +typedef struct _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + union { + ULONG UnwindData; + struct { + ULONG Flag : 2; + ULONG FunctionLength : 11; + ULONG RegF : 3; + ULONG RegI : 4; + ULONG H : 1; + ULONG CR : 2; + ULONG FrameSize : 9; + }; + }; +} IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY; + +typedef union _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA { + ULONG HeaderData; + struct { + ULONG FunctionLength : 18; // in words (2 bytes) + ULONG Version : 2; + ULONG ExceptionDataPresent : 1; + ULONG EpilogInHeader : 1; + ULONG EpilogCount : 5; // number of epilogs or byte index of the first unwind code for the one only epilog + ULONG CodeWords : 5; // number of dwords with unwind codes + }; +} IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA, *PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA; + +typedef union IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED { + ULONG ExtendedHeaderData; + struct { + ULONG ExtendedEpilogCount : 16; + ULONG ExtendedCodeWords : 8; + }; +} IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED, *PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED; + +typedef union IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE { + ULONG EpilogScopeData; + struct { + ULONG EpilogStartOffset : 18; // offset in bytes, divided by 4, of the epilog relative to the start of the function. + ULONG Res0: 4; + ULONG EpilogStartIndex : 10; // byte index of the first unwind code that describes this epilog. + }; +} IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE, *PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE; + +typedef struct _IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY { + ULONGLONG BeginAddress; + ULONGLONG EndAddress; + ULONGLONG ExceptionHandler; + ULONGLONG HandlerData; + ULONGLONG PrologEndAddress; +} IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + ULONG ExceptionHandler; + ULONG HandlerData; + ULONG PrologEndAddress; +} IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + ULONG ExceptionHandler; + ULONG HandlerData; + ULONG PrologEndAddress; +} IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY, *PIMAGE_MIPS_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + union { + ULONG UnwindInfoAddress; + ULONG UnwindData; + }; +} IMAGE_RUNTIME_FUNCTION_ENTRY, *PIMAGE_RUNTIME_FUNCTION_ENTRY; + +// +// Sofware enclave information +// + +#define IMAGE_ENCLAVE_LONG_ID_LENGTH ENCLAVE_LONG_ID_LENGTH +#define IMAGE_ENCLAVE_SHORT_ID_LENGTH ENCLAVE_SHORT_ID_LENGTH + +typedef struct _IMAGE_ENCLAVE_CONFIG32 { + ULONG Size; + ULONG MinimumRequiredConfigSize; + ULONG PolicyFlags; + ULONG NumberOfImports; + ULONG ImportList; + ULONG ImportEntrySize; + UCHAR FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + UCHAR ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + ULONG ImageVersion; + ULONG SecurityVersion; + ULONG EnclaveSize; + ULONG NumberOfThreads; + ULONG EnclaveFlags; +} IMAGE_ENCLAVE_CONFIG32, *PIMAGE_ENCLAVE_CONFIG32; + +typedef struct _IMAGE_ENCLAVE_CONFIG64 { + ULONG Size; + ULONG MinimumRequiredConfigSize; + ULONG PolicyFlags; + ULONG NumberOfImports; + ULONG ImportList; + ULONG ImportEntrySize; + UCHAR FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + UCHAR ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + ULONG ImageVersion; + ULONG SecurityVersion; + ULONGLONG EnclaveSize; + ULONG NumberOfThreads; + ULONG EnclaveFlags; +} IMAGE_ENCLAVE_CONFIG64, *PIMAGE_ENCLAVE_CONFIG64; + +#define IMAGE_ENCLAVE_POLICY_DEBUGGABLE 0x00000001 +#define IMAGE_ENCLAVE_POLICY_STRICT_MEMORY 0x00000002 + +#define IMAGE_ENCLAVE_FLAG_PRIMARY_IMAGE 0x00000001 + +typedef struct _IMAGE_ENCLAVE_IMPORT { + ULONG MatchType; + ULONG MinimumSecurityVersion; + UCHAR UniqueOrAuthorID[IMAGE_ENCLAVE_LONG_ID_LENGTH]; + UCHAR FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + UCHAR ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; + ULONG ImportName; + ULONG Reserved; +} IMAGE_ENCLAVE_IMPORT, *PIMAGE_ENCLAVE_IMPORT; + +#define IMAGE_ENCLAVE_IMPORT_MATCH_NONE 0x00000000 +#define IMAGE_ENCLAVE_IMPORT_MATCH_UNIQUE_ID 0x00000001 +#define IMAGE_ENCLAVE_IMPORT_MATCH_AUTHOR_ID 0x00000002 +#define IMAGE_ENCLAVE_IMPORT_MATCH_FAMILY_ID 0x00000003 +#define IMAGE_ENCLAVE_IMPORT_MATCH_IMAGE_ID 0x00000004 + +// +// Security Format +// + +#define WIN_CERT_REVISION_1_0 0x0100 +#define WIN_CERT_REVISION_2_0 0x0200 + +enum WIN_CERT_TYPE : USHORT { + X509 = 0x0001, // bCertificate contains an X.509 Certificate + PKCS_SIGNED_DATA = 0x0002, // bCertificate contains a PKCS SignedData structure + RESERVED_1 = 0x0003, // Reserved + TS_STACK_SIGNED = 0x0004, // Terminal Server Protocol Stack Certificate signing +}; + +typedef struct _WIN_CERTIFICATE { + ULONG dwLength; + USHORT wRevision; + WIN_CERT_TYPE wCertificateType; + CHAR bCertificate[dwLength - 8]; +} WIN_CERTIFICATE, *PWIN_CERTIFICATE; + +// +// Debug Format +// + +enum IMAGE_DEBUG_TYPE : ULONG { + UNKNOWN = 0, // An unknown value that is ignored by all tools. + COFF = 1, // The COFF debug information (line numbers, symbol table, and string table). This type of debug information is also pointed to by fields in the file headers. + CODEVIEW = 2, // The Visual C++ debug information. + FPO = 3, // The frame pointer omission (FPO) information. This information tells the debugger how to interpret nonstandard stack frames, which use the EBP register for a purpose other than as a frame pointer. + MISC = 4, // The location of DBG file. + EXCEPTION = 5, // A copy of .pdata section. + FIXUP = 6, // Reserved. + OMAP_TO_SRC = 7, // The mapping from an RVA in image to an RVA in source image. + OMAP_FROM_SRC = 8, // The mapping from an RVA in source image to an RVA in image. + BORLAND = 9, // Reserved for Borland. + RESERVED10 = 10, // Reserved. + BBT = 10, + CLSID = 11, // Reserved. + VC_FEATURE = 12, + POGO = 13, + ILTCG = 14, + MPX = 15, + REPRO = 16, // PE determinism or reproducibility. + EMBEDDED_PORTABLE_PDB = 17, // Debugging information is embedded in the PE file at location specified by PointerToRawData. + SPGO = 18, + PDBCHECKSUM = 19, // Stores crypto hash for the content of the symbol file used to build the PE/COFF file. + EX_DLLCHARACTERISTICS = 20, // Extended DLL characteristics bits. + PERFMAP = 21, +}; + +flag IMAGE_DLLCHARACTERISTICS_EX { + CET_COMPAT = 0x01, + CET_COMPAT_STRICT_MODE = 0x02, + CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x04, + CET_DYNAMIC_APIS_ALLOW_IN_PROC = 0x08, + CET_RESERVED_1 = 0x10, + CET_RESERVED_2 = 0x20, + FORWARD_CFI_COMPAT = 0x40, + HOTPATCH_COMPATIBLE = 0x80, +}; + +typedef struct _IMAGE_DEBUG_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + IMAGE_DEBUG_TYPE Type; + ULONG SizeOfData; + ULONG AddressOfRawData; + ULONG PointerToRawData; +} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; + +typedef struct _IMAGE_COFF_SYMBOLS_HEADER { + ULONG NumberOfSymbols; + ULONG LvaToFirstSymbol; + ULONG NumberOfLinenumbers; + ULONG LvaToFirstLinenumber; + ULONG RvaToFirstByteOfCode; + ULONG RvaToLastByteOfCode; + ULONG RvaToFirstByteOfData; + ULONG RvaToLastByteOfData; +} IMAGE_COFF_SYMBOLS_HEADER, *PIMAGE_COFF_SYMBOLS_HEADER; + +#define CVINFO_PDB70_CVSIGNATURE 0x53445352 // "RSDS" +#define CVINFO_PDB20_CVSIGNATURE 0x3031424e // "NB10" +#define CVINFO_CV50_CVSIGNATURE 0x3131424e // "NB11" +#define CVINFO_CV41_CVSIGNATURE 0x3930424e // "NB09" +#define CVINFO_MTOC_CVSIGNATURE 0x434f544d // "MTOC" + +typedef struct _CV_HEADER { + ULONG Signature; + ULONG Offset; +} CV_HEADER, *PCV_HEADER; + +typedef struct _CV_INFO_PDB20 { + CV_HEADER CvHeader; + ULONG Signature; + ULONG Age; + CHAR PdbFileName[]; +} CV_INFO_PDB20, *PCV_INFO_PDB20; + +typedef struct _CV_INFO_PDB70 { + ULONG CvSignature; + CHAR Signature[16]; + ULONG Age; + CHAR PdbFileName[]; +} CV_INFO_PDB70, *PCV_INFO_PDB70; + +typedef struct _CV_INFO_MTOC { + ULONG CvSignature; + BYTE Signature[16]; + BYTE PdbFileName[1]; +} CV_INFO_MTOC, *PCV_INFO_MTOC; + +#define FRAME_FPO 0 +#define FRAME_TRAP 1 +#define FRAME_TSS 2 +#define FRAME_NONFPO 3 + +typedef struct _FPO_DATA { + ULONG ulOffStart; // offset 1st byte of function code + ULONG cbProcSize; // # bytes in function + ULONG cdwLocals; // # bytes in locals/4 + USHORT cdwParams; // # bytes in params/4 + USHORT cbProlog : 8; // # bytes in prolog + USHORT cbRegs : 3; // # regs saved + USHORT fHasSEH : 1; // TRUE if SEH in func + USHORT fUseBP : 1; // TRUE if EBP has been allocated + USHORT reserved : 1; // reserved for future use + USHORT cbFrame : 2; // frame type +} FPO_DATA, *PFPO_DATA; + +#define IMAGE_DEBUG_MISC_EXENAME 1 + +typedef struct _IMAGE_DEBUG_MISC { + ULONG DataType; // type of misc data, see defines + ULONG Length; // total length of record, rounded to four + // byte multiple. + BOOLEAN Unicode; // TRUE if data is unicode string + UCHAR Reserved[ 3 ]; +// UCHAR Data[ 1 ]; // Actual data +} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC; + +#define IMAGE_DEBUG_POGO_SIGNATURE_ZERO 0x00000000 +#define IMAGE_DEBUG_POGO_SIGNATURE_LTCG 0x4C544347 +#define IMAGE_DEBUG_POGO_SIGNATURE_PGU 0x50475500 + +typedef struct _VC_FEATURE { + ULONG PreVC11; + ULONG CCpp; + ULONG Gs; + ULONG Sdl; + ULONG GuardN; +} VC_FEATURE, *PVC_FEATURE; + +// +// Function table extracted from MIPS/ALPHA/IA64 images. Does not contain +// information needed only for runtime support. Just those fields for +// each entry needed by a debugger. +// + +typedef struct _IMAGE_FUNCTION_ENTRY { + ULONG StartingAddress; + ULONG EndingAddress; + ULONG EndOfPrologue; +} IMAGE_FUNCTION_ENTRY, *PIMAGE_FUNCTION_ENTRY; + +typedef struct _IMAGE_FUNCTION_ENTRY64 { + ULONGLONG StartingAddress; + ULONGLONG EndingAddress; + union { + ULONGLONG EndOfPrologue; + ULONGLONG UnwindInfoAddress; + }; +} IMAGE_FUNCTION_ENTRY64, *PIMAGE_FUNCTION_ENTRY64; + +// +// Debugging information can be stripped from an image file and placed +// in a separate .DBG file, whose file name part is the same as the +// image file name part (e.g. symbols for CMD.EXE could be stripped +// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED +// flag in the Characteristics field of the file header. The beginning of +// the .DBG file contains the following structure which captures certain +// information from the image file. This allows a debug to proceed even if +// the original image file is not accessable. This header is followed by +// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more +// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in +// the image file contain file offsets relative to the beginning of the +// .DBG file. +// +// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure +// is left in the image file, but not mapped. This allows a debugger to +// compute the name of the .DBG file, from the name of the image in the +// IMAGE_DEBUG_MISC structure. +// + +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { + USHORT Signature; + USHORT Flags; + USHORT Machine; + USHORT Characteristics; + ULONG TimeDateStamp; + ULONG CheckSum; + ULONG ImageBase; + ULONG SizeOfImage; + ULONG NumberOfSections; + ULONG ExportedNamesSize; + ULONG DebugDirectorySize; + ULONG SectionAlignment; + ULONG Reserved[2]; +} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; + +typedef struct _NON_PAGED_DEBUG_INFO { + USHORT Signature; + USHORT Flags; + ULONG Size; + USHORT Machine; + USHORT Characteristics; + ULONG TimeDateStamp; + ULONG CheckSum; + ULONG SizeOfImage; + ULONGLONG ImageBase; + //DebugDirectorySize + //IMAGE_DEBUG_DIRECTORY +} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO; + +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4449 // DI +#define NON_PAGED_DEBUG_SIGNATURE 0x4E49 // NI + +#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 +#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the + // old checksum didn't match. + +// +// The .arch section is made up of headers, each describing an amask position/value +// pointing to an array of IMAGE_ARCHITECTURE_ENTRY's. Each "array" (both the header +// and entry arrays) are terminiated by a quadword of 0xffffffffL. +// +// NOTE: There may be quadwords of 0 sprinkled around and must be skipped. +// + +typedef struct _ImageArchitectureHeader { + unsigned int AmaskValue: 1; // 1 -> code section depends on mask bit + // 0 -> new instruction depends on mask bit + int _:7; // MBZ + unsigned int AmaskShift: 8; // Amask bit in question for this fixup + int _:16; // MBZ + ULONG FirstEntryRVA; // RVA into .arch section to array of ARCHITECTURE_ENTRY's +} IMAGE_ARCHITECTURE_HEADER, *PIMAGE_ARCHITECTURE_HEADER; + +typedef struct _ImageArchitectureEntry { + ULONG FixupInstRVA; // RVA of instruction to fixup + ULONG NewInst; // fixup instruction (see alphaops.h) +} IMAGE_ARCHITECTURE_ENTRY, *PIMAGE_ARCHITECTURE_ENTRY; + +// The following structure defines the new import object. Note the values of the first two fields, +// which must be set as stated in order to differentiate old and new import members. +// Following this structure, the linker emits two null-terminated strings used to recreate the +// import at the time of use. The first string is the import's name, the second is the dll's name. + +#define IMPORT_OBJECT_HDR_SIG2 0xffff + +enum IMPORT_OBJECT_TYPE { + IMPORT_OBJECT_CODE = 0, + IMPORT_OBJECT_DATA = 1, + IMPORT_OBJECT_CONST = 2, +}; + +enum IMPORT_OBJECT_NAME_TYPE { + IMPORT_OBJECT_ORDINAL = 0, // Import by ordinal + IMPORT_OBJECT_NAME = 1, // Import name == public symbol name. + IMPORT_OBJECT_NAME_NO_PREFIX = 2, // Import name == public symbol name skipping leading ?, @, or optionally _. + IMPORT_OBJECT_NAME_UNDECORATE = 3, // Import name == public symbol name skipping leading ?, @, or optionally _ + // and truncating at first @. + IMPORT_OBJECT_NAME_EXPORTAS = 4, // Import name == a name is explicitly provided after the DLL name. +}; + +typedef struct IMPORT_OBJECT_HEADER { + USHORT Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + USHORT Sig2; // Must be IMPORT_OBJECT_HDR_SIG2. + USHORT Version; + USHORT Machine; + ULONG TimeDateStamp; // Time/date stamp + ULONG SizeOfData; // particularly useful for incremental links + + union { + USHORT Ordinal; // if grf & IMPORT_OBJECT_ORDINAL + USHORT Hint; + }; + + IMPORT_OBJECT_TYPE Type : 2; // IMPORT_TYPE + IMPORT_OBJECT_NAME_TYPE NameType : 3; // IMPORT_NAME_TYPE + USHORT Reserved : 11; // Reserved. Must be zero. +} IMPORT_OBJECT_HEADER, *PIMPORT_OBJECT_HEADER; + +// +// COM Format. +// + +// COM+ Header entry point flags. +flag COMIMAGE_FLAGS : ULONG { + ILONLY = 0x00000001, + 32BITREQUIRED = 0x00000002, + IL_LIBRARY = 0x00000004, + STRONGNAMESIGNED = 0x00000008, + NATIVE_ENTRYPOINT = 0x00000010, + TRACKDEBUGDATA = 0x00010000, + 32BITPREFERRED = 0x00020000 +}; + +// Version flags for image. +#define COR_VERSION_MAJOR_V2 2 +#define COR_VERSION_MAJOR COR_VERSION_MAJOR_V2 +#define COR_VERSION_MINOR 5 +#define COR_DELETED_NAME_LENGTH 8 +#define COR_VTABLEGAP_NAME_LENGTH 8 + +// Maximum size of a NativeType descriptor. +#define NATIVE_TYPE_MAX_CB 1 +#define COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE 0xFF + +// #defines for the MIH FLAGS +#define IMAGE_COR_MIH_METHODRVA 0x01 +#define IMAGE_COR_MIH_EHRVA 0x02 +#define IMAGE_COR_MIH_BASICBLOCK 0x08 + +// V-table constants +#define COR_VTABLE_32BIT 0x01 // V-table slots are 32-bits in size. +#define COR_VTABLE_64BIT 0x02 // V-table slots are 64-bits in size. +#define COR_VTABLE_FROM_UNMANAGED 0x04 // If set, transition from unmanaged. +#define COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN 0x08 // If set, transition from unmanaged with keeping the current appdomain. +#define COR_VTABLE_CALL_MOST_DERIVED 0x10 // Call most derived method described by + +// EATJ constants +#define IMAGE_COR_EATJ_THUNK_SIZE 32 // Size of a jump thunk reserved range. + +// Max name lengths +#define MAX_CLASS_NAME 1024 +#define MAX_PACKAGE_NAME 1024 + +// CLR 2.0 header structure. +typedef struct _IMAGE_COR20_HEADER { + // Header versioning + ULONG cb; + USHORT MajorRuntimeVersion; + USHORT MinorRuntimeVersion; + + // Symbol table and startup information + IMAGE_DATA_DIRECTORY MetaData; + ULONG Flags; + + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint. + union { + ULONG EntryPointToken; + ULONG EntryPointRVA; + }; + + // Binding information + IMAGE_DATA_DIRECTORY Resources; + IMAGE_DATA_DIRECTORY StrongNameSignature; + + // Regular fixup and binding information + IMAGE_DATA_DIRECTORY CodeManagerTable; + IMAGE_DATA_DIRECTORY VTableFixups; + IMAGE_DATA_DIRECTORY ExportAddressTableJumps; + + // Precompiled image info (internal use only - set to zero) + IMAGE_DATA_DIRECTORY ManagedNativeHeader; +} IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; + +typedef struct _IMAGE_COR20_METADATA { + ULONG Magic; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG Reserved; + ULONG Length; + CHAR Version[Length]; + USHORT Flags; + USHORT NumberOfStreams; +} IMAGE_COR20_METADATA, *PIMAGE_COR20_METADATA; + +typedef struct _IMAGE_COR20_STREAM_HEADER { + ULONG Offset; + ULONG Size; + CHAR Name[]; +} IMAGE_COR20_STREAM_HEADER, *PIMAGE_COR20_STREAM_HEADER; +""" # noqa: E501 + +c_pe = cstruct().load(c_pe_def) diff --git a/dissect/executable/pe/c_pe.pyi b/dissect/executable/pe/c_pe.pyi new file mode 100644 index 0000000..1efb7de --- /dev/null +++ b/dissect/executable/pe/c_pe.pyi @@ -0,0 +1,3112 @@ +# Generated by cstruct-stubgen +from typing import BinaryIO, Literal, overload + +import dissect.cstruct as __cs__ +from typing_extensions import TypeAlias + +class _c_pe(__cs__.cstruct): + IMAGE_DOS_SIGNATURE: Literal[23117] = ... + IMAGE_OS2_SIGNATURE: Literal[17742] = ... + IMAGE_OS2_SIGNATURE_LE: Literal[17740] = ... + IMAGE_VXD_SIGNATURE: Literal[17740] = ... + IMAGE_NT_SIGNATURE: Literal[17744] = ... + IMAGE_NUMBEROF_DIRECTORY_ENTRIES: Literal[16] = ... + IMAGE_NT_OPTIONAL_HDR32_MAGIC: Literal[267] = ... + IMAGE_NT_OPTIONAL_HDR64_MAGIC: Literal[523] = ... + IMAGE_ROM_OPTIONAL_HDR_MAGIC: Literal[263] = ... + IMAGE_SIZEOF_SHORT_NAME: Literal[8] = ... + IMAGE_ARCHIVE_START_SIZE: Literal[8] = ... + IMAGE_ARCHIVE_START: Literal['b"!'] = ... + IMAGE_ARCHIVE_END: Literal['b"`'] = ... + IMAGE_ARCHIVE_PAD: Literal['b"'] = ... + IMAGE_ARCHIVE_LINKER_MEMBER: Literal[b"/ "] = ... + IMAGE_ARCHIVE_LONGNAMES_MEMBER: Literal[b"// "] = ... + IMAGE_ORDINAL_FLAG64: Literal[9223372036854775808] = ... + IMAGE_ORDINAL_FLAG32: Literal[2147483648] = ... + IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE: Literal[1] = ... + IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE: Literal[2] = ... + IMAGE_DYNAMIC_RELOCATION_GUARD_IMPORT_CONTROL_TRANSFER: Literal[3] = ... + IMAGE_DYNAMIC_RELOCATION_GUARD_INDIR_CONTROL_TRANSFER: Literal[4] = ... + IMAGE_DYNAMIC_RELOCATION_GUARD_SWITCHTABLE_BRANCH: Literal[5] = ... + IMAGE_DYNAMIC_RELOCATION_ARM64X: Literal[6] = ... + IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE: Literal[7] = ... + IMAGE_DYNAMIC_RELOCATION_ARM64_KERNEL_IMPORT_CALL_TRANSFER: Literal[8] = ... + IMAGE_DYNAMIC_RELOCATION_MM_SHARED_USER_DATA_VA: Literal[2147352576] = ... + IMAGE_DYNAMIC_RELOCATION_KI_USER_SHARED_DATA64: Literal[18446734727860715520] = ... + IMAGE_FUNCTION_OVERRIDE_INVALID: Literal[0] = ... + IMAGE_FUNCTION_OVERRIDE_X64_REL32: Literal[1] = ... + IMAGE_FUNCTION_OVERRIDE_ARM64_BRANCH26: Literal[2] = ... + IMAGE_FUNCTION_OVERRIDE_ARM64_THUNK: Literal[3] = ... + IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK: Literal[4026531840] = ... + IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT: Literal[28] = ... + IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL: Literal[0] = ... + IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: Literal[1] = ... + IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA: Literal[2] = ... + IMAGE_DVRT_ARM64X_FIXUP_SIZE_2BYTES: Literal[1] = ... + IMAGE_DVRT_ARM64X_FIXUP_SIZE_4BYTES: Literal[2] = ... + IMAGE_DVRT_ARM64X_FIXUP_SIZE_8BYTES: Literal[3] = ... + IMAGE_HOT_PATCH_BASE_OBLIGATORY: Literal[1] = ... + IMAGE_HOT_PATCH_BASE_CAN_ROLL_BACK: Literal[2] = ... + IMAGE_HOT_PATCH_BASE_MACHINE_I386: Literal[4] = ... + IMAGE_HOT_PATCH_BASE_MACHINE_ARM64: Literal[8] = ... + IMAGE_HOT_PATCH_BASE_MACHINE_AMD64: Literal[16] = ... + IMAGE_HOT_PATCH_CHUNK_INVERSE: Literal[2147483648] = ... + IMAGE_HOT_PATCH_CHUNK_OBLIGATORY: Literal[1073741824] = ... + IMAGE_HOT_PATCH_CHUNK_RESERVED: Literal[1072705536] = ... + IMAGE_HOT_PATCH_CHUNK_TYPE: Literal[1032192] = ... + IMAGE_HOT_PATCH_CHUNK_SOURCE_RVA: Literal[32768] = ... + IMAGE_HOT_PATCH_CHUNK_TARGET_RVA: Literal[16384] = ... + IMAGE_HOT_PATCH_CHUNK_SIZE: Literal[4095] = ... + IMAGE_GUARD_FLAG_FID_SUPPRESSED: Literal[1] = ... + IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED: Literal[2] = ... + IMAGE_GUARD_FLAG_FID_LANGEXCPTHANDLER: Literal[4] = ... + IMAGE_GUARD_FLAG_FID_XFG: Literal[8] = ... + IMAGE_ENCLAVE_LONG_ID_LENGTH: Literal["ENCLAVE_LONG_ID_LENGTH"] = ... + IMAGE_ENCLAVE_SHORT_ID_LENGTH: Literal["ENCLAVE_SHORT_ID_LENGTH"] = ... + IMAGE_ENCLAVE_POLICY_DEBUGGABLE: Literal[1] = ... + IMAGE_ENCLAVE_POLICY_STRICT_MEMORY: Literal[2] = ... + IMAGE_ENCLAVE_FLAG_PRIMARY_IMAGE: Literal[1] = ... + IMAGE_ENCLAVE_IMPORT_MATCH_NONE: Literal[0] = ... + IMAGE_ENCLAVE_IMPORT_MATCH_UNIQUE_ID: Literal[1] = ... + IMAGE_ENCLAVE_IMPORT_MATCH_AUTHOR_ID: Literal[2] = ... + IMAGE_ENCLAVE_IMPORT_MATCH_FAMILY_ID: Literal[3] = ... + IMAGE_ENCLAVE_IMPORT_MATCH_IMAGE_ID: Literal[4] = ... + WIN_CERT_REVISION_1_0: Literal[256] = ... + WIN_CERT_REVISION_2_0: Literal[512] = ... + CVINFO_PDB70_CVSIGNATURE: Literal[1396986706] = ... + CVINFO_PDB20_CVSIGNATURE: Literal[808534606] = ... + CVINFO_CV50_CVSIGNATURE: Literal[825311822] = ... + CVINFO_CV41_CVSIGNATURE: Literal[959464014] = ... + CVINFO_MTOC_CVSIGNATURE: Literal[1129272397] = ... + FRAME_FPO: Literal[0] = ... + FRAME_TRAP: Literal[1] = ... + FRAME_TSS: Literal[2] = ... + FRAME_NONFPO: Literal[3] = ... + IMAGE_DEBUG_MISC_EXENAME: Literal[1] = ... + IMAGE_DEBUG_POGO_SIGNATURE_ZERO: Literal[0] = ... + IMAGE_DEBUG_POGO_SIGNATURE_LTCG: Literal[1280590663] = ... + IMAGE_DEBUG_POGO_SIGNATURE_PGU: Literal[1346852096] = ... + IMAGE_SEPARATE_DEBUG_SIGNATURE: Literal[17481] = ... + NON_PAGED_DEBUG_SIGNATURE: Literal[20041] = ... + IMAGE_SEPARATE_DEBUG_FLAGS_MASK: Literal[32768] = ... + IMAGE_SEPARATE_DEBUG_MISMATCH: Literal[32768] = ... + IMPORT_OBJECT_HDR_SIG2: Literal[65535] = ... + COR_VERSION_MAJOR_V2: Literal[2] = ... + COR_VERSION_MAJOR: Literal[2] = ... + COR_VERSION_MINOR: Literal[5] = ... + COR_DELETED_NAME_LENGTH: Literal[8] = ... + COR_VTABLEGAP_NAME_LENGTH: Literal[8] = ... + NATIVE_TYPE_MAX_CB: Literal[1] = ... + COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE: Literal[255] = ... + IMAGE_COR_MIH_METHODRVA: Literal[1] = ... + IMAGE_COR_MIH_EHRVA: Literal[2] = ... + IMAGE_COR_MIH_BASICBLOCK: Literal[8] = ... + COR_VTABLE_32BIT: Literal[1] = ... + COR_VTABLE_64BIT: Literal[2] = ... + COR_VTABLE_FROM_UNMANAGED: Literal[4] = ... + COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN: Literal[8] = ... + COR_VTABLE_CALL_MOST_DERIVED: Literal[16] = ... + IMAGE_COR_EATJ_THUNK_SIZE: Literal[32] = ... + MAX_CLASS_NAME: Literal[1024] = ... + MAX_PACKAGE_NAME: Literal[1024] = ... + BOOLEAN: TypeAlias = _c_pe.uint8 + class _IMAGE_DOS_HEADER(__cs__.Structure): + e_magic: _c_pe.uint16 + e_cblp: _c_pe.uint16 + e_cp: _c_pe.uint16 + e_crlc: _c_pe.uint16 + e_cparhdr: _c_pe.uint16 + e_minalloc: _c_pe.uint16 + e_maxalloc: _c_pe.uint16 + e_ss: _c_pe.uint16 + e_sp: _c_pe.uint16 + e_csum: _c_pe.uint16 + e_ip: _c_pe.uint16 + e_cs: _c_pe.uint16 + e_lfarlc: _c_pe.uint16 + e_ovno: _c_pe.uint16 + e_res: __cs__.Array[_c_pe.uint16] + e_oemid: _c_pe.uint16 + e_oeminfo: _c_pe.uint16 + e_res2: __cs__.Array[_c_pe.uint16] + e_lfanew: _c_pe.int32 + @overload + def __init__( + self, + e_magic: _c_pe.uint16 | None = ..., + e_cblp: _c_pe.uint16 | None = ..., + e_cp: _c_pe.uint16 | None = ..., + e_crlc: _c_pe.uint16 | None = ..., + e_cparhdr: _c_pe.uint16 | None = ..., + e_minalloc: _c_pe.uint16 | None = ..., + e_maxalloc: _c_pe.uint16 | None = ..., + e_ss: _c_pe.uint16 | None = ..., + e_sp: _c_pe.uint16 | None = ..., + e_csum: _c_pe.uint16 | None = ..., + e_ip: _c_pe.uint16 | None = ..., + e_cs: _c_pe.uint16 | None = ..., + e_lfarlc: _c_pe.uint16 | None = ..., + e_ovno: _c_pe.uint16 | None = ..., + e_res: __cs__.Array[_c_pe.uint16] | None = ..., + e_oemid: _c_pe.uint16 | None = ..., + e_oeminfo: _c_pe.uint16 | None = ..., + e_res2: __cs__.Array[_c_pe.uint16] | None = ..., + e_lfanew: _c_pe.int32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DOS_HEADER: TypeAlias = _IMAGE_DOS_HEADER + PIMAGE_DOS_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DOS_HEADER] + class _IMAGE_OS2_HEADER(__cs__.Structure): + ne_magic: _c_pe.uint16 + ne_ver: _c_pe.char + ne_rev: _c_pe.char + ne_enttab: _c_pe.uint16 + ne_cbenttab: _c_pe.uint16 + ne_crc: _c_pe.int32 + ne_flags: _c_pe.uint16 + ne_autodata: _c_pe.uint16 + ne_heap: _c_pe.uint16 + ne_stack: _c_pe.uint16 + ne_csip: _c_pe.int32 + ne_sssp: _c_pe.int32 + ne_cseg: _c_pe.uint16 + ne_cmod: _c_pe.uint16 + ne_cbnrestab: _c_pe.uint16 + ne_segtab: _c_pe.uint16 + ne_rsrctab: _c_pe.uint16 + ne_restab: _c_pe.uint16 + ne_modtab: _c_pe.uint16 + ne_imptab: _c_pe.uint16 + ne_nrestab: _c_pe.int32 + ne_cmovent: _c_pe.uint16 + ne_align: _c_pe.uint16 + ne_cres: _c_pe.uint16 + ne_exetyp: _c_pe.uint8 + ne_flagsothers: _c_pe.uint8 + ne_pretthunks: _c_pe.uint16 + ne_psegrefbytes: _c_pe.uint16 + ne_swaparea: _c_pe.uint16 + ne_expver: _c_pe.uint16 + @overload + def __init__( + self, + ne_magic: _c_pe.uint16 | None = ..., + ne_ver: _c_pe.char | None = ..., + ne_rev: _c_pe.char | None = ..., + ne_enttab: _c_pe.uint16 | None = ..., + ne_cbenttab: _c_pe.uint16 | None = ..., + ne_crc: _c_pe.int32 | None = ..., + ne_flags: _c_pe.uint16 | None = ..., + ne_autodata: _c_pe.uint16 | None = ..., + ne_heap: _c_pe.uint16 | None = ..., + ne_stack: _c_pe.uint16 | None = ..., + ne_csip: _c_pe.int32 | None = ..., + ne_sssp: _c_pe.int32 | None = ..., + ne_cseg: _c_pe.uint16 | None = ..., + ne_cmod: _c_pe.uint16 | None = ..., + ne_cbnrestab: _c_pe.uint16 | None = ..., + ne_segtab: _c_pe.uint16 | None = ..., + ne_rsrctab: _c_pe.uint16 | None = ..., + ne_restab: _c_pe.uint16 | None = ..., + ne_modtab: _c_pe.uint16 | None = ..., + ne_imptab: _c_pe.uint16 | None = ..., + ne_nrestab: _c_pe.int32 | None = ..., + ne_cmovent: _c_pe.uint16 | None = ..., + ne_align: _c_pe.uint16 | None = ..., + ne_cres: _c_pe.uint16 | None = ..., + ne_exetyp: _c_pe.uint8 | None = ..., + ne_flagsothers: _c_pe.uint8 | None = ..., + ne_pretthunks: _c_pe.uint16 | None = ..., + ne_psegrefbytes: _c_pe.uint16 | None = ..., + ne_swaparea: _c_pe.uint16 | None = ..., + ne_expver: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_OS2_HEADER: TypeAlias = _IMAGE_OS2_HEADER + PIMAGE_OS2_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_OS2_HEADER] + class _IMAGE_VXD_HEADER(__cs__.Structure): + e32_magic: _c_pe.uint16 + e32_border: _c_pe.uint8 + e32_worder: _c_pe.uint8 + e32_level: _c_pe.uint32 + e32_cpu: _c_pe.uint16 + e32_os: _c_pe.uint16 + e32_ver: _c_pe.uint32 + e32_mflags: _c_pe.uint32 + e32_mpages: _c_pe.uint32 + e32_startobj: _c_pe.uint32 + e32_eip: _c_pe.uint32 + e32_stackobj: _c_pe.uint32 + e32_esp: _c_pe.uint32 + e32_pagesize: _c_pe.uint32 + e32_lastpagesize: _c_pe.uint32 + e32_fixupsize: _c_pe.uint32 + e32_fixupsum: _c_pe.uint32 + e32_ldrsize: _c_pe.uint32 + e32_ldrsum: _c_pe.uint32 + e32_objtab: _c_pe.uint32 + e32_objcnt: _c_pe.uint32 + e32_objmap: _c_pe.uint32 + e32_itermap: _c_pe.uint32 + e32_rsrctab: _c_pe.uint32 + e32_rsrccnt: _c_pe.uint32 + e32_restab: _c_pe.uint32 + e32_enttab: _c_pe.uint32 + e32_dirtab: _c_pe.uint32 + e32_dircnt: _c_pe.uint32 + e32_fpagetab: _c_pe.uint32 + e32_frectab: _c_pe.uint32 + e32_impmod: _c_pe.uint32 + e32_impmodcnt: _c_pe.uint32 + e32_impproc: _c_pe.uint32 + e32_pagesum: _c_pe.uint32 + e32_datapage: _c_pe.uint32 + e32_preload: _c_pe.uint32 + e32_nrestab: _c_pe.uint32 + e32_cbnrestab: _c_pe.uint32 + e32_nressum: _c_pe.uint32 + e32_autodata: _c_pe.uint32 + e32_debuginfo: _c_pe.uint32 + e32_debuglen: _c_pe.uint32 + e32_instpreload: _c_pe.uint32 + e32_instdemand: _c_pe.uint32 + e32_heapsize: _c_pe.uint32 + e32_res3: __cs__.Array[_c_pe.uint8] + e32_winresoff: _c_pe.uint32 + e32_winreslen: _c_pe.uint32 + e32_devid: _c_pe.uint16 + e32_ddkver: _c_pe.uint16 + @overload + def __init__( + self, + e32_magic: _c_pe.uint16 | None = ..., + e32_border: _c_pe.uint8 | None = ..., + e32_worder: _c_pe.uint8 | None = ..., + e32_level: _c_pe.uint32 | None = ..., + e32_cpu: _c_pe.uint16 | None = ..., + e32_os: _c_pe.uint16 | None = ..., + e32_ver: _c_pe.uint32 | None = ..., + e32_mflags: _c_pe.uint32 | None = ..., + e32_mpages: _c_pe.uint32 | None = ..., + e32_startobj: _c_pe.uint32 | None = ..., + e32_eip: _c_pe.uint32 | None = ..., + e32_stackobj: _c_pe.uint32 | None = ..., + e32_esp: _c_pe.uint32 | None = ..., + e32_pagesize: _c_pe.uint32 | None = ..., + e32_lastpagesize: _c_pe.uint32 | None = ..., + e32_fixupsize: _c_pe.uint32 | None = ..., + e32_fixupsum: _c_pe.uint32 | None = ..., + e32_ldrsize: _c_pe.uint32 | None = ..., + e32_ldrsum: _c_pe.uint32 | None = ..., + e32_objtab: _c_pe.uint32 | None = ..., + e32_objcnt: _c_pe.uint32 | None = ..., + e32_objmap: _c_pe.uint32 | None = ..., + e32_itermap: _c_pe.uint32 | None = ..., + e32_rsrctab: _c_pe.uint32 | None = ..., + e32_rsrccnt: _c_pe.uint32 | None = ..., + e32_restab: _c_pe.uint32 | None = ..., + e32_enttab: _c_pe.uint32 | None = ..., + e32_dirtab: _c_pe.uint32 | None = ..., + e32_dircnt: _c_pe.uint32 | None = ..., + e32_fpagetab: _c_pe.uint32 | None = ..., + e32_frectab: _c_pe.uint32 | None = ..., + e32_impmod: _c_pe.uint32 | None = ..., + e32_impmodcnt: _c_pe.uint32 | None = ..., + e32_impproc: _c_pe.uint32 | None = ..., + e32_pagesum: _c_pe.uint32 | None = ..., + e32_datapage: _c_pe.uint32 | None = ..., + e32_preload: _c_pe.uint32 | None = ..., + e32_nrestab: _c_pe.uint32 | None = ..., + e32_cbnrestab: _c_pe.uint32 | None = ..., + e32_nressum: _c_pe.uint32 | None = ..., + e32_autodata: _c_pe.uint32 | None = ..., + e32_debuginfo: _c_pe.uint32 | None = ..., + e32_debuglen: _c_pe.uint32 | None = ..., + e32_instpreload: _c_pe.uint32 | None = ..., + e32_instdemand: _c_pe.uint32 | None = ..., + e32_heapsize: _c_pe.uint32 | None = ..., + e32_res3: __cs__.Array[_c_pe.uint8] | None = ..., + e32_winresoff: _c_pe.uint32 | None = ..., + e32_winreslen: _c_pe.uint32 | None = ..., + e32_devid: _c_pe.uint16 | None = ..., + e32_ddkver: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_VXD_HEADER: TypeAlias = _IMAGE_VXD_HEADER + PIMAGE_VXD_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_VXD_HEADER] + class IMAGE_FILE(__cs__.Flag): + RELOCS_STRIPPED = ... + EXECUTABLE_IMAGE = ... + LINE_NUMS_STRIPPED = ... + LOCAL_SYMS_STRIPPED = ... + AGGRESSIVE_WS_TRIM = ... + LARGE_ADDRESS_AWARE = ... + BYTES_REVERSED_LO = ... + "32BIT_MACHINE = ..." + DEBUG_STRIPPED = ... + REMOVABLE_RUN_FROM_SWAP = ... + NET_RUN_FROM_SWAP = ... + SYSTEM = ... + DLL = ... + UP_SYSTEM_ONLY = ... + BYTES_REVERSED_HI = ... + + class IMAGE_FILE_MACHINE(__cs__.Enum): + UNKNOWN = ... + TARGET_HOST = ... + I386 = ... + R3000 = ... + R4000 = ... + R10000 = ... + WCEMIPSV2 = ... + ALPHA = ... + SH3 = ... + SH3DSP = ... + SH3E = ... + SH4 = ... + SH5 = ... + ARM = ... + THUMB = ... + ARMNT = ... + AM33 = ... + POWERPC = ... + POWERPCFP = ... + IA64 = ... + MIPS16 = ... + ALPHA64 = ... + MIPSFPU = ... + MIPSFPU16 = ... + AXP64 = ... + TRICORE = ... + CEF = ... + EBC = ... + CHPE_X86 = ... + RISCV32 = ... + RISCV64 = ... + RISCV128 = ... + AMD64 = ... + M32R = ... + ARM64 = ... + CEE = ... + + class _IMAGE_FILE_HEADER(__cs__.Structure): + Machine: _c_pe.IMAGE_FILE_MACHINE + NumberOfSections: _c_pe.uint16 + TimeDateStamp: _c_pe.uint32 + PointerToSymbolTable: _c_pe.uint32 + NumberOfSymbols: _c_pe.uint32 + SizeOfOptionalHeader: _c_pe.uint16 + Characteristics: _c_pe.IMAGE_FILE + @overload + def __init__( + self, + Machine: _c_pe.IMAGE_FILE_MACHINE | None = ..., + NumberOfSections: _c_pe.uint16 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + PointerToSymbolTable: _c_pe.uint32 | None = ..., + NumberOfSymbols: _c_pe.uint32 | None = ..., + SizeOfOptionalHeader: _c_pe.uint16 | None = ..., + Characteristics: _c_pe.IMAGE_FILE | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_FILE_HEADER: TypeAlias = _IMAGE_FILE_HEADER + PIMAGE_FILE_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_FILE_HEADER] + class _IMAGE_DATA_DIRECTORY(__cs__.Structure): + VirtualAddress: _c_pe.uint32 + Size: _c_pe.uint32 + @overload + def __init__(self, VirtualAddress: _c_pe.uint32 | None = ..., Size: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DATA_DIRECTORY: TypeAlias = _IMAGE_DATA_DIRECTORY + PIMAGE_DATA_DIRECTORY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DATA_DIRECTORY] + class IMAGE_SUBSYSTEM(__cs__.Enum): + UNKNOWN = ... + NATIVE = ... + WINDOWS_GUI = ... + WINDOWS_CUI = ... + OS2_CUI = ... + POSIX_CUI = ... + NATIVE_WINDOWS = ... + WINDOWS_CE_GUI = ... + EFI_APPLICATION = ... + EFI_BOOT_SERVICE_DRIVER = ... + EFI_RUNTIME_DRIVER = ... + EFI_ROM = ... + XBOX = ... + WINDOWS_BOOT_APPLICATION = ... + XBOX_CODE_CATALOG = ... + + class IMAGE_DLLCHARACTERISTICS(__cs__.Flag): + PROCESS_INIT = ... + PROCESS_TERM = ... + THREAD_INIT = ... + THREAD_TERM = ... + HIGH_ENTROPY_VA = ... + DYNAMIC_BASE = ... + FORCE_INTEGRITY = ... + NX_COMPAT = ... + NO_ISOLATION = ... + NO_SEH = ... + NO_BIND = ... + APPCONTAINER = ... + WDM_DRIVER = ... + GUARD_CF = ... + TERMINAL_SERVER_AWARE = ... + + class _IMAGE_OPTIONAL_HEADER(__cs__.Structure): + Magic: _c_pe.uint16 + MajorLinkerVersion: _c_pe.uint8 + MinorLinkerVersion: _c_pe.uint8 + SizeOfCode: _c_pe.uint32 + SizeOfInitializedData: _c_pe.uint32 + SizeOfUninitializedData: _c_pe.uint32 + AddressOfEntryPoint: _c_pe.uint32 + BaseOfCode: _c_pe.uint32 + BaseOfData: _c_pe.uint32 + ImageBase: _c_pe.uint32 + SectionAlignment: _c_pe.uint32 + FileAlignment: _c_pe.uint32 + MajorOperatingSystemVersion: _c_pe.uint16 + MinorOperatingSystemVersion: _c_pe.uint16 + MajorImageVersion: _c_pe.uint16 + MinorImageVersion: _c_pe.uint16 + MajorSubsystemVersion: _c_pe.uint16 + MinorSubsystemVersion: _c_pe.uint16 + Win32VersionValue: _c_pe.uint32 + SizeOfImage: _c_pe.uint32 + SizeOfHeaders: _c_pe.uint32 + CheckSum: _c_pe.uint32 + Subsystem: _c_pe.IMAGE_SUBSYSTEM + DllCharacteristics: _c_pe.IMAGE_DLLCHARACTERISTICS + SizeOfStackReserve: _c_pe.uint32 + SizeOfStackCommit: _c_pe.uint32 + SizeOfHeapReserve: _c_pe.uint32 + SizeOfHeapCommit: _c_pe.uint32 + LoaderFlags: _c_pe.uint32 + NumberOfRvaAndSizes: _c_pe.uint32 + class _IMAGE_DATA_DIRECTORY(__cs__.Structure): + VirtualAddress: _c_pe.uint32 + Size: _c_pe.uint32 + @overload + def __init__(self, VirtualAddress: _c_pe.uint32 | None = ..., Size: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + DataDirectory: __cs__.Array[_IMAGE_DATA_DIRECTORY] + @overload + def __init__( + self, + Magic: _c_pe.uint16 | None = ..., + MajorLinkerVersion: _c_pe.uint8 | None = ..., + MinorLinkerVersion: _c_pe.uint8 | None = ..., + SizeOfCode: _c_pe.uint32 | None = ..., + SizeOfInitializedData: _c_pe.uint32 | None = ..., + SizeOfUninitializedData: _c_pe.uint32 | None = ..., + AddressOfEntryPoint: _c_pe.uint32 | None = ..., + BaseOfCode: _c_pe.uint32 | None = ..., + BaseOfData: _c_pe.uint32 | None = ..., + ImageBase: _c_pe.uint32 | None = ..., + SectionAlignment: _c_pe.uint32 | None = ..., + FileAlignment: _c_pe.uint32 | None = ..., + MajorOperatingSystemVersion: _c_pe.uint16 | None = ..., + MinorOperatingSystemVersion: _c_pe.uint16 | None = ..., + MajorImageVersion: _c_pe.uint16 | None = ..., + MinorImageVersion: _c_pe.uint16 | None = ..., + MajorSubsystemVersion: _c_pe.uint16 | None = ..., + MinorSubsystemVersion: _c_pe.uint16 | None = ..., + Win32VersionValue: _c_pe.uint32 | None = ..., + SizeOfImage: _c_pe.uint32 | None = ..., + SizeOfHeaders: _c_pe.uint32 | None = ..., + CheckSum: _c_pe.uint32 | None = ..., + Subsystem: _c_pe.IMAGE_SUBSYSTEM | None = ..., + DllCharacteristics: _c_pe.IMAGE_DLLCHARACTERISTICS | None = ..., + SizeOfStackReserve: _c_pe.uint32 | None = ..., + SizeOfStackCommit: _c_pe.uint32 | None = ..., + SizeOfHeapReserve: _c_pe.uint32 | None = ..., + SizeOfHeapCommit: _c_pe.uint32 | None = ..., + LoaderFlags: _c_pe.uint32 | None = ..., + NumberOfRvaAndSizes: _c_pe.uint32 | None = ..., + DataDirectory: __cs__.Array[_IMAGE_DATA_DIRECTORY] | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_OPTIONAL_HEADER32: TypeAlias = _IMAGE_OPTIONAL_HEADER + PIMAGE_OPTIONAL_HEADER32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_OPTIONAL_HEADER] + class _IMAGE_OPTIONAL_HEADER64(__cs__.Structure): + Magic: _c_pe.uint16 + MajorLinkerVersion: _c_pe.uint8 + MinorLinkerVersion: _c_pe.uint8 + SizeOfCode: _c_pe.uint32 + SizeOfInitializedData: _c_pe.uint32 + SizeOfUninitializedData: _c_pe.uint32 + AddressOfEntryPoint: _c_pe.uint32 + BaseOfCode: _c_pe.uint32 + ImageBase: _c_pe.uint64 + SectionAlignment: _c_pe.uint32 + FileAlignment: _c_pe.uint32 + MajorOperatingSystemVersion: _c_pe.uint16 + MinorOperatingSystemVersion: _c_pe.uint16 + MajorImageVersion: _c_pe.uint16 + MinorImageVersion: _c_pe.uint16 + MajorSubsystemVersion: _c_pe.uint16 + MinorSubsystemVersion: _c_pe.uint16 + Win32VersionValue: _c_pe.uint32 + SizeOfImage: _c_pe.uint32 + SizeOfHeaders: _c_pe.uint32 + CheckSum: _c_pe.uint32 + Subsystem: _c_pe.IMAGE_SUBSYSTEM + DllCharacteristics: _c_pe.IMAGE_DLLCHARACTERISTICS + SizeOfStackReserve: _c_pe.uint64 + SizeOfStackCommit: _c_pe.uint64 + SizeOfHeapReserve: _c_pe.uint64 + SizeOfHeapCommit: _c_pe.uint64 + LoaderFlags: _c_pe.uint32 + NumberOfRvaAndSizes: _c_pe.uint32 + class _IMAGE_DATA_DIRECTORY(__cs__.Structure): + VirtualAddress: _c_pe.uint32 + Size: _c_pe.uint32 + @overload + def __init__(self, VirtualAddress: _c_pe.uint32 | None = ..., Size: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + DataDirectory: __cs__.Array[_IMAGE_DATA_DIRECTORY] + @overload + def __init__( + self, + Magic: _c_pe.uint16 | None = ..., + MajorLinkerVersion: _c_pe.uint8 | None = ..., + MinorLinkerVersion: _c_pe.uint8 | None = ..., + SizeOfCode: _c_pe.uint32 | None = ..., + SizeOfInitializedData: _c_pe.uint32 | None = ..., + SizeOfUninitializedData: _c_pe.uint32 | None = ..., + AddressOfEntryPoint: _c_pe.uint32 | None = ..., + BaseOfCode: _c_pe.uint32 | None = ..., + ImageBase: _c_pe.uint64 | None = ..., + SectionAlignment: _c_pe.uint32 | None = ..., + FileAlignment: _c_pe.uint32 | None = ..., + MajorOperatingSystemVersion: _c_pe.uint16 | None = ..., + MinorOperatingSystemVersion: _c_pe.uint16 | None = ..., + MajorImageVersion: _c_pe.uint16 | None = ..., + MinorImageVersion: _c_pe.uint16 | None = ..., + MajorSubsystemVersion: _c_pe.uint16 | None = ..., + MinorSubsystemVersion: _c_pe.uint16 | None = ..., + Win32VersionValue: _c_pe.uint32 | None = ..., + SizeOfImage: _c_pe.uint32 | None = ..., + SizeOfHeaders: _c_pe.uint32 | None = ..., + CheckSum: _c_pe.uint32 | None = ..., + Subsystem: _c_pe.IMAGE_SUBSYSTEM | None = ..., + DllCharacteristics: _c_pe.IMAGE_DLLCHARACTERISTICS | None = ..., + SizeOfStackReserve: _c_pe.uint64 | None = ..., + SizeOfStackCommit: _c_pe.uint64 | None = ..., + SizeOfHeapReserve: _c_pe.uint64 | None = ..., + SizeOfHeapCommit: _c_pe.uint64 | None = ..., + LoaderFlags: _c_pe.uint32 | None = ..., + NumberOfRvaAndSizes: _c_pe.uint32 | None = ..., + DataDirectory: __cs__.Array[_IMAGE_DATA_DIRECTORY] | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_OPTIONAL_HEADER64: TypeAlias = _IMAGE_OPTIONAL_HEADER64 + PIMAGE_OPTIONAL_HEADER64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_OPTIONAL_HEADER64] + class _IMAGE_NT_HEADERS64(__cs__.Structure): + Signature: _c_pe.uint32 + FileHeader: _c_pe._IMAGE_FILE_HEADER + OptionalHeader: _c_pe._IMAGE_OPTIONAL_HEADER64 + @overload + def __init__( + self, + Signature: _c_pe.uint32 | None = ..., + FileHeader: _c_pe._IMAGE_FILE_HEADER | None = ..., + OptionalHeader: _c_pe._IMAGE_OPTIONAL_HEADER64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_NT_HEADERS64: TypeAlias = _IMAGE_NT_HEADERS64 + PIMAGE_NT_HEADERS64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_NT_HEADERS64] + class _IMAGE_NT_HEADERS(__cs__.Structure): + Signature: _c_pe.uint32 + FileHeader: _c_pe._IMAGE_FILE_HEADER + OptionalHeader: _c_pe._IMAGE_OPTIONAL_HEADER + @overload + def __init__( + self, + Signature: _c_pe.uint32 | None = ..., + FileHeader: _c_pe._IMAGE_FILE_HEADER | None = ..., + OptionalHeader: _c_pe._IMAGE_OPTIONAL_HEADER | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_NT_HEADERS32: TypeAlias = _IMAGE_NT_HEADERS + PIMAGE_NT_HEADERS32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_NT_HEADERS] + class IMAGE_DIRECTORY_ENTRY(__cs__.Enum): + EXPORT = ... + IMPORT = ... + RESOURCE = ... + EXCEPTION = ... + SECURITY = ... + BASERELOC = ... + DEBUG = ... + COPYRIGHT = ... + ARCHITECTURE = ... + GLOBALPTR = ... + TLS = ... + LOAD_CONFIG = ... + BOUND_IMPORT = ... + IAT = ... + DELAY_IMPORT = ... + COM_DESCRIPTOR = ... + + class IMAGE_SCN(__cs__.Flag): + TYPE_REG = ... + TYPE_DSECT = ... + TYPE_NOLOAD = ... + TYPE_GROUP = ... + TYPE_NO_PAD = ... + TYPE_COPY = ... + CNT_CODE = ... + CNT_INITIALIZED_DATA = ... + CNT_UNINITIALIZED_DATA = ... + LNK_OTHER = ... + LNK_INFO = ... + TYPE_OVER = ... + LNK_REMOVE = ... + LNK_COMDAT = ... + NO_DEFER_SPEC_EXC = ... + GPREL = ... + MEM_FARDATA = ... + MEM_PURGEABLE = ... + MEM_16BIT = ... + MEM_LOCKED = ... + MEM_PRELOAD = ... + ALIGN_1BYTES = ... + ALIGN_2BYTES = ... + ALIGN_4BYTES = ... + ALIGN_8BYTES = ... + ALIGN_16BYTES = ... + ALIGN_32BYTES = ... + ALIGN_64BYTES = ... + ALIGN_128BYTES = ... + ALIGN_256BYTES = ... + ALIGN_512BYTES = ... + ALIGN_1024BYTES = ... + ALIGN_2048BYTES = ... + ALIGN_4096BYTES = ... + ALIGN_8192BYTES = ... + ALIGN_MASK = ... + LNK_NRELOC_OVFL = ... + MEM_DISCARDABLE = ... + MEM_NOT_CACHED = ... + MEM_NOT_PAGED = ... + MEM_SHARED = ... + MEM_EXECUTE = ... + MEM_READ = ... + MEM_WRITE = ... + + class _IMAGE_SECTION_HEADER(__cs__.Structure): + Name: __cs__.CharArray + class __anonymous_0__(__cs__.Union): + PhysicalAddress: _c_pe.uint32 + VirtualSize: _c_pe.uint32 + @overload + def __init__(self, PhysicalAddress: _c_pe.uint32 | None = ..., VirtualSize: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + Misc: __anonymous_0__ + VirtualAddress: _c_pe.uint32 + SizeOfRawData: _c_pe.uint32 + PointerToRawData: _c_pe.uint32 + PointerToRelocations: _c_pe.uint32 + PointerToLinenumbers: _c_pe.uint32 + NumberOfRelocations: _c_pe.uint16 + NumberOfLinenumbers: _c_pe.uint16 + Characteristics: _c_pe.IMAGE_SCN + @overload + def __init__( + self, + Name: __cs__.CharArray | None = ..., + Misc: __anonymous_0__ | None = ..., + VirtualAddress: _c_pe.uint32 | None = ..., + SizeOfRawData: _c_pe.uint32 | None = ..., + PointerToRawData: _c_pe.uint32 | None = ..., + PointerToRelocations: _c_pe.uint32 | None = ..., + PointerToLinenumbers: _c_pe.uint32 | None = ..., + NumberOfRelocations: _c_pe.uint16 | None = ..., + NumberOfLinenumbers: _c_pe.uint16 | None = ..., + Characteristics: _c_pe.IMAGE_SCN | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_SECTION_HEADER: TypeAlias = _IMAGE_SECTION_HEADER + PIMAGE_SECTION_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_SECTION_HEADER] + class IMAGE_REL_BASED(__cs__.Enum): + ABSOLUTE = ... + HIGH = ... + LOW = ... + HIGHLOW = ... + HIGHADJ = ... + MIPS_JMPADDR = ... + ARM_MOV32 = ... + RISCV_HIGH20 = ... + MACHINE_SPECIFIC_5 = ... + RESERVED = ... + THUMB_MOV32 = ... + RISCV_LOW12I = ... + REL32 = ... + MACHINE_SPECIFIC_7 = ... + RISCV_LOW12S = ... + LOONGARCH32_MARK_LA = ... + LOONGARCH64_MARK_LA = ... + VXD_RELATIVE = ... + MACHINE_SPECIFIC_8 = ... + MIPS_JMPADDR16 = ... + IA64_IMM64 = ... + MACHINE_SPECIFIC_9 = ... + DIR64 = ... + + class _IMAGE_BASE_RELOCATION(__cs__.Structure): + VirtualAddress: _c_pe.uint32 + SizeOfBlock: _c_pe.uint32 + @overload + def __init__(self, VirtualAddress: _c_pe.uint32 | None = ..., SizeOfBlock: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_BASE_RELOCATION: TypeAlias = _IMAGE_BASE_RELOCATION + PIMAGE_BASE_RELOCATION: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_BASE_RELOCATION] + class _IMAGE_ARCHIVE_MEMBER_HEADER(__cs__.Structure): + Name: __cs__.CharArray + Date: __cs__.CharArray + UserID: __cs__.CharArray + GroupID: __cs__.CharArray + Mode: __cs__.CharArray + Size: __cs__.CharArray + EndHeader: __cs__.CharArray + @overload + def __init__( + self, + Name: __cs__.CharArray | None = ..., + Date: __cs__.CharArray | None = ..., + UserID: __cs__.CharArray | None = ..., + GroupID: __cs__.CharArray | None = ..., + Mode: __cs__.CharArray | None = ..., + Size: __cs__.CharArray | None = ..., + EndHeader: __cs__.CharArray | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARCHIVE_MEMBER_HEADER: TypeAlias = _IMAGE_ARCHIVE_MEMBER_HEADER + PIMAGE_ARCHIVE_MEMBER_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARCHIVE_MEMBER_HEADER] + class _IMAGE_EXPORT_DIRECTORY(__cs__.Structure): + Characteristics: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + Name: _c_pe.uint32 + Base: _c_pe.uint32 + NumberOfFunctions: _c_pe.uint32 + NumberOfNames: _c_pe.uint32 + AddressOfFunctions: _c_pe.uint32 + AddressOfNames: _c_pe.uint32 + AddressOfNameOrdinals: _c_pe.uint32 + @overload + def __init__( + self, + Characteristics: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + Name: _c_pe.uint32 | None = ..., + Base: _c_pe.uint32 | None = ..., + NumberOfFunctions: _c_pe.uint32 | None = ..., + NumberOfNames: _c_pe.uint32 | None = ..., + AddressOfFunctions: _c_pe.uint32 | None = ..., + AddressOfNames: _c_pe.uint32 | None = ..., + AddressOfNameOrdinals: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_EXPORT_DIRECTORY: TypeAlias = _IMAGE_EXPORT_DIRECTORY + PIMAGE_EXPORT_DIRECTORY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_EXPORT_DIRECTORY] + class _IMAGE_IMPORT_BY_NAME(__cs__.Structure): + Hint: _c_pe.uint16 + Name: __cs__.CharArray + @overload + def __init__(self, Hint: _c_pe.uint16 | None = ..., Name: __cs__.CharArray | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_IMPORT_BY_NAME: TypeAlias = _IMAGE_IMPORT_BY_NAME + PIMAGE_IMPORT_BY_NAME: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_IMPORT_BY_NAME] + class _IMAGE_THUNK_DATA64(__cs__.Structure): + class __anonymous_1__(__cs__.Union): + ForwarderString: _c_pe.uint64 + Function: _c_pe.uint64 + Ordinal: _c_pe.uint64 + AddressOfData: _c_pe.uint64 + @overload + def __init__( + self, + ForwarderString: _c_pe.uint64 | None = ..., + Function: _c_pe.uint64 | None = ..., + Ordinal: _c_pe.uint64 | None = ..., + AddressOfData: _c_pe.uint64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + u1: __anonymous_1__ + @overload + def __init__(self, u1: __anonymous_1__ | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_THUNK_DATA64: TypeAlias = _IMAGE_THUNK_DATA64 + PIMAGE_THUNK_DATA64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_THUNK_DATA64] + class _IMAGE_THUNK_DATA32(__cs__.Structure): + class __anonymous_2__(__cs__.Union): + ForwarderString: _c_pe.uint32 + Function: _c_pe.uint32 + Ordinal: _c_pe.uint32 + AddressOfData: _c_pe.uint32 + @overload + def __init__( + self, + ForwarderString: _c_pe.uint32 | None = ..., + Function: _c_pe.uint32 | None = ..., + Ordinal: _c_pe.uint32 | None = ..., + AddressOfData: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + u1: __anonymous_2__ + @overload + def __init__(self, u1: __anonymous_2__ | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_THUNK_DATA32: TypeAlias = _IMAGE_THUNK_DATA32 + PIMAGE_THUNK_DATA32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_THUNK_DATA32] + class _IMAGE_IMPORT_DESCRIPTOR(__cs__.Structure): + Characteristics: _c_pe.uint32 + OriginalFirstThunk: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + ForwarderChain: _c_pe.uint32 + Name: _c_pe.uint32 + FirstThunk: _c_pe.uint32 + @overload + def __init__( + self, + Characteristics: _c_pe.uint32 | None = ..., + OriginalFirstThunk: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + ForwarderChain: _c_pe.uint32 | None = ..., + Name: _c_pe.uint32 | None = ..., + FirstThunk: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_IMPORT_DESCRIPTOR: TypeAlias = _IMAGE_IMPORT_DESCRIPTOR + PIMAGE_IMPORT_DESCRIPTOR: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_IMPORT_DESCRIPTOR] + class _IMAGE_TLS_DIRECTORY64(__cs__.Structure): + StartAddressOfRawData: _c_pe.uint64 + EndAddressOfRawData: _c_pe.uint64 + AddressOfIndex: _c_pe.uint64 + AddressOfCallBacks: _c_pe.uint64 + SizeOfZeroFill: _c_pe.uint32 + Characteristics: _c_pe.uint32 + Reserved0: _c_pe.uint32 + Alignment: _c_pe.uint32 + Reserved1: _c_pe.uint32 + @overload + def __init__( + self, + StartAddressOfRawData: _c_pe.uint64 | None = ..., + EndAddressOfRawData: _c_pe.uint64 | None = ..., + AddressOfIndex: _c_pe.uint64 | None = ..., + AddressOfCallBacks: _c_pe.uint64 | None = ..., + SizeOfZeroFill: _c_pe.uint32 | None = ..., + Characteristics: _c_pe.uint32 | None = ..., + Reserved0: _c_pe.uint32 | None = ..., + Alignment: _c_pe.uint32 | None = ..., + Reserved1: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_TLS_DIRECTORY64: TypeAlias = _IMAGE_TLS_DIRECTORY64 + PIMAGE_TLS_DIRECTORY64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_TLS_DIRECTORY64] + class _IMAGE_TLS_DIRECTORY32(__cs__.Structure): + StartAddressOfRawData: _c_pe.uint32 + EndAddressOfRawData: _c_pe.uint32 + AddressOfIndex: _c_pe.uint32 + AddressOfCallBacks: _c_pe.uint32 + SizeOfZeroFill: _c_pe.uint32 + Characteristics: _c_pe.uint32 + Reserved0: _c_pe.uint32 + Alignment: _c_pe.uint32 + Reserved1: _c_pe.uint32 + @overload + def __init__( + self, + StartAddressOfRawData: _c_pe.uint32 | None = ..., + EndAddressOfRawData: _c_pe.uint32 | None = ..., + AddressOfIndex: _c_pe.uint32 | None = ..., + AddressOfCallBacks: _c_pe.uint32 | None = ..., + SizeOfZeroFill: _c_pe.uint32 | None = ..., + Characteristics: _c_pe.uint32 | None = ..., + Reserved0: _c_pe.uint32 | None = ..., + Alignment: _c_pe.uint32 | None = ..., + Reserved1: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_TLS_DIRECTORY32: TypeAlias = _IMAGE_TLS_DIRECTORY32 + PIMAGE_TLS_DIRECTORY32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_TLS_DIRECTORY32] + class _IMAGE_BOUND_IMPORT_DESCRIPTOR(__cs__.Structure): + TimeDateStamp: _c_pe.uint32 + OffsetModuleName: _c_pe.uint16 + NumberOfModuleForwarderRefs: _c_pe.uint16 + @overload + def __init__( + self, + TimeDateStamp: _c_pe.uint32 | None = ..., + OffsetModuleName: _c_pe.uint16 | None = ..., + NumberOfModuleForwarderRefs: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_BOUND_IMPORT_DESCRIPTOR: TypeAlias = _IMAGE_BOUND_IMPORT_DESCRIPTOR + PIMAGE_BOUND_IMPORT_DESCRIPTOR: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_BOUND_IMPORT_DESCRIPTOR] + class _IMAGE_BOUND_FORWARDER_REF(__cs__.Structure): + TimeDateStamp: _c_pe.uint32 + OffsetModuleName: _c_pe.uint16 + Reserved: _c_pe.uint16 + @overload + def __init__( + self, + TimeDateStamp: _c_pe.uint32 | None = ..., + OffsetModuleName: _c_pe.uint16 | None = ..., + Reserved: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_BOUND_FORWARDER_REF: TypeAlias = _IMAGE_BOUND_FORWARDER_REF + PIMAGE_BOUND_FORWARDER_REF: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_BOUND_FORWARDER_REF] + class _IMAGE_DELAYLOAD_DESCRIPTOR(__cs__.Structure): + class __anonymous_9__(__cs__.Union): + AllAttributes: _c_pe.uint32 + RvaBased: _c_pe.uint32 + ReservedAttributes: _c_pe.uint32 + @overload + def __init__( + self, + AllAttributes: _c_pe.uint32 | None = ..., + RvaBased: _c_pe.uint32 | None = ..., + ReservedAttributes: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + Attributes: __anonymous_9__ + DllNameRVA: _c_pe.uint32 + ModuleHandleRVA: _c_pe.uint32 + ImportAddressTableRVA: _c_pe.uint32 + ImportNameTableRVA: _c_pe.uint32 + BoundImportAddressTableRVA: _c_pe.uint32 + UnloadInformationTableRVA: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + @overload + def __init__( + self, + Attributes: __anonymous_9__ | None = ..., + DllNameRVA: _c_pe.uint32 | None = ..., + ModuleHandleRVA: _c_pe.uint32 | None = ..., + ImportAddressTableRVA: _c_pe.uint32 | None = ..., + ImportNameTableRVA: _c_pe.uint32 | None = ..., + BoundImportAddressTableRVA: _c_pe.uint32 | None = ..., + UnloadInformationTableRVA: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DELAYLOAD_DESCRIPTOR: TypeAlias = _IMAGE_DELAYLOAD_DESCRIPTOR + PIMAGE_DELAYLOAD_DESCRIPTOR: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DELAYLOAD_DESCRIPTOR] + class RT(__cs__.Enum): + CURSOR = ... + BITMAP = ... + ICON = ... + MENU = ... + DIALOG = ... + STRING = ... + FONTDIR = ... + FONT = ... + ACCELERATOR = ... + RCDATA = ... + MESSAGETABLE = ... + GROUP_CURSOR = ... + GROUP_ICON = ... + VERSION = ... + DLGINCLUDE = ... + PLUGPLAY = ... + VXD = ... + ANICURSOR = ... + ANIICON = ... + HTML = ... + MANIFEST = ... + + class _IMAGE_RESOURCE_DIRECTORY(__cs__.Structure): + Characteristics: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + NumberOfNamedEntries: _c_pe.uint16 + NumberOfIdEntries: _c_pe.uint16 + @overload + def __init__( + self, + Characteristics: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + NumberOfNamedEntries: _c_pe.uint16 | None = ..., + NumberOfIdEntries: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RESOURCE_DIRECTORY: TypeAlias = _IMAGE_RESOURCE_DIRECTORY + PIMAGE_RESOURCE_DIRECTORY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RESOURCE_DIRECTORY] + class _IMAGE_RESOURCE_DIRECTORY_ENTRY(__cs__.Structure): + NameOffset: _c_pe.uint32 + NameIsString: _c_pe.uint32 + Name: _c_pe.uint32 + Id: _c_pe.uint16 + OffsetToData: _c_pe.uint32 + OffsetToDirectory: _c_pe.uint32 + DataIsDirectory: _c_pe.uint32 + @overload + def __init__( + self, + NameOffset: _c_pe.uint32 | None = ..., + NameIsString: _c_pe.uint32 | None = ..., + Name: _c_pe.uint32 | None = ..., + Id: _c_pe.uint16 | None = ..., + OffsetToData: _c_pe.uint32 | None = ..., + OffsetToDirectory: _c_pe.uint32 | None = ..., + DataIsDirectory: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RESOURCE_DIRECTORY_ENTRY: TypeAlias = _IMAGE_RESOURCE_DIRECTORY_ENTRY + PIMAGE_RESOURCE_DIRECTORY_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RESOURCE_DIRECTORY_ENTRY] + class _IMAGE_RESOURCE_DIRECTORY_STRING(__cs__.Structure): + Length: _c_pe.uint16 + NameString: __cs__.CharArray + @overload + def __init__(self, Length: _c_pe.uint16 | None = ..., NameString: __cs__.CharArray | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RESOURCE_DIRECTORY_STRING: TypeAlias = _IMAGE_RESOURCE_DIRECTORY_STRING + PIMAGE_RESOURCE_DIRECTORY_STRING: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RESOURCE_DIRECTORY_STRING] + class _IMAGE_RESOURCE_DIR_STRING_U(__cs__.Structure): + Length: _c_pe.uint16 + NameString: __cs__.WcharArray + @overload + def __init__(self, Length: _c_pe.uint16 | None = ..., NameString: __cs__.WcharArray | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RESOURCE_DIR_STRING_U: TypeAlias = _IMAGE_RESOURCE_DIR_STRING_U + PIMAGE_RESOURCE_DIR_STRING_U: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RESOURCE_DIR_STRING_U] + class _IMAGE_RESOURCE_DATA_ENTRY(__cs__.Structure): + OffsetToData: _c_pe.uint32 + Size: _c_pe.uint32 + CodePage: _c_pe.uint32 + Reserved: _c_pe.uint32 + @overload + def __init__( + self, + OffsetToData: _c_pe.uint32 | None = ..., + Size: _c_pe.uint32 | None = ..., + CodePage: _c_pe.uint32 | None = ..., + Reserved: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RESOURCE_DATA_ENTRY: TypeAlias = _IMAGE_RESOURCE_DATA_ENTRY + PIMAGE_RESOURCE_DATA_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RESOURCE_DATA_ENTRY] + class _VS_FIXEDFILEINFO(__cs__.Structure): + dwSignature: _c_pe.uint32 + dwStrucVersion: _c_pe.uint32 + dwFileVersionMS: _c_pe.uint32 + dwFileVersionLS: _c_pe.uint32 + dwProductVersionMS: _c_pe.uint32 + dwProductVersionLS: _c_pe.uint32 + dwFileFlagsMask: _c_pe.uint32 + dwFileFlags: _c_pe.uint32 + dwFileOS: _c_pe.uint32 + dwFileType: _c_pe.uint32 + dwFileSubtype: _c_pe.uint32 + dwFileDateMS: _c_pe.uint32 + dwFileDateLS: _c_pe.uint32 + @overload + def __init__( + self, + dwSignature: _c_pe.uint32 | None = ..., + dwStrucVersion: _c_pe.uint32 | None = ..., + dwFileVersionMS: _c_pe.uint32 | None = ..., + dwFileVersionLS: _c_pe.uint32 | None = ..., + dwProductVersionMS: _c_pe.uint32 | None = ..., + dwProductVersionLS: _c_pe.uint32 | None = ..., + dwFileFlagsMask: _c_pe.uint32 | None = ..., + dwFileFlags: _c_pe.uint32 | None = ..., + dwFileOS: _c_pe.uint32 | None = ..., + dwFileType: _c_pe.uint32 | None = ..., + dwFileSubtype: _c_pe.uint32 | None = ..., + dwFileDateMS: _c_pe.uint32 | None = ..., + dwFileDateLS: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + VS_FIXEDFILEINFO: TypeAlias = _VS_FIXEDFILEINFO + PVS_FIXEDFILEINFO: TypeAlias = __cs__.Pointer[_c_pe._VS_FIXEDFILEINFO] + class VS_FF(__cs__.Flag): + DEBUG = ... + PRERELEASE = ... + PATCHED = ... + PRIVATEBUILD = ... + INFOINFERRED = ... + SPECIALBUILD = ... + + class VOS(__cs__.Enum): + UNKNOWN = ... + WINDOWS16 = ... + PM16 = ... + PM32 = ... + WINDOWS32 = ... + DOS = ... + OS216 = ... + OS232 = ... + NT = ... + + class VFT(__cs__.Enum): + UNKNOWN = ... + APP = ... + DLL = ... + DRV = ... + FONT = ... + VXD = ... + STATIC_LIBRARY = ... + + class VFT2_DRV(__cs__.Enum): + UNKNOWN = ... + PRINTER = ... + KEYBOARD = ... + LANGUAGE = ... + DISPLAY = ... + MOUSE = ... + NETWORK = ... + SYSTEM = ... + INSTALLABLE = ... + SOUND = ... + COMM = ... + INPUTMETHOD = ... + VERSIONED_PRINTER = ... + + class VFT2_FONT(__cs__.Enum): + UNKNOWN = ... + RASTER = ... + VECTOR = ... + TRUETYPE = ... + + class VK(__cs__.Enum): + LBUTTON = ... + RBUTTON = ... + CANCEL = ... + MBUTTON = ... + XBUTTON1 = ... + XBUTTON2 = ... + BACK = ... + TAB = ... + CLEAR = ... + RETURN = ... + SHIFT = ... + CONTROL = ... + MENU = ... + PAUSE = ... + CAPITAL = ... + KANA = ... + HANGEUL = ... + HANGUL = ... + IME_ON = ... + JUNJA = ... + FINAL = ... + HANJA = ... + KANJI = ... + IME_OFF = ... + ESCAPE = ... + CONVERT = ... + NONCONVERT = ... + ACCEPT = ... + MODECHANGE = ... + SPACE = ... + PRIOR = ... + NEXT = ... + END = ... + HOME = ... + LEFT = ... + UP = ... + RIGHT = ... + DOWN = ... + SELECT = ... + PRINT = ... + EXECUTE = ... + SNAPSHOT = ... + INSERT = ... + DELETE = ... + HELP = ... + "0 = ..." + "1 = ..." + "2 = ..." + "3 = ..." + "4 = ..." + "5 = ..." + "6 = ..." + "7 = ..." + "8 = ..." + "9 = ..." + A = ... + B = ... + C = ... + D = ... + E = ... + F = ... + G = ... + H = ... + I = ... + J = ... + K = ... + L = ... + M = ... + N = ... + O = ... + P = ... + Q = ... + R = ... + S = ... + T = ... + U = ... + V = ... + W = ... + X = ... + Y = ... + Z = ... + LWIN = ... + RWIN = ... + APPS = ... + SLEEP = ... + NUMPAD0 = ... + NUMPAD1 = ... + NUMPAD2 = ... + NUMPAD3 = ... + NUMPAD4 = ... + NUMPAD5 = ... + NUMPAD6 = ... + NUMPAD7 = ... + NUMPAD8 = ... + NUMPAD9 = ... + MULTIPLY = ... + ADD = ... + SEPARATOR = ... + SUBTRACT = ... + DECIMAL = ... + DIVIDE = ... + F1 = ... + F2 = ... + F3 = ... + F4 = ... + F5 = ... + F6 = ... + F7 = ... + F8 = ... + F9 = ... + F10 = ... + F11 = ... + F12 = ... + F13 = ... + F14 = ... + F15 = ... + F16 = ... + F17 = ... + F18 = ... + F19 = ... + F20 = ... + F21 = ... + F22 = ... + F23 = ... + F24 = ... + NAVIGATION_VIEW = ... + NAVIGATION_MENU = ... + NAVIGATION_UP = ... + NAVIGATION_DOWN = ... + NAVIGATION_LEFT = ... + NAVIGATION_RIGHT = ... + NAVIGATION_ACCEPT = ... + NAVIGATION_CANCEL = ... + NUMLOCK = ... + SCROLL = ... + OEM_NEC_EQUAL = ... + OEM_FJ_JISHO = ... + OEM_FJ_MASSHOU = ... + OEM_FJ_TOUROKU = ... + OEM_FJ_LOYA = ... + OEM_FJ_ROYA = ... + LSHIFT = ... + RSHIFT = ... + LCONTROL = ... + RCONTROL = ... + LMENU = ... + RMENU = ... + BROWSER_BACK = ... + BROWSER_FORWARD = ... + BROWSER_REFRESH = ... + BROWSER_STOP = ... + BROWSER_SEARCH = ... + BROWSER_FAVORITES = ... + BROWSER_HOME = ... + VOLUME_MUTE = ... + VOLUME_DOWN = ... + VOLUME_UP = ... + MEDIA_NEXT_TRACK = ... + MEDIA_PREV_TRACK = ... + MEDIA_STOP = ... + MEDIA_PLAY_PAUSE = ... + LAUNCH_MAIL = ... + LAUNCH_MEDIA_SELECT = ... + LAUNCH_APP1 = ... + LAUNCH_APP2 = ... + OEM_1 = ... + OEM_PLUS = ... + OEM_COMMA = ... + OEM_MINUS = ... + OEM_PERIOD = ... + OEM_2 = ... + OEM_3 = ... + GAMEPAD_A = ... + GAMEPAD_B = ... + GAMEPAD_X = ... + GAMEPAD_Y = ... + GAMEPAD_RIGHT_SHOULDER = ... + GAMEPAD_LEFT_SHOULDER = ... + GAMEPAD_LEFT_TRIGGER = ... + GAMEPAD_RIGHT_TRIGGER = ... + GAMEPAD_DPAD_UP = ... + GAMEPAD_DPAD_DOWN = ... + GAMEPAD_DPAD_LEFT = ... + GAMEPAD_DPAD_RIGHT = ... + GAMEPAD_MENU = ... + GAMEPAD_VIEW = ... + GAMEPAD_LEFT_THUMBSTICK_BUTTON = ... + GAMEPAD_RIGHT_THUMBSTICK_BUTTON = ... + GAMEPAD_LEFT_THUMBSTICK_UP = ... + GAMEPAD_LEFT_THUMBSTICK_DOWN = ... + GAMEPAD_LEFT_THUMBSTICK_RIGHT = ... + GAMEPAD_LEFT_THUMBSTICK_LEFT = ... + GAMEPAD_RIGHT_THUMBSTICK_UP = ... + GAMEPAD_RIGHT_THUMBSTICK_DOWN = ... + GAMEPAD_RIGHT_THUMBSTICK_RIGHT = ... + GAMEPAD_RIGHT_THUMBSTICK_LEFT = ... + OEM_4 = ... + OEM_5 = ... + OEM_6 = ... + OEM_7 = ... + OEM_8 = ... + OEM_AX = ... + OEM_102 = ... + ICO_HELP = ... + ICO_00 = ... + PROCESSKEY = ... + ICO_CLEAR = ... + PACKET = ... + OEM_RESET = ... + OEM_JUMP = ... + OEM_PA1 = ... + OEM_PA2 = ... + OEM_PA3 = ... + OEM_WSCTRL = ... + OEM_CUSEL = ... + OEM_ATTN = ... + OEM_FINISH = ... + OEM_COPY = ... + OEM_AUTO = ... + OEM_ENLW = ... + OEM_BACKTAB = ... + ATTN = ... + CRSEL = ... + EXSEL = ... + EREOF = ... + PLAY = ... + ZOOM = ... + NONAME = ... + PA1 = ... + OEM_CLEAR = ... + + class ACCEL_F(__cs__.Flag): + VIRTKEY = ... + LASTKEY = ... + NOINVERT = ... + SHIFT = ... + CONTROL = ... + ALT = ... + + class _IMAGE_LOAD_CONFIG_CODE_INTEGRITY(__cs__.Structure): + Flags: _c_pe.uint16 + Catalog: _c_pe.uint16 + CatalogOffset: _c_pe.uint32 + Reserved: _c_pe.uint32 + @overload + def __init__( + self, + Flags: _c_pe.uint16 | None = ..., + Catalog: _c_pe.uint16 | None = ..., + CatalogOffset: _c_pe.uint32 | None = ..., + Reserved: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_LOAD_CONFIG_CODE_INTEGRITY: TypeAlias = _IMAGE_LOAD_CONFIG_CODE_INTEGRITY + PIMAGE_LOAD_CONFIG_CODE_INTEGRITY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_LOAD_CONFIG_CODE_INTEGRITY] + class _IMAGE_DYNAMIC_RELOCATION_TABLE(__cs__.Structure): + Version: _c_pe.uint32 + Size: _c_pe.uint32 + @overload + def __init__(self, Version: _c_pe.uint32 | None = ..., Size: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DYNAMIC_RELOCATION_TABLE: TypeAlias = _IMAGE_DYNAMIC_RELOCATION_TABLE + PIMAGE_DYNAMIC_RELOCATION_TABLE: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DYNAMIC_RELOCATION_TABLE] + class _IMAGE_DYNAMIC_RELOCATION32(__cs__.Structure): + Symbol: _c_pe.uint32 + BaseRelocSize: _c_pe.uint32 + @overload + def __init__(self, Symbol: _c_pe.uint32 | None = ..., BaseRelocSize: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DYNAMIC_RELOCATION32: TypeAlias = _IMAGE_DYNAMIC_RELOCATION32 + PIMAGE_DYNAMIC_RELOCATION32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DYNAMIC_RELOCATION32] + class _IMAGE_DYNAMIC_RELOCATION64(__cs__.Structure): + Symbol: _c_pe.uint64 + BaseRelocSize: _c_pe.uint32 + @overload + def __init__(self, Symbol: _c_pe.uint64 | None = ..., BaseRelocSize: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DYNAMIC_RELOCATION64: TypeAlias = _IMAGE_DYNAMIC_RELOCATION64 + PIMAGE_DYNAMIC_RELOCATION64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DYNAMIC_RELOCATION64] + class _IMAGE_DYNAMIC_RELOCATION32_V2(__cs__.Structure): + HeaderSize: _c_pe.uint32 + FixupInfoSize: _c_pe.uint32 + Symbol: _c_pe.uint32 + SymbolGroup: _c_pe.uint32 + Flags: _c_pe.uint32 + @overload + def __init__( + self, + HeaderSize: _c_pe.uint32 | None = ..., + FixupInfoSize: _c_pe.uint32 | None = ..., + Symbol: _c_pe.uint32 | None = ..., + SymbolGroup: _c_pe.uint32 | None = ..., + Flags: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DYNAMIC_RELOCATION32_V2: TypeAlias = _IMAGE_DYNAMIC_RELOCATION32_V2 + PIMAGE_DYNAMIC_RELOCATION32_V2: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DYNAMIC_RELOCATION32_V2] + class _IMAGE_DYNAMIC_RELOCATION64_V2(__cs__.Structure): + HeaderSize: _c_pe.uint32 + FixupInfoSize: _c_pe.uint32 + Symbol: _c_pe.uint64 + SymbolGroup: _c_pe.uint32 + Flags: _c_pe.uint32 + @overload + def __init__( + self, + HeaderSize: _c_pe.uint32 | None = ..., + FixupInfoSize: _c_pe.uint32 | None = ..., + Symbol: _c_pe.uint64 | None = ..., + SymbolGroup: _c_pe.uint32 | None = ..., + Flags: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DYNAMIC_RELOCATION64_V2: TypeAlias = _IMAGE_DYNAMIC_RELOCATION64_V2 + PIMAGE_DYNAMIC_RELOCATION64_V2: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DYNAMIC_RELOCATION64_V2] + class _IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER(__cs__.Structure): + PrologueByteCount: _c_pe.uint8 + @overload + def __init__(self, PrologueByteCount: _c_pe.uint8 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER: TypeAlias = _IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER + PIMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER + ] + class _IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER(__cs__.Structure): + EpilogueCount: _c_pe.uint32 + EpilogueByteCount: _c_pe.uint8 + BranchDescriptorElementSize: _c_pe.uint8 + BranchDescriptorCount: _c_pe.uint16 + @overload + def __init__( + self, + EpilogueCount: _c_pe.uint32 | None = ..., + EpilogueByteCount: _c_pe.uint8 | None = ..., + BranchDescriptorElementSize: _c_pe.uint8 | None = ..., + BranchDescriptorCount: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER: TypeAlias = _IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER + PIMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER + ] + class _IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION(__cs__.Structure): + PageRelativeOffset: _c_pe.uint32 + IndirectCall: _c_pe.uint32 + IATIndex: _c_pe.uint32 + @overload + def __init__( + self, + PageRelativeOffset: _c_pe.uint32 | None = ..., + IndirectCall: _c_pe.uint32 | None = ..., + IATIndex: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION: TypeAlias = _IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION + PIMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION + ] + class _IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION(__cs__.Structure): + PageRelativeOffset: _c_pe.uint32 + IndirectCall: _c_pe.uint32 + RegisterIndex: _c_pe.uint32 + ImportType: _c_pe.uint32 + IATIndex: _c_pe.uint32 + @overload + def __init__( + self, + PageRelativeOffset: _c_pe.uint32 | None = ..., + IndirectCall: _c_pe.uint32 | None = ..., + RegisterIndex: _c_pe.uint32 | None = ..., + ImportType: _c_pe.uint32 | None = ..., + IATIndex: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION: TypeAlias = _IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION + PIMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_IMPORT_CONTROL_TRANSFER_ARM64_RELOCATION + ] + class _IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION(__cs__.Structure): + PageRelativeOffset: _c_pe.uint16 + IndirectCall: _c_pe.uint16 + RexWPrefix: _c_pe.uint16 + CfgCheck: _c_pe.uint16 + Reserved: _c_pe.uint16 + @overload + def __init__( + self, + PageRelativeOffset: _c_pe.uint16 | None = ..., + IndirectCall: _c_pe.uint16 | None = ..., + RexWPrefix: _c_pe.uint16 | None = ..., + CfgCheck: _c_pe.uint16 | None = ..., + Reserved: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION: TypeAlias = _IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION + PIMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION + ] + class _IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION(__cs__.Structure): + PageRelativeOffset: _c_pe.uint16 + RegisterNumber: _c_pe.uint16 + @overload + def __init__( + self, PageRelativeOffset: _c_pe.uint16 | None = ..., RegisterNumber: _c_pe.uint16 | None = ... + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION: TypeAlias = _IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION + PIMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION + ] + class _IMAGE_FUNCTION_OVERRIDE_HEADER(__cs__.Structure): + FuncOverrideSize: _c_pe.uint32 + @overload + def __init__(self, FuncOverrideSize: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_FUNCTION_OVERRIDE_HEADER: TypeAlias = _IMAGE_FUNCTION_OVERRIDE_HEADER + PIMAGE_FUNCTION_OVERRIDE_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_FUNCTION_OVERRIDE_HEADER] + class _IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION(__cs__.Structure): + OriginalRva: _c_pe.uint32 + BDDOffset: _c_pe.uint32 + RvaSize: _c_pe.uint32 + BaseRelocSize: _c_pe.uint32 + @overload + def __init__( + self, + OriginalRva: _c_pe.uint32 | None = ..., + BDDOffset: _c_pe.uint32 | None = ..., + RvaSize: _c_pe.uint32 | None = ..., + BaseRelocSize: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION: TypeAlias = _IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION + PIMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION + ] + class _IMAGE_BDD_INFO(__cs__.Structure): + Version: _c_pe.uint32 + BDDSize: _c_pe.uint32 + @overload + def __init__(self, Version: _c_pe.uint32 | None = ..., BDDSize: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_BDD_INFO: TypeAlias = _IMAGE_BDD_INFO + PIMAGE_BDD_INFO: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_BDD_INFO] + class _IMAGE_BDD_DYNAMIC_RELOCATION(__cs__.Structure): + Left: _c_pe.uint16 + Right: _c_pe.uint16 + Value: _c_pe.uint32 + @overload + def __init__( + self, Left: _c_pe.uint16 | None = ..., Right: _c_pe.uint16 | None = ..., Value: _c_pe.uint32 | None = ... + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_BDD_DYNAMIC_RELOCATION: TypeAlias = _IMAGE_BDD_DYNAMIC_RELOCATION + PIMAGE_BDD_DYNAMIC_RELOCATION: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_BDD_DYNAMIC_RELOCATION] + class IMAGE_GUARD(__cs__.Flag): + CF_INSTRUMENTED = ... + CFW_INSTRUMENTED = ... + CF_FUNCTION_TABLE_PRESENT = ... + SECURITY_COOKIE_UNUSED = ... + PROTECT_DELAYLOAD_IAT = ... + DELAYLOAD_IAT_IN_ITS_OWN_SECTION = ... + CF_EXPORT_SUPPRESSION_INFO_PRESENT = ... + CF_ENABLE_EXPORT_SUPPRESSION = ... + CF_LONGJUMP_TABLE_PRESENT = ... + RF_INSTRUMENTED = ... + RF_ENABLE = ... + RF_STRICT = ... + RETPOLINE_PRESENT = ... + EH_CONTINUATION_TABLE_PRESENT = ... + XFG_ENABLED = ... + CASTGUARD_PRESENT = ... + MEMCPY_PRESENT = ... + + class _IMAGE_LOAD_CONFIG_DIRECTORY32(__cs__.Structure): + Size: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + GlobalFlagsClear: _c_pe.uint32 + GlobalFlagsSet: _c_pe.uint32 + CriticalSectionDefaultTimeout: _c_pe.uint32 + DeCommitFreeBlockThreshold: _c_pe.uint32 + DeCommitTotalFreeThreshold: _c_pe.uint32 + LockPrefixTable: _c_pe.uint32 + MaximumAllocationSize: _c_pe.uint32 + VirtualMemoryThreshold: _c_pe.uint32 + ProcessHeapFlags: _c_pe.uint32 + ProcessAffinityMask: _c_pe.uint32 + CSDVersion: _c_pe.uint16 + DependentLoadFlags: _c_pe.uint16 + EditList: _c_pe.uint32 + SecurityCookie: _c_pe.uint32 + SEHandlerTable: _c_pe.uint32 + SEHandlerCount: _c_pe.uint32 + GuardCFCheckFunctionPointer: _c_pe.uint32 + GuardCFDispatchFunctionPointer: _c_pe.uint32 + GuardCFFunctionTable: _c_pe.uint32 + GuardCFFunctionCount: _c_pe.uint32 + GuardFlags: _c_pe.IMAGE_GUARD + CodeIntegrity: _c_pe._IMAGE_LOAD_CONFIG_CODE_INTEGRITY + GuardAddressTakenIatEntryTable: _c_pe.uint32 + GuardAddressTakenIatEntryCount: _c_pe.uint32 + GuardLongJumpTargetTable: _c_pe.uint32 + GuardLongJumpTargetCount: _c_pe.uint32 + DynamicValueRelocTable: _c_pe.uint32 + CHPEMetadataPointer: _c_pe.uint32 + GuardRFFailureRoutine: _c_pe.uint32 + GuardRFFailureRoutineFunctionPointer: _c_pe.uint32 + DynamicValueRelocTableOffset: _c_pe.uint32 + DynamicValueRelocTableSection: _c_pe.uint16 + Reserved2: _c_pe.uint16 + GuardRFVerifyStackPointerFunctionPointer: _c_pe.uint32 + HotPatchTableOffset: _c_pe.uint32 + Reserved3: _c_pe.uint32 + EnclaveConfigurationPointer: _c_pe.uint32 + VolatileMetadataPointer: _c_pe.uint32 + GuardEHContinuationTable: _c_pe.uint32 + GuardEHContinuationCount: _c_pe.uint32 + GuardXFGCheckFunctionPointer: _c_pe.uint32 + GuardXFGDispatchFunctionPointer: _c_pe.uint32 + GuardXFGTableDispatchFunctionPointer: _c_pe.uint32 + CastGuardOsDeterminedFailureMode: _c_pe.uint32 + GuardMemcpyFunctionPointer: _c_pe.uint32 + UmaFunctionPointers: _c_pe.uint32 + @overload + def __init__( + self, + Size: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + GlobalFlagsClear: _c_pe.uint32 | None = ..., + GlobalFlagsSet: _c_pe.uint32 | None = ..., + CriticalSectionDefaultTimeout: _c_pe.uint32 | None = ..., + DeCommitFreeBlockThreshold: _c_pe.uint32 | None = ..., + DeCommitTotalFreeThreshold: _c_pe.uint32 | None = ..., + LockPrefixTable: _c_pe.uint32 | None = ..., + MaximumAllocationSize: _c_pe.uint32 | None = ..., + VirtualMemoryThreshold: _c_pe.uint32 | None = ..., + ProcessHeapFlags: _c_pe.uint32 | None = ..., + ProcessAffinityMask: _c_pe.uint32 | None = ..., + CSDVersion: _c_pe.uint16 | None = ..., + DependentLoadFlags: _c_pe.uint16 | None = ..., + EditList: _c_pe.uint32 | None = ..., + SecurityCookie: _c_pe.uint32 | None = ..., + SEHandlerTable: _c_pe.uint32 | None = ..., + SEHandlerCount: _c_pe.uint32 | None = ..., + GuardCFCheckFunctionPointer: _c_pe.uint32 | None = ..., + GuardCFDispatchFunctionPointer: _c_pe.uint32 | None = ..., + GuardCFFunctionTable: _c_pe.uint32 | None = ..., + GuardCFFunctionCount: _c_pe.uint32 | None = ..., + GuardFlags: _c_pe.IMAGE_GUARD | None = ..., + CodeIntegrity: _c_pe._IMAGE_LOAD_CONFIG_CODE_INTEGRITY | None = ..., + GuardAddressTakenIatEntryTable: _c_pe.uint32 | None = ..., + GuardAddressTakenIatEntryCount: _c_pe.uint32 | None = ..., + GuardLongJumpTargetTable: _c_pe.uint32 | None = ..., + GuardLongJumpTargetCount: _c_pe.uint32 | None = ..., + DynamicValueRelocTable: _c_pe.uint32 | None = ..., + CHPEMetadataPointer: _c_pe.uint32 | None = ..., + GuardRFFailureRoutine: _c_pe.uint32 | None = ..., + GuardRFFailureRoutineFunctionPointer: _c_pe.uint32 | None = ..., + DynamicValueRelocTableOffset: _c_pe.uint32 | None = ..., + DynamicValueRelocTableSection: _c_pe.uint16 | None = ..., + Reserved2: _c_pe.uint16 | None = ..., + GuardRFVerifyStackPointerFunctionPointer: _c_pe.uint32 | None = ..., + HotPatchTableOffset: _c_pe.uint32 | None = ..., + Reserved3: _c_pe.uint32 | None = ..., + EnclaveConfigurationPointer: _c_pe.uint32 | None = ..., + VolatileMetadataPointer: _c_pe.uint32 | None = ..., + GuardEHContinuationTable: _c_pe.uint32 | None = ..., + GuardEHContinuationCount: _c_pe.uint32 | None = ..., + GuardXFGCheckFunctionPointer: _c_pe.uint32 | None = ..., + GuardXFGDispatchFunctionPointer: _c_pe.uint32 | None = ..., + GuardXFGTableDispatchFunctionPointer: _c_pe.uint32 | None = ..., + CastGuardOsDeterminedFailureMode: _c_pe.uint32 | None = ..., + GuardMemcpyFunctionPointer: _c_pe.uint32 | None = ..., + UmaFunctionPointers: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_LOAD_CONFIG_DIRECTORY32: TypeAlias = _IMAGE_LOAD_CONFIG_DIRECTORY32 + PIMAGE_LOAD_CONFIG_DIRECTORY32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_LOAD_CONFIG_DIRECTORY32] + class _IMAGE_LOAD_CONFIG_DIRECTORY64(__cs__.Structure): + Size: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + GlobalFlagsClear: _c_pe.uint32 + GlobalFlagsSet: _c_pe.uint32 + CriticalSectionDefaultTimeout: _c_pe.uint32 + DeCommitFreeBlockThreshold: _c_pe.uint64 + DeCommitTotalFreeThreshold: _c_pe.uint64 + LockPrefixTable: _c_pe.uint64 + MaximumAllocationSize: _c_pe.uint64 + VirtualMemoryThreshold: _c_pe.uint64 + ProcessAffinityMask: _c_pe.uint64 + ProcessHeapFlags: _c_pe.uint32 + CSDVersion: _c_pe.uint16 + DependentLoadFlags: _c_pe.uint16 + EditList: _c_pe.uint64 + SecurityCookie: _c_pe.uint64 + SEHandlerTable: _c_pe.uint64 + SEHandlerCount: _c_pe.uint64 + GuardCFCheckFunctionPointer: _c_pe.uint64 + GuardCFDispatchFunctionPointer: _c_pe.uint64 + GuardCFFunctionTable: _c_pe.uint64 + GuardCFFunctionCount: _c_pe.uint64 + GuardFlags: _c_pe.IMAGE_GUARD + CodeIntegrity: _c_pe._IMAGE_LOAD_CONFIG_CODE_INTEGRITY + GuardAddressTakenIatEntryTable: _c_pe.uint64 + GuardAddressTakenIatEntryCount: _c_pe.uint64 + GuardLongJumpTargetTable: _c_pe.uint64 + GuardLongJumpTargetCount: _c_pe.uint64 + DynamicValueRelocTable: _c_pe.uint64 + CHPEMetadataPointer: _c_pe.uint64 + GuardRFFailureRoutine: _c_pe.uint64 + GuardRFFailureRoutineFunctionPointer: _c_pe.uint64 + DynamicValueRelocTableOffset: _c_pe.uint32 + DynamicValueRelocTableSection: _c_pe.uint16 + Reserved2: _c_pe.uint16 + GuardRFVerifyStackPointerFunctionPointer: _c_pe.uint64 + HotPatchTableOffset: _c_pe.uint32 + Reserved3: _c_pe.uint32 + EnclaveConfigurationPointer: _c_pe.uint64 + VolatileMetadataPointer: _c_pe.uint64 + GuardEHContinuationTable: _c_pe.uint64 + GuardEHContinuationCount: _c_pe.uint64 + GuardXFGCheckFunctionPointer: _c_pe.uint64 + GuardXFGDispatchFunctionPointer: _c_pe.uint64 + GuardXFGTableDispatchFunctionPointer: _c_pe.uint64 + CastGuardOsDeterminedFailureMode: _c_pe.uint64 + GuardMemcpyFunctionPointer: _c_pe.uint64 + UmaFunctionPointers: _c_pe.uint64 + @overload + def __init__( + self, + Size: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + GlobalFlagsClear: _c_pe.uint32 | None = ..., + GlobalFlagsSet: _c_pe.uint32 | None = ..., + CriticalSectionDefaultTimeout: _c_pe.uint32 | None = ..., + DeCommitFreeBlockThreshold: _c_pe.uint64 | None = ..., + DeCommitTotalFreeThreshold: _c_pe.uint64 | None = ..., + LockPrefixTable: _c_pe.uint64 | None = ..., + MaximumAllocationSize: _c_pe.uint64 | None = ..., + VirtualMemoryThreshold: _c_pe.uint64 | None = ..., + ProcessAffinityMask: _c_pe.uint64 | None = ..., + ProcessHeapFlags: _c_pe.uint32 | None = ..., + CSDVersion: _c_pe.uint16 | None = ..., + DependentLoadFlags: _c_pe.uint16 | None = ..., + EditList: _c_pe.uint64 | None = ..., + SecurityCookie: _c_pe.uint64 | None = ..., + SEHandlerTable: _c_pe.uint64 | None = ..., + SEHandlerCount: _c_pe.uint64 | None = ..., + GuardCFCheckFunctionPointer: _c_pe.uint64 | None = ..., + GuardCFDispatchFunctionPointer: _c_pe.uint64 | None = ..., + GuardCFFunctionTable: _c_pe.uint64 | None = ..., + GuardCFFunctionCount: _c_pe.uint64 | None = ..., + GuardFlags: _c_pe.IMAGE_GUARD | None = ..., + CodeIntegrity: _c_pe._IMAGE_LOAD_CONFIG_CODE_INTEGRITY | None = ..., + GuardAddressTakenIatEntryTable: _c_pe.uint64 | None = ..., + GuardAddressTakenIatEntryCount: _c_pe.uint64 | None = ..., + GuardLongJumpTargetTable: _c_pe.uint64 | None = ..., + GuardLongJumpTargetCount: _c_pe.uint64 | None = ..., + DynamicValueRelocTable: _c_pe.uint64 | None = ..., + CHPEMetadataPointer: _c_pe.uint64 | None = ..., + GuardRFFailureRoutine: _c_pe.uint64 | None = ..., + GuardRFFailureRoutineFunctionPointer: _c_pe.uint64 | None = ..., + DynamicValueRelocTableOffset: _c_pe.uint32 | None = ..., + DynamicValueRelocTableSection: _c_pe.uint16 | None = ..., + Reserved2: _c_pe.uint16 | None = ..., + GuardRFVerifyStackPointerFunctionPointer: _c_pe.uint64 | None = ..., + HotPatchTableOffset: _c_pe.uint32 | None = ..., + Reserved3: _c_pe.uint32 | None = ..., + EnclaveConfigurationPointer: _c_pe.uint64 | None = ..., + VolatileMetadataPointer: _c_pe.uint64 | None = ..., + GuardEHContinuationTable: _c_pe.uint64 | None = ..., + GuardEHContinuationCount: _c_pe.uint64 | None = ..., + GuardXFGCheckFunctionPointer: _c_pe.uint64 | None = ..., + GuardXFGDispatchFunctionPointer: _c_pe.uint64 | None = ..., + GuardXFGTableDispatchFunctionPointer: _c_pe.uint64 | None = ..., + CastGuardOsDeterminedFailureMode: _c_pe.uint64 | None = ..., + GuardMemcpyFunctionPointer: _c_pe.uint64 | None = ..., + UmaFunctionPointers: _c_pe.uint64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_LOAD_CONFIG_DIRECTORY64: TypeAlias = _IMAGE_LOAD_CONFIG_DIRECTORY64 + PIMAGE_LOAD_CONFIG_DIRECTORY64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_LOAD_CONFIG_DIRECTORY64] + class _IMAGE_CHPE_METADATA_X86(__cs__.Structure): + Version: _c_pe.uint32 + CHPECodeAddressRangeOffset: _c_pe.uint32 + CHPECodeAddressRangeCount: _c_pe.uint32 + WowA64ExceptionHandlerFunctionPointer: _c_pe.uint32 + WowA64DispatchCallFunctionPointer: _c_pe.uint32 + WowA64DispatchIndirectCallFunctionPointer: _c_pe.uint32 + WowA64DispatchIndirectCallCfgFunctionPointer: _c_pe.uint32 + WowA64DispatchRetFunctionPointer: _c_pe.uint32 + WowA64DispatchRetLeafFunctionPointer: _c_pe.uint32 + WowA64DispatchJumpFunctionPointer: _c_pe.uint32 + CompilerIATPointer: _c_pe.uint32 + WowA64RdtscFunctionPointer: _c_pe.uint32 + @overload + def __init__( + self, + Version: _c_pe.uint32 | None = ..., + CHPECodeAddressRangeOffset: _c_pe.uint32 | None = ..., + CHPECodeAddressRangeCount: _c_pe.uint32 | None = ..., + WowA64ExceptionHandlerFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchCallFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchIndirectCallFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchIndirectCallCfgFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchRetFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchRetLeafFunctionPointer: _c_pe.uint32 | None = ..., + WowA64DispatchJumpFunctionPointer: _c_pe.uint32 | None = ..., + CompilerIATPointer: _c_pe.uint32 | None = ..., + WowA64RdtscFunctionPointer: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_CHPE_METADATA_X86: TypeAlias = _IMAGE_CHPE_METADATA_X86 + PIMAGE_CHPE_METADATA_X86: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_CHPE_METADATA_X86] + class _IMAGE_CHPE_RANGE_ENTRY(__cs__.Structure): + StartOffset: _c_pe.uint32 + NativeCode: _c_pe.uint32 + AddressBits: _c_pe.uint32 + Length: _c_pe.uint32 + @overload + def __init__( + self, + StartOffset: _c_pe.uint32 | None = ..., + NativeCode: _c_pe.uint32 | None = ..., + AddressBits: _c_pe.uint32 | None = ..., + Length: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_CHPE_RANGE_ENTRY: TypeAlias = _IMAGE_CHPE_RANGE_ENTRY + PIMAGE_CHPE_RANGE_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_CHPE_RANGE_ENTRY] + class _IMAGE_ARM64EC_METADATA(__cs__.Structure): + Version: _c_pe.uint32 + CodeMap: _c_pe.uint32 + CodeMapCount: _c_pe.uint32 + CodeRangesToEntryPoints: _c_pe.uint32 + RedirectionMetadata: _c_pe.uint32 + tbd__os_arm64x_dispatch_call_no_redirect: _c_pe.uint32 + tbd__os_arm64x_dispatch_ret: _c_pe.uint32 + tbd__os_arm64x_dispatch_call: _c_pe.uint32 + tbd__os_arm64x_dispatch_icall: _c_pe.uint32 + tbd__os_arm64x_dispatch_icall_cfg: _c_pe.uint32 + AlternateEntryPoint: _c_pe.uint32 + AuxiliaryIAT: _c_pe.uint32 + CodeRangesToEntryPointsCount: _c_pe.uint32 + RedirectionMetadataCount: _c_pe.uint32 + GetX64InformationFunctionPointer: _c_pe.uint32 + SetX64InformationFunctionPointer: _c_pe.uint32 + ExtraRFETable: _c_pe.uint32 + ExtraRFETableSize: _c_pe.uint32 + __os_arm64x_dispatch_fptr: _c_pe.uint32 + AuxiliaryIATCopy: _c_pe.uint32 + @overload + def __init__( + self, + Version: _c_pe.uint32 | None = ..., + CodeMap: _c_pe.uint32 | None = ..., + CodeMapCount: _c_pe.uint32 | None = ..., + CodeRangesToEntryPoints: _c_pe.uint32 | None = ..., + RedirectionMetadata: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_call_no_redirect: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_ret: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_call: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_icall: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_icall_cfg: _c_pe.uint32 | None = ..., + AlternateEntryPoint: _c_pe.uint32 | None = ..., + AuxiliaryIAT: _c_pe.uint32 | None = ..., + CodeRangesToEntryPointsCount: _c_pe.uint32 | None = ..., + RedirectionMetadataCount: _c_pe.uint32 | None = ..., + GetX64InformationFunctionPointer: _c_pe.uint32 | None = ..., + SetX64InformationFunctionPointer: _c_pe.uint32 | None = ..., + ExtraRFETable: _c_pe.uint32 | None = ..., + ExtraRFETableSize: _c_pe.uint32 | None = ..., + __os_arm64x_dispatch_fptr: _c_pe.uint32 | None = ..., + AuxiliaryIATCopy: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64EC_METADATA: TypeAlias = _IMAGE_ARM64EC_METADATA + PIMAGE_ARM64EC_METADATA: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM64EC_METADATA] + class _IMAGE_ARM64EC_METADATA_V2(__cs__.Structure): + Version: _c_pe.uint32 + CodeMap: _c_pe.uint32 + CodeMapCount: _c_pe.uint32 + CodeRangesToEntryPoints: _c_pe.uint32 + RedirectionMetadata: _c_pe.uint32 + tbd__os_arm64x_dispatch_call_no_redirect: _c_pe.uint32 + tbd__os_arm64x_dispatch_ret: _c_pe.uint32 + tbd__os_arm64x_dispatch_call: _c_pe.uint32 + tbd__os_arm64x_dispatch_icall: _c_pe.uint32 + tbd__os_arm64x_dispatch_icall_cfg: _c_pe.uint32 + AlternateEntryPoint: _c_pe.uint32 + AuxiliaryIAT: _c_pe.uint32 + CodeRangesToEntryPointsCount: _c_pe.uint32 + RedirectionMetadataCount: _c_pe.uint32 + GetX64InformationFunctionPointer: _c_pe.uint32 + SetX64InformationFunctionPointer: _c_pe.uint32 + ExtraRFETable: _c_pe.uint32 + ExtraRFETableSize: _c_pe.uint32 + __os_arm64x_dispatch_fptr: _c_pe.uint32 + AuxiliaryIATCopy: _c_pe.uint32 + AuxDelayloadIAT: _c_pe.uint32 + AuxDelayloadIATCopy: _c_pe.uint32 + ReservedBitField: _c_pe.uint32 + @overload + def __init__( + self, + Version: _c_pe.uint32 | None = ..., + CodeMap: _c_pe.uint32 | None = ..., + CodeMapCount: _c_pe.uint32 | None = ..., + CodeRangesToEntryPoints: _c_pe.uint32 | None = ..., + RedirectionMetadata: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_call_no_redirect: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_ret: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_call: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_icall: _c_pe.uint32 | None = ..., + tbd__os_arm64x_dispatch_icall_cfg: _c_pe.uint32 | None = ..., + AlternateEntryPoint: _c_pe.uint32 | None = ..., + AuxiliaryIAT: _c_pe.uint32 | None = ..., + CodeRangesToEntryPointsCount: _c_pe.uint32 | None = ..., + RedirectionMetadataCount: _c_pe.uint32 | None = ..., + GetX64InformationFunctionPointer: _c_pe.uint32 | None = ..., + SetX64InformationFunctionPointer: _c_pe.uint32 | None = ..., + ExtraRFETable: _c_pe.uint32 | None = ..., + ExtraRFETableSize: _c_pe.uint32 | None = ..., + __os_arm64x_dispatch_fptr: _c_pe.uint32 | None = ..., + AuxiliaryIATCopy: _c_pe.uint32 | None = ..., + AuxDelayloadIAT: _c_pe.uint32 | None = ..., + AuxDelayloadIATCopy: _c_pe.uint32 | None = ..., + ReservedBitField: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64EC_METADATA_V2: TypeAlias = _IMAGE_ARM64EC_METADATA_V2 + PIMAGE_ARM64EC_METADATA_V2: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM64EC_METADATA_V2] + class _IMAGE_ARM64EC_REDIRECTION_ENTRY(__cs__.Structure): + Source: _c_pe.uint32 + Destination: _c_pe.uint32 + @overload + def __init__(self, Source: _c_pe.uint32 | None = ..., Destination: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64EC_REDIRECTION_ENTRY: TypeAlias = _IMAGE_ARM64EC_REDIRECTION_ENTRY + PIMAGE_ARM64EC_REDIRECTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM64EC_REDIRECTION_ENTRY] + class _IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT(__cs__.Structure): + StartRva: _c_pe.uint32 + EndRva: _c_pe.uint32 + EntryPoint: _c_pe.uint32 + @overload + def __init__( + self, + StartRva: _c_pe.uint32 | None = ..., + EndRva: _c_pe.uint32 | None = ..., + EntryPoint: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT: TypeAlias = _IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT + PIMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT] + class _IMAGE_DVRT_ARM64X_FIXUP_RECORD(__cs__.Structure): + Offset: _c_pe.uint16 + Type: _c_pe.uint16 + Size: _c_pe.uint16 + @overload + def __init__( + self, Offset: _c_pe.uint16 | None = ..., Type: _c_pe.uint16 | None = ..., Size: _c_pe.uint16 | None = ... + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DVRT_ARM64X_FIXUP_RECORD: TypeAlias = _IMAGE_DVRT_ARM64X_FIXUP_RECORD + PIMAGE_DVRT_ARM64X_FIXUP_RECORD: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DVRT_ARM64X_FIXUP_RECORD] + class _IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD(__cs__.Structure): + Offset: _c_pe.uint16 + Type: _c_pe.uint16 + Sign: _c_pe.uint16 + Scale: _c_pe.uint16 + @overload + def __init__( + self, + Offset: _c_pe.uint16 | None = ..., + Type: _c_pe.uint16 | None = ..., + Sign: _c_pe.uint16 | None = ..., + Scale: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD: TypeAlias = _IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD + PIMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DVRT_ARM64X_DELTA_FIXUP_RECORD] + class _IMAGE_HOT_PATCH_INFO(__cs__.Structure): + Version: _c_pe.uint32 + Size: _c_pe.uint32 + SequenceNumber: _c_pe.uint32 + BaseImageList: _c_pe.uint32 + BaseImageCount: _c_pe.uint32 + BufferOffset: _c_pe.uint32 + ExtraPatchSize: _c_pe.uint32 + MinSequenceNumber: _c_pe.uint32 + Flags: _c_pe.uint32 + @overload + def __init__( + self, + Version: _c_pe.uint32 | None = ..., + Size: _c_pe.uint32 | None = ..., + SequenceNumber: _c_pe.uint32 | None = ..., + BaseImageList: _c_pe.uint32 | None = ..., + BaseImageCount: _c_pe.uint32 | None = ..., + BufferOffset: _c_pe.uint32 | None = ..., + ExtraPatchSize: _c_pe.uint32 | None = ..., + MinSequenceNumber: _c_pe.uint32 | None = ..., + Flags: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_HOT_PATCH_INFO: TypeAlias = _IMAGE_HOT_PATCH_INFO + PIMAGE_HOT_PATCH_INFO: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_HOT_PATCH_INFO] + class _IMAGE_HOT_PATCH_BASE(__cs__.Structure): + SequenceNumber: _c_pe.uint32 + Flags: _c_pe.uint32 + OriginalTimeDateStamp: _c_pe.uint32 + OriginalCheckSum: _c_pe.uint32 + CodeIntegrityInfo: _c_pe.uint32 + CodeIntegritySize: _c_pe.uint32 + PatchTable: _c_pe.uint32 + BufferOffset: _c_pe.uint32 + @overload + def __init__( + self, + SequenceNumber: _c_pe.uint32 | None = ..., + Flags: _c_pe.uint32 | None = ..., + OriginalTimeDateStamp: _c_pe.uint32 | None = ..., + OriginalCheckSum: _c_pe.uint32 | None = ..., + CodeIntegrityInfo: _c_pe.uint32 | None = ..., + CodeIntegritySize: _c_pe.uint32 | None = ..., + PatchTable: _c_pe.uint32 | None = ..., + BufferOffset: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_HOT_PATCH_BASE: TypeAlias = _IMAGE_HOT_PATCH_BASE + PIMAGE_HOT_PATCH_BASE: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_HOT_PATCH_BASE] + class _IMAGE_HOT_PATCH_MACHINE(__cs__.Structure): + _x86: _c_pe.uint32 + Amd64: _c_pe.uint32 + Arm64: _c_pe.uint32 + Amd64EC: _c_pe.uint32 + @overload + def __init__( + self, + _x86: _c_pe.uint32 | None = ..., + Amd64: _c_pe.uint32 | None = ..., + Arm64: _c_pe.uint32 | None = ..., + Amd64EC: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_HOT_PATCH_MACHINE: TypeAlias = _IMAGE_HOT_PATCH_MACHINE + PIMAGE_HOT_PATCH_MACHINE: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_HOT_PATCH_MACHINE] + class _IMAGE_HOT_PATCH_HASHES(__cs__.Structure): + SHA256: __cs__.Array[_c_pe.uint8] + SHA1: __cs__.Array[_c_pe.uint8] + @overload + def __init__( + self, SHA256: __cs__.Array[_c_pe.uint8] | None = ..., SHA1: __cs__.Array[_c_pe.uint8] | None = ... + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_HOT_PATCH_HASHES: TypeAlias = _IMAGE_HOT_PATCH_HASHES + PIMAGE_HOT_PATCH_HASHES: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_HOT_PATCH_HASHES] + class IMAGE_HOT_PATCH(__cs__.Enum): + NONE = ... + FUNCTION = ... + ABSOLUTE = ... + REL32 = ... + CALL_TARGET = ... + INDIRECT = ... + NO_CALL_TARGET = ... + DYNAMIC_VALUE = ... + + class _IMAGE_CE_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + FuncStart: _c_pe.uint32 + PrologLen: _c_pe.uint32 + FuncLen: _c_pe.uint32 + ThirtyTwoBit: _c_pe.uint32 + ExceptionFlag: _c_pe.uint32 + @overload + def __init__( + self, + FuncStart: _c_pe.uint32 | None = ..., + PrologLen: _c_pe.uint32 | None = ..., + FuncLen: _c_pe.uint32 | None = ..., + ThirtyTwoBit: _c_pe.uint32 | None = ..., + ExceptionFlag: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_CE_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_CE_RUNTIME_FUNCTION_ENTRY + PIMAGE_CE_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_CE_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint32 + UnwindData: _c_pe.uint32 + Flag: _c_pe.uint32 + FunctionLength: _c_pe.uint32 + Ret: _c_pe.uint32 + H: _c_pe.uint32 + Reg: _c_pe.uint32 + R: _c_pe.uint32 + L: _c_pe.uint32 + C: _c_pe.uint32 + StackAdjust: _c_pe.uint32 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint32 | None = ..., + UnwindData: _c_pe.uint32 | None = ..., + Flag: _c_pe.uint32 | None = ..., + FunctionLength: _c_pe.uint32 | None = ..., + Ret: _c_pe.uint32 | None = ..., + H: _c_pe.uint32 | None = ..., + Reg: _c_pe.uint32 | None = ..., + R: _c_pe.uint32 | None = ..., + L: _c_pe.uint32 | None = ..., + C: _c_pe.uint32 | None = ..., + StackAdjust: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY + PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM_RUNTIME_FUNCTION_ENTRY] + class ARM64_FNPDATA_FLAGS(__cs__.Enum): + PdataRefToFullXdata = ... + PdataPackedUnwindFunction = ... + PdataPackedUnwindFragment = ... + + class ARM64_FNPDATA_CR(__cs__.Enum): + PdataCrUnchained = ... + PdataCrUnchainedSavedLr = ... + PdataCrChainedWithPac = ... + PdataCrChained = ... + + class _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint32 + UnwindData: _c_pe.uint32 + Flag: _c_pe.uint32 + FunctionLength: _c_pe.uint32 + RegF: _c_pe.uint32 + RegI: _c_pe.uint32 + H: _c_pe.uint32 + CR: _c_pe.uint32 + FrameSize: _c_pe.uint32 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint32 | None = ..., + UnwindData: _c_pe.uint32 | None = ..., + Flag: _c_pe.uint32 | None = ..., + FunctionLength: _c_pe.uint32 | None = ..., + RegF: _c_pe.uint32 | None = ..., + RegI: _c_pe.uint32 | None = ..., + H: _c_pe.uint32 | None = ..., + CR: _c_pe.uint32 | None = ..., + FrameSize: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY + PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA(__cs__.Union): + HeaderData: _c_pe.uint32 + FunctionLength: _c_pe.uint32 + Version: _c_pe.uint32 + ExceptionDataPresent: _c_pe.uint32 + EpilogInHeader: _c_pe.uint32 + EpilogCount: _c_pe.uint32 + CodeWords: _c_pe.uint32 + @overload + def __init__( + self, + HeaderData: _c_pe.uint32 | None = ..., + FunctionLength: _c_pe.uint32 | None = ..., + Version: _c_pe.uint32 | None = ..., + ExceptionDataPresent: _c_pe.uint32 | None = ..., + EpilogInHeader: _c_pe.uint32 | None = ..., + EpilogCount: _c_pe.uint32 | None = ..., + CodeWords: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA: TypeAlias = _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA + PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA: TypeAlias = __cs__.Pointer[ + _c_pe._IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA + ] + class IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED(__cs__.Union): + ExtendedHeaderData: _c_pe.uint32 + ExtendedEpilogCount: _c_pe.uint32 + ExtendedCodeWords: _c_pe.uint32 + @overload + def __init__( + self, + ExtendedHeaderData: _c_pe.uint32 | None = ..., + ExtendedEpilogCount: _c_pe.uint32 | None = ..., + ExtendedCodeWords: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED: TypeAlias = __cs__.Pointer[ + _c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EXTENDED + ] + class IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE(__cs__.Union): + EpilogScopeData: _c_pe.uint32 + EpilogStartOffset: _c_pe.uint32 + Res0: _c_pe.uint32 + EpilogStartIndex: _c_pe.uint32 + @overload + def __init__( + self, + EpilogScopeData: _c_pe.uint32 | None = ..., + EpilogStartOffset: _c_pe.uint32 | None = ..., + Res0: _c_pe.uint32 | None = ..., + EpilogStartIndex: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + PIMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE: TypeAlias = __cs__.Pointer[ + _c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA_EPILOG_SCOPE + ] + class _IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint64 + EndAddress: _c_pe.uint64 + ExceptionHandler: _c_pe.uint64 + HandlerData: _c_pe.uint64 + PrologEndAddress: _c_pe.uint64 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint64 | None = ..., + EndAddress: _c_pe.uint64 | None = ..., + ExceptionHandler: _c_pe.uint64 | None = ..., + HandlerData: _c_pe.uint64 | None = ..., + PrologEndAddress: _c_pe.uint64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY + PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint32 + EndAddress: _c_pe.uint32 + ExceptionHandler: _c_pe.uint32 + HandlerData: _c_pe.uint32 + PrologEndAddress: _c_pe.uint32 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint32 | None = ..., + EndAddress: _c_pe.uint32 | None = ..., + ExceptionHandler: _c_pe.uint32 | None = ..., + HandlerData: _c_pe.uint32 | None = ..., + PrologEndAddress: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY + PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint32 + EndAddress: _c_pe.uint32 + ExceptionHandler: _c_pe.uint32 + HandlerData: _c_pe.uint32 + PrologEndAddress: _c_pe.uint32 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint32 | None = ..., + EndAddress: _c_pe.uint32 | None = ..., + ExceptionHandler: _c_pe.uint32 | None = ..., + HandlerData: _c_pe.uint32 | None = ..., + PrologEndAddress: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY + PIMAGE_MIPS_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_RUNTIME_FUNCTION_ENTRY(__cs__.Structure): + BeginAddress: _c_pe.uint32 + EndAddress: _c_pe.uint32 + UnwindInfoAddress: _c_pe.uint32 + UnwindData: _c_pe.uint32 + @overload + def __init__( + self, + BeginAddress: _c_pe.uint32 | None = ..., + EndAddress: _c_pe.uint32 | None = ..., + UnwindInfoAddress: _c_pe.uint32 | None = ..., + UnwindData: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_RUNTIME_FUNCTION_ENTRY: TypeAlias = _IMAGE_RUNTIME_FUNCTION_ENTRY + PIMAGE_RUNTIME_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_RUNTIME_FUNCTION_ENTRY] + class _IMAGE_ENCLAVE_CONFIG32(__cs__.Structure): + Size: _c_pe.uint32 + MinimumRequiredConfigSize: _c_pe.uint32 + PolicyFlags: _c_pe.uint32 + NumberOfImports: _c_pe.uint32 + ImportList: _c_pe.uint32 + ImportEntrySize: _c_pe.uint32 + FamilyID: __cs__.Array[_c_pe.uint8] + ImageID: __cs__.Array[_c_pe.uint8] + ImageVersion: _c_pe.uint32 + SecurityVersion: _c_pe.uint32 + EnclaveSize: _c_pe.uint32 + NumberOfThreads: _c_pe.uint32 + EnclaveFlags: _c_pe.uint32 + @overload + def __init__( + self, + Size: _c_pe.uint32 | None = ..., + MinimumRequiredConfigSize: _c_pe.uint32 | None = ..., + PolicyFlags: _c_pe.uint32 | None = ..., + NumberOfImports: _c_pe.uint32 | None = ..., + ImportList: _c_pe.uint32 | None = ..., + ImportEntrySize: _c_pe.uint32 | None = ..., + FamilyID: __cs__.Array[_c_pe.uint8] | None = ..., + ImageID: __cs__.Array[_c_pe.uint8] | None = ..., + ImageVersion: _c_pe.uint32 | None = ..., + SecurityVersion: _c_pe.uint32 | None = ..., + EnclaveSize: _c_pe.uint32 | None = ..., + NumberOfThreads: _c_pe.uint32 | None = ..., + EnclaveFlags: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ENCLAVE_CONFIG32: TypeAlias = _IMAGE_ENCLAVE_CONFIG32 + PIMAGE_ENCLAVE_CONFIG32: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ENCLAVE_CONFIG32] + class _IMAGE_ENCLAVE_CONFIG64(__cs__.Structure): + Size: _c_pe.uint32 + MinimumRequiredConfigSize: _c_pe.uint32 + PolicyFlags: _c_pe.uint32 + NumberOfImports: _c_pe.uint32 + ImportList: _c_pe.uint32 + ImportEntrySize: _c_pe.uint32 + FamilyID: __cs__.Array[_c_pe.uint8] + ImageID: __cs__.Array[_c_pe.uint8] + ImageVersion: _c_pe.uint32 + SecurityVersion: _c_pe.uint32 + EnclaveSize: _c_pe.uint64 + NumberOfThreads: _c_pe.uint32 + EnclaveFlags: _c_pe.uint32 + @overload + def __init__( + self, + Size: _c_pe.uint32 | None = ..., + MinimumRequiredConfigSize: _c_pe.uint32 | None = ..., + PolicyFlags: _c_pe.uint32 | None = ..., + NumberOfImports: _c_pe.uint32 | None = ..., + ImportList: _c_pe.uint32 | None = ..., + ImportEntrySize: _c_pe.uint32 | None = ..., + FamilyID: __cs__.Array[_c_pe.uint8] | None = ..., + ImageID: __cs__.Array[_c_pe.uint8] | None = ..., + ImageVersion: _c_pe.uint32 | None = ..., + SecurityVersion: _c_pe.uint32 | None = ..., + EnclaveSize: _c_pe.uint64 | None = ..., + NumberOfThreads: _c_pe.uint32 | None = ..., + EnclaveFlags: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ENCLAVE_CONFIG64: TypeAlias = _IMAGE_ENCLAVE_CONFIG64 + PIMAGE_ENCLAVE_CONFIG64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ENCLAVE_CONFIG64] + class _IMAGE_ENCLAVE_IMPORT(__cs__.Structure): + MatchType: _c_pe.uint32 + MinimumSecurityVersion: _c_pe.uint32 + UniqueOrAuthorID: __cs__.Array[_c_pe.uint8] + FamilyID: __cs__.Array[_c_pe.uint8] + ImageID: __cs__.Array[_c_pe.uint8] + ImportName: _c_pe.uint32 + Reserved: _c_pe.uint32 + @overload + def __init__( + self, + MatchType: _c_pe.uint32 | None = ..., + MinimumSecurityVersion: _c_pe.uint32 | None = ..., + UniqueOrAuthorID: __cs__.Array[_c_pe.uint8] | None = ..., + FamilyID: __cs__.Array[_c_pe.uint8] | None = ..., + ImageID: __cs__.Array[_c_pe.uint8] | None = ..., + ImportName: _c_pe.uint32 | None = ..., + Reserved: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ENCLAVE_IMPORT: TypeAlias = _IMAGE_ENCLAVE_IMPORT + PIMAGE_ENCLAVE_IMPORT: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_ENCLAVE_IMPORT] + class WIN_CERT_TYPE(__cs__.Enum): + X509 = ... + PKCS_SIGNED_DATA = ... + RESERVED_1 = ... + TS_STACK_SIGNED = ... + + class _WIN_CERTIFICATE(__cs__.Structure): + dwLength: _c_pe.uint32 + wRevision: _c_pe.uint16 + wCertificateType: _c_pe.WIN_CERT_TYPE + bCertificate: __cs__.CharArray + @overload + def __init__( + self, + dwLength: _c_pe.uint32 | None = ..., + wRevision: _c_pe.uint16 | None = ..., + wCertificateType: _c_pe.WIN_CERT_TYPE | None = ..., + bCertificate: __cs__.CharArray | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + WIN_CERTIFICATE: TypeAlias = _WIN_CERTIFICATE + PWIN_CERTIFICATE: TypeAlias = __cs__.Pointer[_c_pe._WIN_CERTIFICATE] + class IMAGE_DEBUG_TYPE(__cs__.Enum): + UNKNOWN = ... + COFF = ... + CODEVIEW = ... + FPO = ... + MISC = ... + EXCEPTION = ... + FIXUP = ... + OMAP_TO_SRC = ... + OMAP_FROM_SRC = ... + BORLAND = ... + RESERVED10 = ... + BBT = ... + CLSID = ... + VC_FEATURE = ... + POGO = ... + ILTCG = ... + MPX = ... + REPRO = ... + EMBEDDED_PORTABLE_PDB = ... + SPGO = ... + PDBCHECKSUM = ... + EX_DLLCHARACTERISTICS = ... + PERFMAP = ... + + class IMAGE_DLLCHARACTERISTICS_EX(__cs__.Flag): + CET_COMPAT = ... + CET_COMPAT_STRICT_MODE = ... + CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = ... + CET_DYNAMIC_APIS_ALLOW_IN_PROC = ... + CET_RESERVED_1 = ... + CET_RESERVED_2 = ... + FORWARD_CFI_COMPAT = ... + HOTPATCH_COMPATIBLE = ... + + class _IMAGE_DEBUG_DIRECTORY(__cs__.Structure): + Characteristics: _c_pe.uint32 + TimeDateStamp: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + Type: _c_pe.IMAGE_DEBUG_TYPE + SizeOfData: _c_pe.uint32 + AddressOfRawData: _c_pe.uint32 + PointerToRawData: _c_pe.uint32 + @overload + def __init__( + self, + Characteristics: _c_pe.uint32 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + Type: _c_pe.IMAGE_DEBUG_TYPE | None = ..., + SizeOfData: _c_pe.uint32 | None = ..., + AddressOfRawData: _c_pe.uint32 | None = ..., + PointerToRawData: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DEBUG_DIRECTORY: TypeAlias = _IMAGE_DEBUG_DIRECTORY + PIMAGE_DEBUG_DIRECTORY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DEBUG_DIRECTORY] + class _IMAGE_COFF_SYMBOLS_HEADER(__cs__.Structure): + NumberOfSymbols: _c_pe.uint32 + LvaToFirstSymbol: _c_pe.uint32 + NumberOfLinenumbers: _c_pe.uint32 + LvaToFirstLinenumber: _c_pe.uint32 + RvaToFirstByteOfCode: _c_pe.uint32 + RvaToLastByteOfCode: _c_pe.uint32 + RvaToFirstByteOfData: _c_pe.uint32 + RvaToLastByteOfData: _c_pe.uint32 + @overload + def __init__( + self, + NumberOfSymbols: _c_pe.uint32 | None = ..., + LvaToFirstSymbol: _c_pe.uint32 | None = ..., + NumberOfLinenumbers: _c_pe.uint32 | None = ..., + LvaToFirstLinenumber: _c_pe.uint32 | None = ..., + RvaToFirstByteOfCode: _c_pe.uint32 | None = ..., + RvaToLastByteOfCode: _c_pe.uint32 | None = ..., + RvaToFirstByteOfData: _c_pe.uint32 | None = ..., + RvaToLastByteOfData: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_COFF_SYMBOLS_HEADER: TypeAlias = _IMAGE_COFF_SYMBOLS_HEADER + PIMAGE_COFF_SYMBOLS_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_COFF_SYMBOLS_HEADER] + class _CV_HEADER(__cs__.Structure): + Signature: _c_pe.uint32 + Offset: _c_pe.uint32 + @overload + def __init__(self, Signature: _c_pe.uint32 | None = ..., Offset: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + CV_HEADER: TypeAlias = _CV_HEADER + PCV_HEADER: TypeAlias = __cs__.Pointer[_c_pe._CV_HEADER] + class _CV_INFO_PDB20(__cs__.Structure): + CvHeader: _c_pe._CV_HEADER + Signature: _c_pe.uint32 + Age: _c_pe.uint32 + PdbFileName: __cs__.CharArray + @overload + def __init__( + self, + CvHeader: _c_pe._CV_HEADER | None = ..., + Signature: _c_pe.uint32 | None = ..., + Age: _c_pe.uint32 | None = ..., + PdbFileName: __cs__.CharArray | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + CV_INFO_PDB20: TypeAlias = _CV_INFO_PDB20 + PCV_INFO_PDB20: TypeAlias = __cs__.Pointer[_c_pe._CV_INFO_PDB20] + class _CV_INFO_PDB70(__cs__.Structure): + CvSignature: _c_pe.uint32 + Signature: __cs__.CharArray + Age: _c_pe.uint32 + PdbFileName: __cs__.CharArray + @overload + def __init__( + self, + CvSignature: _c_pe.uint32 | None = ..., + Signature: __cs__.CharArray | None = ..., + Age: _c_pe.uint32 | None = ..., + PdbFileName: __cs__.CharArray | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + CV_INFO_PDB70: TypeAlias = _CV_INFO_PDB70 + PCV_INFO_PDB70: TypeAlias = __cs__.Pointer[_c_pe._CV_INFO_PDB70] + class _CV_INFO_MTOC(__cs__.Structure): + CvSignature: _c_pe.uint32 + Signature: __cs__.Array[_c_pe.uint8] + PdbFileName: __cs__.Array[_c_pe.uint8] + @overload + def __init__( + self, + CvSignature: _c_pe.uint32 | None = ..., + Signature: __cs__.Array[_c_pe.uint8] | None = ..., + PdbFileName: __cs__.Array[_c_pe.uint8] | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + CV_INFO_MTOC: TypeAlias = _CV_INFO_MTOC + PCV_INFO_MTOC: TypeAlias = __cs__.Pointer[_c_pe._CV_INFO_MTOC] + class _FPO_DATA(__cs__.Structure): + ulOffStart: _c_pe.uint32 + cbProcSize: _c_pe.uint32 + cdwLocals: _c_pe.uint32 + cdwParams: _c_pe.uint16 + cbProlog: _c_pe.uint16 + cbRegs: _c_pe.uint16 + fHasSEH: _c_pe.uint16 + fUseBP: _c_pe.uint16 + reserved: _c_pe.uint16 + cbFrame: _c_pe.uint16 + @overload + def __init__( + self, + ulOffStart: _c_pe.uint32 | None = ..., + cbProcSize: _c_pe.uint32 | None = ..., + cdwLocals: _c_pe.uint32 | None = ..., + cdwParams: _c_pe.uint16 | None = ..., + cbProlog: _c_pe.uint16 | None = ..., + cbRegs: _c_pe.uint16 | None = ..., + fHasSEH: _c_pe.uint16 | None = ..., + fUseBP: _c_pe.uint16 | None = ..., + reserved: _c_pe.uint16 | None = ..., + cbFrame: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + FPO_DATA: TypeAlias = _FPO_DATA + PFPO_DATA: TypeAlias = __cs__.Pointer[_c_pe._FPO_DATA] + class _IMAGE_DEBUG_MISC(__cs__.Structure): + DataType: _c_pe.uint32 + Length: _c_pe.uint32 + Unicode: _c_pe.uint8 + Reserved: __cs__.Array[_c_pe.uint8] + @overload + def __init__( + self, + DataType: _c_pe.uint32 | None = ..., + Length: _c_pe.uint32 | None = ..., + Unicode: _c_pe.uint8 | None = ..., + Reserved: __cs__.Array[_c_pe.uint8] | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_DEBUG_MISC: TypeAlias = _IMAGE_DEBUG_MISC + PIMAGE_DEBUG_MISC: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_DEBUG_MISC] + class _VC_FEATURE(__cs__.Structure): + PreVC11: _c_pe.uint32 + CCpp: _c_pe.uint32 + Gs: _c_pe.uint32 + Sdl: _c_pe.uint32 + GuardN: _c_pe.uint32 + @overload + def __init__( + self, + PreVC11: _c_pe.uint32 | None = ..., + CCpp: _c_pe.uint32 | None = ..., + Gs: _c_pe.uint32 | None = ..., + Sdl: _c_pe.uint32 | None = ..., + GuardN: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + VC_FEATURE: TypeAlias = _VC_FEATURE + PVC_FEATURE: TypeAlias = __cs__.Pointer[_c_pe._VC_FEATURE] + class _IMAGE_FUNCTION_ENTRY(__cs__.Structure): + StartingAddress: _c_pe.uint32 + EndingAddress: _c_pe.uint32 + EndOfPrologue: _c_pe.uint32 + @overload + def __init__( + self, + StartingAddress: _c_pe.uint32 | None = ..., + EndingAddress: _c_pe.uint32 | None = ..., + EndOfPrologue: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_FUNCTION_ENTRY: TypeAlias = _IMAGE_FUNCTION_ENTRY + PIMAGE_FUNCTION_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_FUNCTION_ENTRY] + class _IMAGE_FUNCTION_ENTRY64(__cs__.Structure): + StartingAddress: _c_pe.uint64 + EndingAddress: _c_pe.uint64 + EndOfPrologue: _c_pe.uint64 + UnwindInfoAddress: _c_pe.uint64 + @overload + def __init__( + self, + StartingAddress: _c_pe.uint64 | None = ..., + EndingAddress: _c_pe.uint64 | None = ..., + EndOfPrologue: _c_pe.uint64 | None = ..., + UnwindInfoAddress: _c_pe.uint64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_FUNCTION_ENTRY64: TypeAlias = _IMAGE_FUNCTION_ENTRY64 + PIMAGE_FUNCTION_ENTRY64: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_FUNCTION_ENTRY64] + class _IMAGE_SEPARATE_DEBUG_HEADER(__cs__.Structure): + Signature: _c_pe.uint16 + Flags: _c_pe.uint16 + Machine: _c_pe.uint16 + Characteristics: _c_pe.uint16 + TimeDateStamp: _c_pe.uint32 + CheckSum: _c_pe.uint32 + ImageBase: _c_pe.uint32 + SizeOfImage: _c_pe.uint32 + NumberOfSections: _c_pe.uint32 + ExportedNamesSize: _c_pe.uint32 + DebugDirectorySize: _c_pe.uint32 + SectionAlignment: _c_pe.uint32 + Reserved: __cs__.Array[_c_pe.uint32] + @overload + def __init__( + self, + Signature: _c_pe.uint16 | None = ..., + Flags: _c_pe.uint16 | None = ..., + Machine: _c_pe.uint16 | None = ..., + Characteristics: _c_pe.uint16 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + CheckSum: _c_pe.uint32 | None = ..., + ImageBase: _c_pe.uint32 | None = ..., + SizeOfImage: _c_pe.uint32 | None = ..., + NumberOfSections: _c_pe.uint32 | None = ..., + ExportedNamesSize: _c_pe.uint32 | None = ..., + DebugDirectorySize: _c_pe.uint32 | None = ..., + SectionAlignment: _c_pe.uint32 | None = ..., + Reserved: __cs__.Array[_c_pe.uint32] | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_SEPARATE_DEBUG_HEADER: TypeAlias = _IMAGE_SEPARATE_DEBUG_HEADER + PIMAGE_SEPARATE_DEBUG_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_SEPARATE_DEBUG_HEADER] + class _NON_PAGED_DEBUG_INFO(__cs__.Structure): + Signature: _c_pe.uint16 + Flags: _c_pe.uint16 + Size: _c_pe.uint32 + Machine: _c_pe.uint16 + Characteristics: _c_pe.uint16 + TimeDateStamp: _c_pe.uint32 + CheckSum: _c_pe.uint32 + SizeOfImage: _c_pe.uint32 + ImageBase: _c_pe.uint64 + @overload + def __init__( + self, + Signature: _c_pe.uint16 | None = ..., + Flags: _c_pe.uint16 | None = ..., + Size: _c_pe.uint32 | None = ..., + Machine: _c_pe.uint16 | None = ..., + Characteristics: _c_pe.uint16 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + CheckSum: _c_pe.uint32 | None = ..., + SizeOfImage: _c_pe.uint32 | None = ..., + ImageBase: _c_pe.uint64 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + NON_PAGED_DEBUG_INFO: TypeAlias = _NON_PAGED_DEBUG_INFO + PNON_PAGED_DEBUG_INFO: TypeAlias = __cs__.Pointer[_c_pe._NON_PAGED_DEBUG_INFO] + class _ImageArchitectureHeader(__cs__.Structure): + AmaskValue: _c_pe.uint32 + _: _c_pe.int32 + AmaskShift: _c_pe.uint32 + FirstEntryRVA: _c_pe.uint32 + @overload + def __init__( + self, + AmaskValue: _c_pe.uint32 | None = ..., + _: _c_pe.int32 | None = ..., + AmaskShift: _c_pe.uint32 | None = ..., + FirstEntryRVA: _c_pe.uint32 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARCHITECTURE_HEADER: TypeAlias = _ImageArchitectureHeader + PIMAGE_ARCHITECTURE_HEADER: TypeAlias = __cs__.Pointer[_c_pe._ImageArchitectureHeader] + class _ImageArchitectureEntry(__cs__.Structure): + FixupInstRVA: _c_pe.uint32 + NewInst: _c_pe.uint32 + @overload + def __init__(self, FixupInstRVA: _c_pe.uint32 | None = ..., NewInst: _c_pe.uint32 | None = ...): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_ARCHITECTURE_ENTRY: TypeAlias = _ImageArchitectureEntry + PIMAGE_ARCHITECTURE_ENTRY: TypeAlias = __cs__.Pointer[_c_pe._ImageArchitectureEntry] + class IMPORT_OBJECT_TYPE(__cs__.Enum): + IMPORT_OBJECT_CODE = ... + IMPORT_OBJECT_DATA = ... + IMPORT_OBJECT_CONST = ... + + class IMPORT_OBJECT_NAME_TYPE(__cs__.Enum): + IMPORT_OBJECT_ORDINAL = ... + IMPORT_OBJECT_NAME = ... + IMPORT_OBJECT_NAME_NO_PREFIX = ... + IMPORT_OBJECT_NAME_UNDECORATE = ... + IMPORT_OBJECT_NAME_EXPORTAS = ... + + class IMPORT_OBJECT_HEADER(__cs__.Structure): + Sig1: _c_pe.uint16 + Sig2: _c_pe.uint16 + Version: _c_pe.uint16 + Machine: _c_pe.uint16 + TimeDateStamp: _c_pe.uint32 + SizeOfData: _c_pe.uint32 + Ordinal: _c_pe.uint16 + Hint: _c_pe.uint16 + Type: _c_pe.IMPORT_OBJECT_TYPE + NameType: _c_pe.IMPORT_OBJECT_NAME_TYPE + Reserved: _c_pe.uint16 + @overload + def __init__( + self, + Sig1: _c_pe.uint16 | None = ..., + Sig2: _c_pe.uint16 | None = ..., + Version: _c_pe.uint16 | None = ..., + Machine: _c_pe.uint16 | None = ..., + TimeDateStamp: _c_pe.uint32 | None = ..., + SizeOfData: _c_pe.uint32 | None = ..., + Ordinal: _c_pe.uint16 | None = ..., + Hint: _c_pe.uint16 | None = ..., + Type: _c_pe.IMPORT_OBJECT_TYPE | None = ..., + NameType: _c_pe.IMPORT_OBJECT_NAME_TYPE | None = ..., + Reserved: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + PIMPORT_OBJECT_HEADER: TypeAlias = __cs__.Pointer[_c_pe.IMPORT_OBJECT_HEADER] + class COMIMAGE_FLAGS(__cs__.Flag): + ILONLY = ... + "32BITREQUIRED = ..." + IL_LIBRARY = ... + STRONGNAMESIGNED = ... + NATIVE_ENTRYPOINT = ... + TRACKDEBUGDATA = ... + "32BITPREFERRED = ..." + + class _IMAGE_COR20_HEADER(__cs__.Structure): + cb: _c_pe.uint32 + MajorRuntimeVersion: _c_pe.uint16 + MinorRuntimeVersion: _c_pe.uint16 + MetaData: _c_pe._IMAGE_DATA_DIRECTORY + Flags: _c_pe.uint32 + EntryPointToken: _c_pe.uint32 + EntryPointRVA: _c_pe.uint32 + Resources: _c_pe._IMAGE_DATA_DIRECTORY + StrongNameSignature: _c_pe._IMAGE_DATA_DIRECTORY + CodeManagerTable: _c_pe._IMAGE_DATA_DIRECTORY + VTableFixups: _c_pe._IMAGE_DATA_DIRECTORY + ExportAddressTableJumps: _c_pe._IMAGE_DATA_DIRECTORY + ManagedNativeHeader: _c_pe._IMAGE_DATA_DIRECTORY + @overload + def __init__( + self, + cb: _c_pe.uint32 | None = ..., + MajorRuntimeVersion: _c_pe.uint16 | None = ..., + MinorRuntimeVersion: _c_pe.uint16 | None = ..., + MetaData: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + Flags: _c_pe.uint32 | None = ..., + EntryPointToken: _c_pe.uint32 | None = ..., + EntryPointRVA: _c_pe.uint32 | None = ..., + Resources: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + StrongNameSignature: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + CodeManagerTable: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + VTableFixups: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + ExportAddressTableJumps: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + ManagedNativeHeader: _c_pe._IMAGE_DATA_DIRECTORY | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_COR20_HEADER: TypeAlias = _IMAGE_COR20_HEADER + PIMAGE_COR20_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_COR20_HEADER] + class _IMAGE_COR20_METADATA(__cs__.Structure): + Magic: _c_pe.uint32 + MajorVersion: _c_pe.uint16 + MinorVersion: _c_pe.uint16 + Reserved: _c_pe.uint32 + Length: _c_pe.uint32 + Version: __cs__.CharArray + Flags: _c_pe.uint16 + NumberOfStreams: _c_pe.uint16 + @overload + def __init__( + self, + Magic: _c_pe.uint32 | None = ..., + MajorVersion: _c_pe.uint16 | None = ..., + MinorVersion: _c_pe.uint16 | None = ..., + Reserved: _c_pe.uint32 | None = ..., + Length: _c_pe.uint32 | None = ..., + Version: __cs__.CharArray | None = ..., + Flags: _c_pe.uint16 | None = ..., + NumberOfStreams: _c_pe.uint16 | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_COR20_METADATA: TypeAlias = _IMAGE_COR20_METADATA + PIMAGE_COR20_METADATA: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_COR20_METADATA] + class _IMAGE_COR20_STREAM_HEADER(__cs__.Structure): + Offset: _c_pe.uint32 + Size: _c_pe.uint32 + Name: __cs__.CharArray + @overload + def __init__( + self, + Offset: _c_pe.uint32 | None = ..., + Size: _c_pe.uint32 | None = ..., + Name: __cs__.CharArray | None = ..., + ): ... + @overload + def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ... + + IMAGE_COR20_STREAM_HEADER: TypeAlias = _IMAGE_COR20_STREAM_HEADER + PIMAGE_COR20_STREAM_HEADER: TypeAlias = __cs__.Pointer[_c_pe._IMAGE_COR20_STREAM_HEADER] + +# Technically `c_pe` is an instance of `_c_pe`, but then we can't use it in type hints +c_pe: TypeAlias = _c_pe diff --git a/dissect/executable/pe/directory/__init__.py b/dissect/executable/pe/directory/__init__.py new file mode 100644 index 0000000..907f6fd --- /dev/null +++ b/dissect/executable/pe/directory/__init__.py @@ -0,0 +1,41 @@ +from dissect.executable.pe.directory.base import DataDirectory +from dissect.executable.pe.directory.basereloc import BaseRelocationDirectory +from dissect.executable.pe.directory.bound_import import BoundImportDirectory +from dissect.executable.pe.directory.com_descriptor import ComDescriptorDirectory +from dissect.executable.pe.directory.debug import DebugDirectory +from dissect.executable.pe.directory.delay_import import DelayImportDirectory +from dissect.executable.pe.directory.exception import ExceptionDirectory +from dissect.executable.pe.directory.export import ExportDirectory +from dissect.executable.pe.directory.iat import IatDirectory +from dissect.executable.pe.directory.imports import ImportDirectory, ImportFunction, ImportModule +from dissect.executable.pe.directory.load_config import LoadConfigDirectory +from dissect.executable.pe.directory.resource import ( + ResourceDataEntry, + ResourceDirectory, + ResourceDirectoryEntry, + ResourceEntry, +) +from dissect.executable.pe.directory.security import SecurityDirectory +from dissect.executable.pe.directory.tls import TlsDirectory + +__all__ = [ + "BaseRelocationDirectory", + "BoundImportDirectory", + "ComDescriptorDirectory", + "DataDirectory", + "DebugDirectory", + "DelayImportDirectory", + "ExceptionDirectory", + "ExportDirectory", + "IatDirectory", + "ImportDirectory", + "ImportFunction", + "ImportModule", + "LoadConfigDirectory", + "ResourceDataEntry", + "ResourceDirectory", + "ResourceDirectoryEntry", + "ResourceEntry", + "SecurityDirectory", + "TlsDirectory", +] diff --git a/dissect/executable/pe/directory/base.py b/dissect/executable/pe/directory/base.py new file mode 100644 index 0000000..4778aa7 --- /dev/null +++ b/dissect/executable/pe/directory/base.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from dissect.executable.pe.pe import PE + + +class DataDirectory: + """Base class for PE data directories.""" + + def __init__(self, pe: PE, address: int, size: int): + self.pe = pe + self.address = address + self.size = size + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} address={self.address:#x} size={self.size}>" diff --git a/dissect/executable/pe/directory/basereloc.py b/dissect/executable/pe/directory/basereloc.py new file mode 100644 index 0000000..fcbacc1 --- /dev/null +++ b/dissect/executable/pe/directory/basereloc.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +from dataclasses import dataclass +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + from collections.abc import Iterator + + +class BaseRelocationDirectory(DataDirectory): + """The base relocation directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__(self) -> Iterator[BaseRelocation]: + return iter(self.entries) + + def __getitem__(self, idx: int) -> BaseRelocation: + return self.entries[idx] + + @cached_property + def entries(self) -> list[BaseRelocation]: + """List of base relocation entries.""" + result = [] + + offset = self.address + while offset < self.address + self.size: + self.pe.vfh.seek(offset) + + block = c_pe._IMAGE_BASE_RELOCATION(self.pe.vfh) + if block.SizeOfBlock == 0: + break + + page_rva = block.VirtualAddress + + num_entries = (block.SizeOfBlock - len(c_pe._IMAGE_BASE_RELOCATION)) // len(c_pe.USHORT) + result.extend( + BaseRelocation(c_pe.IMAGE_REL_BASED(entry >> 12), page_rva + (entry & 0xFFF)) + for entry in c_pe.USHORT[num_entries](self.pe.vfh) + if (entry >> 12) != 0 # Skip IMAGE_REL_BASED_ABSOLUTE (0) + ) + offset += block.SizeOfBlock + offset += -offset & 3 # Align to 4 bytes + + return result + + +@dataclass +class BaseRelocation: + """A single base relocation entry in the base relocation directory.""" + + type: c_pe.IMAGE_REL_BASED + rva: int + + def __repr__(self) -> str: + return f"" diff --git a/dissect/executable/pe/directory/bound_import.py b/dissect/executable/pe/directory/bound_import.py new file mode 100644 index 0000000..ce7f14d --- /dev/null +++ b/dissect/executable/pe/directory/bound_import.py @@ -0,0 +1,114 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + + +class BoundImportDirectory(DataDirectory): + """The bound import directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.modules) + + def __getitem__(self, idx: str | int) -> BoundImportModule: + if isinstance(idx, int): + return self.modules[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Bound import module {idx!r} not found") + return self._by_name[idx] + raise TypeError(f"BoundImportDirectory indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, name: str) -> bool: + if isinstance(name, str): + return name in self._by_name + return False + + @cached_property + def modules(self) -> list[BoundImportModule]: + """List of bound imported modules.""" + result = [] + + self.pe.vfh.seek(self.address) + while self.pe.vfh.tell() < self.address + self.size: + descriptor = c_pe.IMAGE_BOUND_IMPORT_DESCRIPTOR(self.pe.vfh) + if not descriptor: + break + + forwarders = [] + for _ in range(descriptor.NumberOfModuleForwarderRefs): + forwarder = c_pe.IMAGE_BOUND_FORWARDER_REF(self.pe.vfh) + if not forwarder: + break + + forwarders.append(BoundImportForwardReference(self, forwarder)) + + result.append(BoundImportModule(self, descriptor, forwarders)) + + return result + + @cached_property + def _by_name(self) -> dict[str, BoundImportModule]: + """A mapping of module names to their :class:`DelayImportModule`.""" + return {module.name: module for module in self.modules} + + +class BoundImportModule: + """A module bound imported by a PE file, containing its functions.""" + + def __init__( + self, + directory: BoundImportDirectory, + descriptor: c_pe.IMAGE_BOUND_IMPORT_DESCRIPTOR, + forwarders: list[BoundImportForwardReference], + ): + self.directory = directory + self.descriptor = descriptor + self.forwarders = forwarders + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of this bound import module, or ``None`` if the PE file is compiled as reproducible.""" + if self.directory.pe.is_reproducible(): + return None + return from_unix(self.descriptor.TimeDateStamp) + + @property + def name(self) -> str: + self.directory.pe.vfh.seek(self.directory.address + self.descriptor.OffsetModuleName) + return c_pe.CHAR[None](self.directory.pe.vfh).decode() + + +class BoundImportForwardReference: + """A forward reference in a bound import module.""" + + def __init__( + self, + directory: BoundImportDirectory, + descriptor: c_pe.IMAGE_BOUND_FORWARDER_REF, + ): + self.directory = directory + self.descriptor = descriptor + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of this bound import module, or ``None`` if the PE file is compiled as reproducible.""" + if self.directory.pe.is_reproducible(): + return None + return from_unix(self.descriptor.TimeDateStamp) + + @property + def name(self) -> str: + self.directory.pe.vfh.seek(self.directory.address + self.descriptor.OffsetModuleName) + return c_pe.CHAR[None](self.directory.pe.vfh).decode() diff --git a/dissect/executable/pe/directory/com_descriptor.py b/dissect/executable/pe/directory/com_descriptor.py new file mode 100644 index 0000000..21e060a --- /dev/null +++ b/dissect/executable/pe/directory/com_descriptor.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +from functools import cached_property +from typing import BinaryIO + +from dissect.util.stream import RangeStream + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + + +class ComDescriptorDirectory(DataDirectory): + """The COM descriptor directory of a PE file. + + References: + - https://www.codeproject.com/Articles/12585/The-NET-File-Format + """ + + @cached_property + def descriptor(self) -> c_pe.IMAGE_COR20_HEADER: + """The CLR 2.0 header descriptor.""" + self.pe.vfh.seek(self.address) + return c_pe.IMAGE_COR20_HEADER(self.pe.vfh) + + @cached_property + def metadata(self) -> ComMetadata: + """The COM metadata directory.""" + return ComMetadata(self.pe, self.descriptor.MetaData.VirtualAddress, self.descriptor.MetaData.Size) + + +class ComMetadata(DataDirectory): + """The COM metadata directory of the COM descriptor.""" + + @cached_property + def metadata(self) -> c_pe.IMAGE_COR20_METADATA: + """The CLR 2.0 metadata descriptor.""" + self.pe.vfh.seek(self.address) + return c_pe.IMAGE_COR20_METADATA(self.pe.vfh) + + @property + def version(self) -> str: + """The version as defined in the metadata.""" + return self.metadata.Version.decode().strip("\x00") + + @cached_property + def streams(self) -> list[ComStream]: + """A list of streams defined in the metadata.""" + result = [] + + offset = self.address + len(self.metadata) + for _ in range(self.metadata.NumberOfStreams): + self.pe.vfh.seek(offset) + header = c_pe.IMAGE_COR20_STREAM_HEADER(self.pe.vfh) + + result.append(ComStream(self, header.Offset, header.Size, header.Name.decode())) + + offset += len(header) + offset += -offset & 3 # Align to 4 bytes + + return result + + +class ComStream: + """A stream in the COM metadata.""" + + def __init__(self, metadata: ComMetadata, offset: int, size: int, name: str): + self.metadata = metadata + self.offset = offset + self.size = size + self.name = name + + def __repr__(self) -> str: + return f"" + + @property + def data(self) -> bytes: + """The data of the stream.""" + self.metadata.pe.vfh.seek(self.metadata.address + self.offset) + return self.metadata.pe.vfh.read(self.size) + + def open(self) -> BinaryIO: + """Open the stream for reading.""" + return RangeStream(self.metadata.pe.vfh, self.metadata.address + self.offset, self.size) diff --git a/dissect/executable/pe/directory/debug.py b/dissect/executable/pe/directory/debug.py new file mode 100644 index 0000000..da172a3 --- /dev/null +++ b/dissect/executable/pe/directory/debug.py @@ -0,0 +1,244 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING, BinaryIO +from uuid import UUID + +from dissect.util.stream import RangeStream +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + from collections.abc import Iterator + + from dissect.executable.pe.pe import PE + + +class DebugDirectory(DataDirectory): + """The debug directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__(self) -> Iterator[DebugEntry]: + return iter(self.entries) + + def __getitem__(self, idx: int) -> DebugEntry: + return self.entries[idx] + + @cached_property + def entries(self) -> list[DebugEntry]: + """List of debug entries in the debug directory.""" + result = [] + + self.pe.vfh.seek(self.address) + for entry in c_pe.IMAGE_DEBUG_DIRECTORY[self.size // len(c_pe.IMAGE_DEBUG_DIRECTORY)](self.pe.vfh): + cls = _DEBUG_TYPE_MAP.get(entry.Type, DebugEntry) + result.append(cls(self.pe, entry)) + + return result + + +class DebugEntry: + """A single debug entry in the debug directory.""" + + def __init__(self, pe: PE, entry: c_pe.IMAGE_DEBUG_DIRECTORY): + self.pe = pe + self.entry = entry + + def __repr__(self) -> str: + return f"" + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of this debug entry, or ``None`` if the PE file is compiled as reproducible.""" + if self.pe.is_reproducible(): + return None + return from_unix(self.entry.TimeDateStamp) + + @property + def type(self) -> c_pe.IMAGE_DEBUG_TYPE: + """The type of the debug entry.""" + return self.entry.Type + + @property + def size(self) -> int: + """The size of the debug entry.""" + return self.entry.SizeOfData + + @property + def data(self) -> bytes: + """The data of the debug entry.""" + with self.open() as fh: + return fh.read() + + def open(self) -> BinaryIO: + """Return a file-like object to read the debug entry data.""" + if not self.entry.AddressOfRawData: + if self.pe.virtual: + raise ValueError("Cannot access raw data of debug entry because it's not mapped into memory") + + fh = self.pe.fh + address = self.entry.PointerToRawData + else: + fh = self.pe.vfh + address = self.entry.AddressOfRawData + + return RangeStream(fh, address, self.size) + + +class CodeViewDebugEntry(DebugEntry): + """A CodeView debug entry.""" + + def __repr__(self) -> str: + return f"" + + @cached_property + def info(self) -> c_pe.CV_INFO_PDB20 | c_pe.CV_INFO_PDB70 | c_pe.CV_INFO_MTOC: + """The CodeView debug information.""" + with self.open() as fh: + cv_signature = c_pe.ULONG(fh) + fh.seek(0) + + if cv_signature == c_pe.CVINFO_PDB20_CVSIGNATURE: + return c_pe.CV_INFO_PDB20(fh) + + if cv_signature == c_pe.CVINFO_PDB70_CVSIGNATURE: + return c_pe.CV_INFO_PDB70(fh) + + if cv_signature == c_pe.CVINFO_MTOC_CVSIGNATURE: + return c_pe.CV_INFO_MTOC(fh) + + raise ValueError("Not a CodeView debug entry") + + @property + def signature(self) -> UUID | int | None: + """The signature of the CodeView debug entry.""" + if isinstance(self.info, c_pe.CV_INFO_PDB20): + return self.info.Signature + + if isinstance(self.info, (c_pe.CV_INFO_PDB70, c_pe.CV_INFO_MTOC)): + return UUID(bytes_le=self.info.Signature) + + return None + + @property + def age(self) -> int | None: + """The age of the CodeView debug entry.""" + return getattr(self.info, "Age", None) + + @property + def pdb(self) -> str: + """The PDB filename of the CodeView debug entry.""" + return self.info.PdbFileName.decode() + + +class VcFeatureDebugEntry(DebugEntry): + """A VC feature debug entry.""" + + def __repr__(self) -> str: + return f"" # noqa: E501 + + @cached_property + def info(self) -> c_pe.VC_FEATURE: + """The VC feature debug information.""" + with self.open() as fh: + return c_pe.VC_FEATURE(fh) + + @property + def pre_vc11(self) -> int: + """Return the count for ``Pre-VC++ 11.00``.""" + return self.info.PreVC11 + + @property + def ccpp(self) -> int: + """Return the count for ``C/C++``.""" + return self.info.CCpp + + @property + def gs(self) -> int: + """Return the count for ``/GS`` (number of guard stack).""" + return self.info.Gs + + @property + def sdl(self) -> int: + """Return the count for ``/sdl`` (Security Development Lifecycle).""" + return self.info.Sdl + + @property + def guards(self) -> int: + """Return the count for ``/guardN``.""" + return self.info.GuardN + + +class PogoDebugEntry(DebugEntry): + """A POGO debug entry.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__(self) -> Iterator[tuple[int, int, str]]: + return iter(self.entries) + + def __getitem__(self, idx: int) -> tuple[int, int, str]: + return self.entries[idx] + + @cached_property + def entries(self) -> list[tuple[int, int, str]]: + """The POGO debug entries.""" + result = [] + + with self.open() as fh: + signature = c_pe.ULONG(fh) + if signature not in ( + c_pe.IMAGE_DEBUG_POGO_SIGNATURE_ZERO, + c_pe.IMAGE_DEBUG_POGO_SIGNATURE_LTCG, + c_pe.IMAGE_DEBUG_POGO_SIGNATURE_PGU, + ): + raise NotImplementedError(f"Unsupported POGO signature: {signature:#x}") + + offset = fh.tell() + while offset < self.size: + fh.seek(offset) + + rva = c_pe.ULONG(fh) + size = c_pe.ULONG(fh) + label = c_pe.CHAR[None](fh).decode() + + result.append((rva, size, label)) + + offset = fh.tell() + offset += -offset & 3 # Align to 4 bytes + + return result + + +class ReproDebugEntry(DebugEntry): + """A Repro debug entry.""" + + def __repr__(self) -> str: + return f"" + + @property + def hash(self) -> bytes: + """The hash of the Repro debug entry.""" + with self.open() as fh: + hash_size = c_pe.ULONG(fh) + return fh.read(hash_size) + + +_DEBUG_TYPE_MAP: dict[c_pe.IMAGE_DEBUG_TYPE, type[DebugEntry]] = { + c_pe.IMAGE_DEBUG_TYPE.CODEVIEW: CodeViewDebugEntry, + c_pe.IMAGE_DEBUG_TYPE.VC_FEATURE: VcFeatureDebugEntry, + c_pe.IMAGE_DEBUG_TYPE.POGO: PogoDebugEntry, + c_pe.IMAGE_DEBUG_TYPE.REPRO: ReproDebugEntry, +} diff --git a/dissect/executable/pe/directory/delay_import.py b/dissect/executable/pe/directory/delay_import.py new file mode 100644 index 0000000..138e5af --- /dev/null +++ b/dissect/executable/pe/directory/delay_import.py @@ -0,0 +1,176 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + from collections.abc import Iterator + + from dissect.executable.pe.pe import PE + + +class DelayImportDirectory(DataDirectory): + """The delay import directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.modules) + + def __getitem__(self, idx: str | int) -> DelayImportModule: + if isinstance(idx, int): + return self.modules[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Delay import module {idx!r} not found") + return self._by_name[idx] + raise TypeError(f"DelayImportDirectory indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, name: str) -> bool: + if isinstance(name, str): + return name in self._by_name + return False + + @cached_property + def modules(self) -> list[DelayImportModule]: + """List of delay imported modules.""" + self.pe.vfh.seek(self.address) + return [ + DelayImportModule(self.pe, descriptor) for descriptor in c_pe.IMAGE_DELAYLOAD_DESCRIPTOR[None](self.pe.vfh) + ] + + @cached_property + def _by_name(self) -> dict[str, DelayImportModule]: + """A mapping of module names to their :class:`DelayImportModule`.""" + return {module.name: module for module in self.modules} + + +class DelayImportModule: + """A module delay imported by a PE file, containing its functions.""" + + def __init__(self, pe: PE, descriptor: c_pe.IMAGE_DELAYLOAD_DESCRIPTOR): + self.pe = pe + self.descriptor = descriptor + + def __repr__(self) -> str: + return f"" + + def __iter__(self) -> Iterator[DelayImportFunction]: + return iter(self.functions) + + def __getitem__(self, idx: str | int) -> DelayImportFunction: + if isinstance(idx, int): + return self._by_ordinal[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Delay import function {idx!r} not found in module {self.name!r}") + return self._by_name[idx] + raise TypeError(f"DelayImportModule indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, idx: str | int) -> bool: + if isinstance(idx, int): + return idx in self._by_ordinal + if isinstance(idx, str): + return idx in self._by_name + return False + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of the target DLL of this delay import module, or ``None`` if the PE file is + compiled as reproducible. + + Will be ``0`` (so epoch) if it's not bound yet. + """ + if self.pe.is_reproducible(): + return None + return from_unix(self.descriptor.TimeDateStamp) + + @cached_property + def name(self) -> str: + """The name of the delay import module.""" + self.pe.vfh.seek(self.descriptor.DllNameRVA) + return c_pe.CHAR[None](self.pe.vfh).decode() + + @cached_property + def functions(self) -> list[DelayImportFunction]: + """List of delay imported functions from this module.""" + ctype = c_pe.IMAGE_THUNK_DATA64 if self.pe.is_64bit() else c_pe.IMAGE_THUNK_DATA32 + + self.pe.vfh.seek(self.descriptor.ImportNameTableRVA) + name_table = ctype[None](self.pe.vfh) + + self.pe.vfh.seek(self.descriptor.ImportAddressTableRVA) + address_table = ctype[None](self.pe.vfh) + + bound_table = [] + if self.descriptor.BoundImportAddressTableRVA: + self.pe.vfh.seek(self.descriptor.BoundImportAddressTableRVA) + bound_table = ctype[None](self.pe.vfh) + # If we are not bound (e.g. PE file on disk instead of in memory), create an empty table + bound_table = bound_table or [None] * len(name_table) + + unload_table = [] + if self.descriptor.UnloadInformationTableRVA: + self.pe.vfh.seek(self.descriptor.UnloadInformationTableRVA) + unload_table = ctype[None](self.pe.vfh) + # If we are not unloading (e.g. PE file on disk instead of in memory), create an empty table + unload_table = unload_table or [None] * len(name_table) + + return [ + DelayImportFunction(self, name_thunk, address_thunk, bound_thunk, unload_thunk) + for name_thunk, address_thunk, bound_thunk, unload_thunk in zip( + name_table, address_table, bound_table, unload_table + ) + ] + + @cached_property + def _by_name(self) -> dict[str, DelayImportFunction]: + """A mapping of imported function names to their :class:`DelayImportFunction`.""" + return {func.name: func for func in self.functions if func.name is not None} + + @cached_property + def _by_ordinal(self) -> dict[int, DelayImportFunction]: + """A mapping of function ordinals to their :class:`DelayImportFunction`.""" + return {func.ordinal: func for func in self.functions} + + +class DelayImportFunction: + """A function delay imported from a module.""" + + def __init__( + self, + module: DelayImportModule, + name_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64, + address_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64, + bound_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64 | None = None, + unload_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64 | None = None, + ): + self.module = module + self.name_thunk = name_thunk + self.address_thunk = address_thunk + + if name_thunk.u1.Ordinal & (c_pe.IMAGE_ORDINAL_FLAG64 if module.pe.is_64bit() else c_pe.IMAGE_ORDINAL_FLAG32): + self.ordinal = name_thunk.u1.Ordinal & 0xFFFF + self.name = None + else: + self.module.pe.vfh.seek(name_thunk.u1.AddressOfData & (c_pe.IMAGE_ORDINAL_FLAG32 - 1)) + import_by_name = c_pe.IMAGE_IMPORT_BY_NAME(self.module.pe.vfh) + self.ordinal = import_by_name.Hint + self.name = import_by_name.Name.decode() + + self.address = address_thunk.u1.Function + self.bound_address = bound_thunk.u1.Function if bound_thunk else None + self.unload_address = unload_thunk.u1.Function if unload_thunk else None + + def __repr__(self) -> str: + address = hex(self.address) if self.address is not None else "None" + bound_address = hex(self.bound_address) if self.bound_address is not None else "None" + unload_address = hex(self.unload_address) if self.unload_address is not None else "None" + return f"" # noqa: E501 diff --git a/dissect/executable/pe/directory/exception.py b/dissect/executable/pe/directory/exception.py new file mode 100644 index 0000000..6b28b62 --- /dev/null +++ b/dissect/executable/pe/directory/exception.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + from collections.abc import Iterator + + +class ExceptionDirectory(DataDirectory): + """The exception directory of a PE file. + + Currently only shows the raw exception entries. + """ + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__( + self, + ) -> Iterator[ + c_pe.IMAGE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_CE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY + ]: + return iter(self.entries) + + def __getitem__( + self, idx: int + ) -> ( + c_pe.IMAGE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_CE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY + ): + return self.entries[idx] + + @cached_property + def entries( + self, + ) -> list[ + c_pe.IMAGE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_CE_RUNTIME_FUNCTION_ENTRY + | c_pe.IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY + ]: + """List of exception entries.""" + self.pe.vfh.seek(self.address) + + machine = self.pe.machine + if machine in (c_pe.IMAGE_FILE_MACHINE.ARM, c_pe.IMAGE_FILE_MACHINE.THUMB, c_pe.IMAGE_FILE_MACHINE.ARMNT): + ctype = c_pe.IMAGE_ARM_RUNTIME_FUNCTION_ENTRY + elif machine == c_pe.IMAGE_FILE_MACHINE.ARM64: + ctype = c_pe.IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY + elif machine == c_pe.IMAGE_FILE_MACHINE.ALPHA: + ctype = c_pe.IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY + elif machine == c_pe.IMAGE_FILE_MACHINE.ALPHA64: + ctype = c_pe.IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY + elif machine in ( + c_pe.IMAGE_FILE_MACHINE.R3000, + c_pe.IMAGE_FILE_MACHINE.R4000, + c_pe.IMAGE_FILE_MACHINE.R10000, + c_pe.IMAGE_FILE_MACHINE.WCEMIPSV2, + c_pe.IMAGE_FILE_MACHINE.MIPS16, + c_pe.IMAGE_FILE_MACHINE.MIPSFPU, + c_pe.IMAGE_FILE_MACHINE.MIPSFPU16, + ): + ctype = c_pe.IMAGE_MIPS_RUNTIME_FUNCTION_ENTRY + else: + # May be wrong for esoteric architectures, but this is the default + ctype = c_pe.IMAGE_RUNTIME_FUNCTION_ENTRY + + return ctype[self.size // len(ctype)](self.pe.vfh) diff --git a/dissect/executable/pe/directory/export.py b/dissect/executable/pe/directory/export.py new file mode 100644 index 0000000..3bd4762 --- /dev/null +++ b/dissect/executable/pe/directory/export.py @@ -0,0 +1,128 @@ +from __future__ import annotations + +from dataclasses import dataclass +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + from collections.abc import Iterator + + +class ExportDirectory(DataDirectory): + """The export directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __iter__(self) -> Iterator[ExportFunction]: + return iter(self.functions) + + def __getitem__(self, idx: str | int) -> ExportFunction: + if isinstance(idx, int): + return self._by_ordinal[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Export function {idx!r} not found in directory {self.name!r}") + return self._by_name[idx] + raise TypeError(f"ImportModule indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, idx: str | int) -> bool: + if isinstance(idx, int): + return idx in self._by_ordinal + if isinstance(idx, str): + return idx in self._by_name + return False + + @cached_property + def header(self) -> c_pe.IMAGE_EXPORT_DIRECTORY: + """The export directory header.""" + self.pe.vfh.seek(self.address) + return c_pe.IMAGE_EXPORT_DIRECTORY(self.pe.vfh) + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of the export directory, or ``None`` if the PE file is compiled as reproducible.""" + if self.pe.is_reproducible(): + return None + return from_unix(self.header.TimeDateStamp) + + @cached_property + def name(self) -> str | None: + """The name of the export directory, if available.""" + if self.header.Name: + self.pe.vfh.seek(self.header.Name) + return c_pe.char[None](self.pe.vfh).decode() + return None + + @property + def base(self) -> int: + """The base ordinal of the exported functions.""" + return self.header.Base + + @cached_property + def functions(self) -> list[ExportFunction]: + """List of exported functions.""" + result = [] + + self.pe.vfh.seek(self.header.AddressOfFunctions) + addresses = c_pe.ULONG[self.header.NumberOfFunctions](self.pe.vfh) + + self.pe.vfh.seek(self.header.AddressOfNames) + names = c_pe.ULONG[self.header.NumberOfNames](self.pe.vfh) + + self.pe.vfh.seek(self.header.AddressOfNameOrdinals) + ordinals = c_pe.USHORT[self.header.NumberOfNames](self.pe.vfh) + + for name_ptr, ordinal in zip(names, ordinals): + self.pe.vfh.seek(name_ptr) + name = c_pe.CHAR[None](self.pe.vfh).decode() + + address = addresses[ordinal] + forwarder = None + if self.address <= address < self.address + self.size: + self.pe.vfh.seek(address) + forwarder = c_pe.CHAR[None](self.pe.vfh).decode() + + result.append(ExportFunction(self, ordinal, name, address, forwarder)) + + return result + + @cached_property + def _by_name(self) -> dict[str, ExportFunction]: + """A mapping of exported function names to their :class:`ExportFunction`.""" + return {func.name: func for func in self.functions} + + @cached_property + def _by_ordinal(self) -> dict[int, ExportFunction]: + """A mapping of exported function ordinals to their :class:`ExportFunction`.""" + return {func.ordinal: func for func in self.functions} + + +@dataclass +class ExportFunction: + directory: ExportDirectory + """The export directory this function belongs to.""" + unbiased_ordinal: int + """The unbiased ordinal of the exported function.""" + name: str + """The name of the exported function.""" + address: int + """The address of the exported function.""" + forwarder: str | None = None + """The forwarder of the exported function, if it is a forwarder.""" + + def __repr__(self) -> str: + if self.forwarder: + return f"" + return f"" + + @property + def ordinal(self) -> int: + """The unbiased ordinal with the base ordinal added.""" + return self.unbiased_ordinal + self.directory.base diff --git a/dissect/executable/pe/directory/iat.py b/dissect/executable/pe/directory/iat.py new file mode 100644 index 0000000..5a2bc78 --- /dev/null +++ b/dissect/executable/pe/directory/iat.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + from collections.abc import Iterator + + +class IatDirectory(DataDirectory): + """The import address table (IAT) directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__(self) -> Iterator[int]: + return iter(self.entries) + + def __getitem__(self, idx: int) -> int: + return self.entries[idx] + + @cached_property + def entries(self) -> list[int]: + """List of addresses in the import address table.""" + self.pe.vfh.seek(self.address) + ctype = c_pe.ULONGLONG if self.pe.is_64bit() else c_pe.ULONG + return ctype[self.size // len(ctype)](self.pe.vfh) diff --git a/dissect/executable/pe/directory/imports.py b/dissect/executable/pe/directory/imports.py new file mode 100644 index 0000000..cde895d --- /dev/null +++ b/dissect/executable/pe/directory/imports.py @@ -0,0 +1,151 @@ +# `import` is a reserved keyword in Python, so we can't name this file `import.py` +# Doorn in mijn oog + +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + from collections.abc import Iterator + + from dissect.executable.pe.pe import PE + + +class ImportDirectory(DataDirectory): + """The import directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.modules) + + def __getitem__(self, idx: str | int) -> ImportModule: + if isinstance(idx, int): + return self.modules[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Import module {idx!r} not found") + return self._by_name[idx] + raise TypeError(f"ImportDirectory indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, name: str) -> bool: + if isinstance(name, str): + return name in self._by_name + return False + + @cached_property + def modules(self) -> list[ImportModule]: + """List of imported modules.""" + self.pe.vfh.seek(self.address) + return [ImportModule(self.pe, descriptor) for descriptor in c_pe.IMAGE_IMPORT_DESCRIPTOR[None](self.pe.vfh)] + + @cached_property + def _by_name(self) -> dict[str, ImportModule]: + """A mapping of module names to their :class:`ImportModule`.""" + return {module.name: module for module in self.modules} + + +class ImportModule: + """A module imported by a PE file, containing its functions.""" + + def __init__(self, pe: PE, descriptor: c_pe.IMAGE_IMPORT_DESCRIPTOR): + self.pe = pe + self.descriptor = descriptor + + def __repr__(self) -> str: + return f"" + + def __iter__(self) -> Iterator[ImportFunction]: + return iter(self.functions) + + def __getitem__(self, idx: str | int) -> ImportFunction: + if isinstance(idx, int): + return self._by_ordinal[idx] + if isinstance(idx, str): + if idx not in self._by_name: + raise KeyError(f"Import function {idx!r} not found in module {self.name!r}") + return self._by_name[idx] + raise TypeError(f"ImportModule indices must be str or int, not {type(idx).__name__}") + + def __contains__(self, idx: str | int) -> bool: + if isinstance(idx, int): + return idx in self._by_ordinal + if isinstance(idx, str): + return idx in self._by_name + return False + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of this import module, or ``None`` if the PE file is compiled as reproducible.""" + if self.pe.is_reproducible(): + return None + return from_unix(self.descriptor.TimeDateStamp) + + @cached_property + def name(self) -> str: + """The name of the imported module.""" + self.pe.vfh.seek(self.descriptor.Name) + return c_pe.char[None](self.pe.vfh).decode() + + @cached_property + def functions(self) -> list[ImportFunction]: + """List of functions imported from this module.""" + ctype = c_pe.IMAGE_THUNK_DATA64 if self.pe.is_64bit() else c_pe.IMAGE_THUNK_DATA32 + + self.pe.vfh.seek(self.descriptor.OriginalFirstThunk) + lookup_table = ctype[None](self.pe.vfh) + + self.pe.vfh.seek(self.descriptor.FirstThunk) + address_table = ctype[None](self.pe.vfh) + + return [ + ImportFunction(self, lookup_thunk, address_thunk) + for lookup_thunk, address_thunk in zip(lookup_table, address_table) + ] + + @cached_property + def _by_name(self) -> dict[str, ImportFunction]: + """A mapping of imported function names to their :class:`ImportFunction`.""" + return {func.name: func for func in self.functions if func.name is not None} + + @cached_property + def _by_ordinal(self) -> dict[int, ImportFunction]: + """A mapping of imported function ordinals to their :class:`ImportFunction`.""" + return {func.ordinal: func for func in self.functions} + + +class ImportFunction: + """A function imported from a module.""" + + def __init__( + self, + module: ImportModule, + lookup_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64, + address_thunk: c_pe.IMAGE_THUNK_DATA32 | c_pe.IMAGE_THUNK_DATA64, + ): + self.module = module + self.lookup_thunk = lookup_thunk + self.address_thunk = address_thunk + + if lookup_thunk.u1.Ordinal & (c_pe.IMAGE_ORDINAL_FLAG64 if module.pe.is_64bit() else c_pe.IMAGE_ORDINAL_FLAG32): + self.ordinal = lookup_thunk.u1.Ordinal & 0xFFFF + self.name = None + else: + self.module.pe.vfh.seek(lookup_thunk.u1.AddressOfData & (c_pe.IMAGE_ORDINAL_FLAG32 - 1)) + import_by_name = c_pe.IMAGE_IMPORT_BY_NAME(self.module.pe.vfh) + self.ordinal = import_by_name.Hint + self.name = import_by_name.Name.decode() + + self.address = address_thunk.u1.Function if lookup_thunk.u1.Function != address_thunk.u1.Function else None + + def __repr__(self) -> str: + address = hex(self.address) if self.address is not None else "None" + return f"" diff --git a/dissect/executable/pe/directory/load_config.py b/dissect/executable/pe/directory/load_config.py new file mode 100644 index 0000000..861d3ac --- /dev/null +++ b/dissect/executable/pe/directory/load_config.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.util.ts import from_unix + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + import datetime + + +class LoadConfigDirectory(DataDirectory): + """The load configuration directory of a PE file.""" + + @cached_property + def config(self) -> c_pe.IMAGE_LOAD_CONFIG_DIRECTORY32 | c_pe.IMAGE_LOAD_CONFIG_DIRECTORY64: + """The load configuration directory header.""" + self.pe.vfh.seek(self.address) + ctype = c_pe.IMAGE_LOAD_CONFIG_DIRECTORY64 if self.pe.is_64bit() else c_pe.IMAGE_LOAD_CONFIG_DIRECTORY32 + return ctype(self.pe.vfh) + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of the load configuration directory, or ``None`` if the PE file is compiled as reproducible.""" + if self.pe.is_reproducible(): + return None + return from_unix(self.config.TimeDateStamp) + + @property + def security_cookie(self) -> int: + """The security cookie address.""" + return self.config.SecurityCookie + + @property + def guard_flags(self) -> c_pe.IMAGE_GUARD: + """The guard flags.""" + return self.config.GuardFlags & ~c_pe.IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK + + @property + def chpe( + self, + ) -> c_pe.IMAGE_ARM64EC_METADATA | c_pe.IMAGE_ARM64EC_METADATA_V2 | c_pe.IMAGE_CHPE_METADATA_X86 | None: + """The CHPE (Compiled Hybrid Portable Executable) metadata.""" + if not self.config.CHPEMetadataPointer: + return None + + rva = self.pe.va_to_rva(self.config.CHPEMetadataPointer) + self.pe.vfh.seek(rva) + if self.pe.machine == c_pe.IMAGE_FILE_MACHINE.ARM64: + version = c_pe.ULONG(self.pe.vfh) + self.pe.vfh.seek(rva) + if version == 2: + return c_pe.IMAGE_ARM64EC_METADATA_V2(self.pe.vfh) + return c_pe.IMAGE_ARM64EC_METADATA(self.pe.vfh) + return c_pe.IMAGE_CHPE_METADATA_X86(self.pe.vfh) diff --git a/dissect/executable/pe/directory/resource.py b/dissect/executable/pe/directory/resource.py new file mode 100644 index 0000000..61d4fef --- /dev/null +++ b/dissect/executable/pe/directory/resource.py @@ -0,0 +1,589 @@ +from __future__ import annotations + +from functools import cached_property +from io import BytesIO +from typing import TYPE_CHECKING, Any, BinaryIO, Union + +from dissect.util.ts import from_unix, wintimestamp + +try: + from typing import TypeAlias # novermin +except ImportError: + # COMPAT: Remove this when we drop Python 3.9 + TypeAlias = Any + + +from dissect.util.stream import RangeStream + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory +from dissect.executable.pe.locale_id import CP_TO_NAME, LCID_TO_TAG, TAG_TO_LCID + +if TYPE_CHECKING: + import datetime + from collections.abc import Iterator + + from dissect.executable.pe.pe import PE + + +class ResourceDirectory(DataDirectory): + """The resource directory of a PE file. + + This class provides a higher-level interface to access resources in a PE file. If you wish to access + the raw resource directory structure, you can traverse it with the ``tree`` attribute. + """ + + def __init__(self, pe: PE, address: int, size: int): + super().__init__(pe, address, size) + self.tree = ResourceDirectoryEntry(self, address) + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.resources) + + def __iter__(self) -> Iterator[Resource]: + return iter(self.resources) + + def __getitem__(self, idx: int | str | c_pe.RT) -> list[Resource] | None: + """Get a resource by index or type. + + Args: + idx: The index of the resource to get, which can be an integer, a string (resource type name), + or a member of the ``c_pe.RT`` enum. Integers refer to the index in the resources list, + while strings and enum members refer to the resource type. + """ + if isinstance(idx, int): + return self.resources[idx] + + if isinstance(idx, (str, c_pe.RT)): + return self.get(idx) + + raise TypeError(f"ResourceDirectory indices must be int, str or RT enum members, not {type(idx).__name__}") + + def __contains__(self, idx: str | c_pe.RT) -> bool: + if isinstance(idx, (str, c_pe.RT)): + return self.get(idx) is not None + + return False + + def get(self, type: int | str | c_pe.RT) -> list[Resource] | None: + """Get all resources of a specific type. + + Args: + type: The type of the resource (e.g. ``c_pe.RT.ICON``). + Integers can also be used to refer to resource types by their numeric value, + or strings to refer to resource types by their name. + """ + if isinstance(type, int): + type = c_pe.RT(type) + + if isinstance(type, str) and type in c_pe.RT.__members__: + type = c_pe.RT[type] + + if (root := self.tree.get(type)) is None: + return None + + return [Resource(type, name, entry) for name, entry in root.iterdir()] + + def find(self, type: int | str | c_pe.RT, name: str | int) -> Resource | None: + """Find a specific resource by type and name. + + Args: + type: The type of the resource (e.g. ``c_pe.RT.ICON``). + Integers can also be used to refer to resource types by their numeric value, + or strings to refer to resource types by their name. + name: The name of the resource, which can be a string or an integer ID. + """ + if isinstance(type, int): + type = c_pe.RT(type) + + if isinstance(type, str) and type in c_pe.RT.__members__: + type = c_pe.RT[type] + + if (root := self.tree.get(type)) is None: + return None + + if isinstance(name, str): + name = TAG_TO_LCID.get(name, name) + + if isinstance(name, (int, c_pe.RT)) and (entry := root.get(name)) is not None: + return Resource(type, name, entry) + + raise KeyError(f"Resource with type {type.name!r} and name {name!r} not found") + + @cached_property + def resources(self) -> list[Resource]: + """Return a list of all resources.""" + result = [] + + for type, type_entry in self.tree.iterdir(): + for name, entry in type_entry.iterdir(): + result.append(Resource(c_pe.RT(type) if isinstance(type, int) else type, name, entry)) + + return result + + @property + def cursor(self) -> list[Resource] | None: + """Return a list of hardware-dependent cursor resources, if available.""" + return self.get(c_pe.RT.CURSOR) + + @property + def bitmap(self) -> list[Resource] | None: + """Return a list of bitmap resources, if available.""" + return self.get(c_pe.RT.BITMAP) + + @property + def icon(self) -> list[Resource] | None: + """Return a list of hardware-dependent icon resources, if available.""" + return self.get(c_pe.RT.ICON) + + @property + def menu(self) -> list[Resource] | None: + """Return a list of menu resources, if available.""" + return self.get(c_pe.RT.MENU) + + @property + def dialog(self) -> list[Resource] | None: + """Return a list of dialog box resources, if available.""" + return self.get(c_pe.RT.DIALOG) + + @property + def string(self) -> list[Resource] | None: + """Return a list of string table resources, if available.""" + return self.get(c_pe.RT.STRING) + + def string_table(self, language: str | int | None = None) -> dict[int, str]: + """Return the parsed string table for a specific language. + + Args: + language: The language of the string table to return. + If ``None``, the first available language is used. + """ + result = {} + + if isinstance(language, str): + language = TAG_TO_LCID.get(language, language) + + root = self.tree.get(c_pe.RT.STRING) + + for id, resource in root.iterdir(): + idx = (id - 1) * 16 + entry = next(resource.iterdir())[1] if language is None else resource.get(language) + + with entry.open() as fh: + while fh.tell() != entry.size: + if length := c_pe.USHORT(fh): + result[idx] = fh.read(length * 2).decode("utf-16-le") + idx += 1 + + return result + + @property + def fontdir(self) -> list[Resource] | None: + """Return a list of font directory resources, if available.""" + return self.get(c_pe.RT.FONTDIR) + + @property + def font(self) -> list[Resource] | None: + """Return a list of font resources, if available.""" + return self.get(c_pe.RT.FONT) + + @property + def accelerator(self) -> list[Resource] | None: + """Return a list of accelerator table resources, if available.""" + return self.get(c_pe.RT.ACCELERATOR) + + def accelerator_table(self, language: str | int | None = None) -> dict[int, str]: + """Return the parsed accelerator table for a specific language. + + Args: + language: The language of the version information to return. + If ``None``, the first available language is used. + """ + result = [] + + if isinstance(language, str): + language = TAG_TO_LCID.get(language, language) + + for accelerator in self.accelerator or []: + with accelerator.open(language) as fh: + last_found = False + while not last_found: + try: + key_flags = c_pe.ULONG(fh) + modifiers = c_pe.ACCEL_F(key_flags & 0xFFFF) + key = c_pe.VK(key_flags >> 16) + cmd = c_pe.ULONG(fh) + + if c_pe.ACCEL_F.LASTKEY in modifiers: + last_found = True + modifiers &= ~c_pe.ACCEL_F.LASTKEY + + result.append((key, cmd & 0xFFFF, modifiers)) + except EOFError: # noqa: PERF203 + break + + return result + + @property + def rcdata(self) -> list[Resource] | None: + """Return a list of application-defined (raw data) resources, if available.""" + return self.get(c_pe.RT.RCDATA) + + @property + def message_table(self) -> list[Resource] | None: + """Return a list of message table resources, if available.""" + return self.get(c_pe.RT.MESSAGETABLE) + + @property + def group_cursor(self) -> list[Resource] | None: + """Return a list of hardware-independent group cursor resources, if available.""" + return self.get(c_pe.RT.GROUP_CURSOR) + + @property + def group_icon(self) -> list[Resource] | None: + """Return a list of hardware-independent group icon resources, if available.""" + return self.get(c_pe.RT.GROUP_ICON) + + @property + def version(self) -> list[Resource] | None: + """Return a list of version resources, if available.""" + return self.get(c_pe.RT.VERSION) + + def vs_version_info(self, language: str | int | None = None) -> dict | None: + """Return the parsed version information for a specific language. + + Args: + language: The language of the version information to return. + If ``None``, the first available language is used. + """ + if isinstance(language, str): + language = TAG_TO_LCID.get(language, language) + + if not (version := self.get(c_pe.RT.VERSION)): + return None + + if len(version) != 1: + raise ValueError(f"Expected exactly one version resource, found {len(version)}") + + _Node: TypeAlias = tuple[str, Union[str, bytes, None], list["_Node"]] + + def _parse_lvt(fh: BinaryIO) -> _Node | None: + start = fh.tell() + length = c_pe.USHORT(fh) + if length == 0: + return None + + value_length = c_pe.USHORT(fh) + value_type = c_pe.USHORT(fh) + + key = c_pe.WCHAR[None](fh).rstrip("\x00") + fh.seek(fh.tell() + (-fh.tell() & 3)) # Align to 4 bytes + value = None + if value_length: + value = ( + fh.read(value_length * 2).decode("utf-16-le").rstrip("\x00") + if value_type == 1 + else fh.read(value_length) + ) + fh.seek(fh.tell() + (-fh.tell() & 3)) # Align to 4 bytes + + children = [] + while fh.tell() - start < length: + if (child := _parse_lvt(fh)) is None: + break + children.append(child) + + return key, value, children + + def _build_dict(node: _Node, obj: dict[str, Any]) -> None: + key, value, children = node + + if key == "VS_VERSION_INFO": + # Special case for VS_VERSION_INFO, which is a top-level key + obj[key] = {} + file_info = c_pe.VS_FIXEDFILEINFO(value.ljust(len(c_pe.VS_FIXEDFILEINFO), b"\x00")) + if file_info.dwSignature != 0xFEEF04BD: + raise ValueError("Invalid VS_FIXEDFILEINFO signature") + + if file_info.dwFileVersionMS or file_info.dwFileVersionLS: + obj[key]["FileVersion"] = ( + f"{file_info.dwFileVersionMS >> 16}.{file_info.dwFileVersionMS & 0xFFFF}.{file_info.dwFileVersionLS >> 16}.{file_info.dwFileVersionLS & 0xFFFF}" # noqa: E501 + ) + + if file_info.dwProductVersionMS or file_info.dwProductVersionLS: + obj[key]["ProductVersion"] = ( + f"{file_info.dwProductVersionMS >> 16}.{file_info.dwProductVersionMS & 0xFFFF}.{file_info.dwProductVersionLS >> 16}.{file_info.dwProductVersionLS & 0xFFFF}" # noqa: E501 + ) + + if file_info.dwFileFlags: + obj[key]["FileFlags"] = c_pe.VS_FF(file_info.dwFileFlags & file_info.dwFileFlagsMask).name + + if file_info.dwFileOS: + upper_file_os = file_info.dwFileOS & 0xFFFF0000 + lower_file_os = file_info.dwFileOS & 0x0000FFFF + obj[key]["FileOS"] = "_".join( + c_pe.VOS(x).name for x in filter(None, [upper_file_os, lower_file_os]) + ) + + if file_info.dwFileType: + obj[key]["FileType"] = c_pe.VFT(file_info.dwFileType).name + + if file_info.dwFileSubtype: + if file_info.dwFileType == c_pe.VFT.DRV: + obj[key]["FileSubtype"] = c_pe.VFT2_DRV(file_info.dwFileSubtype).name + elif file_info.dwFileType == c_pe.VFT.FONT: + obj[key]["FileSubtype"] = c_pe.VFT2_FONT(file_info.dwFileSubtype).name + else: + obj[key]["FileSubtype"] = file_info.dwFileSubtype + + if file_info.dwFileDateMS or file_info.dwFileDateLS: + obj[key]["FileDate"] = wintimestamp(file_info.dwFileDateMS << 32 | file_info.dwFileDateLS) + else: + if value is not None: + obj[key] = value + else: + obj[key] = {} + + for child in children: + _build_dict(child, obj[key]) + + result = {} + with version[0].open(language) as fh: + _build_dict(_parse_lvt(fh), result) + + if sfi := result.get("VS_VERSION_INFO", {}).get("StringFileInfo", {}): + keys = list(sfi.keys()) + for key in keys: + lcid = int(key[:4], 16) + codepage = int(key[4:], 16) + sfi[f"{LCID_TO_TAG.get(lcid, str(lcid))}_{CP_TO_NAME.get(codepage, str(codepage))}"] = sfi[key] + del sfi[key] + + if (vfit := result.get("VS_VERSION_INFO", {}).get("VarFileInfo", {})) and "Translation" in vfit: + buf = BytesIO(vfit["Translation"]) + tmp = [] + for _ in range(len(vfit["Translation"]) // 4): + lcid, codepage = c_pe.USHORT[2](buf) + tmp.append(f"{LCID_TO_TAG.get(lcid, str(lcid))}_{CP_TO_NAME.get(codepage, str(codepage))}") + vfit["Translation"] = tmp + + return result + + @property + def dialog_include(self) -> list[Resource] | None: + """Return a list of dialog include resources, if available.""" + return self.get(c_pe.RT.DLGINCLUDE) + + @property + def plug_and_play(self) -> list[Resource] | None: + """Return a list of plug and play resources, if available.""" + return self.get(c_pe.RT.PLUGPLAY) + + @property + def vxd(self) -> list[Resource] | None: + """Return a list of VXD resources, if available.""" + return self.get(c_pe.RT.VXD) + + @property + def animated_cursor(self) -> list[Resource] | None: + """Return a list of animated cursor resources, if available.""" + return self.get(c_pe.RT.ANICURSOR) + + @property + def animated_icon(self) -> list[Resource] | None: + """Return a list of animated icon resources, if available.""" + return self.get(c_pe.RT.ANIICON) + + @property + def html(self) -> list[Resource] | None: + """Return a list of HTML resources, if available.""" + return self.get(c_pe.RT.HTML) + + @property + def manifest(self) -> list[Resource] | None: + """Return a list of side-by-side assembly manifest resources, if available.""" + return self.get(c_pe.RT.MANIFEST) + + +class Resource: + """Higher level representation of a resource in a PE file. + + This class provides a convenient interface to access resource data, abstracting away the details of the + underlying resource directory structure. + + Args: + type: The type of the resource (e.g. ``c_pe.RT.ICON``). + name: The name of the resource, which can be a string or an integer ID. + entry: The resource directory entry that contains the resource data per language. + """ + + def __init__(self, type: c_pe.RT | str, name: str | int, entry: ResourceDirectoryEntry): + self.type = type + self.name = name + self.entry = entry + + def __repr__(self) -> str: + return f"" + + def __iter__(self) -> Iterator[Resource]: + return self.entry.iterdir() + + def __getitem__(self, idx: int | str) -> ResourceDataEntry: + """Get a specific resource data entry by language. + + Args: + idx: The index of the resource data entry, which can be an integer (LCID) or a string (language tag). + """ + if isinstance(idx, str): + idx = TAG_TO_LCID.get(idx, idx) + + if isinstance(idx, int) and (entry := self.entry.get(idx)) is not None: + return entry + + raise KeyError(f"Resource with language {idx!r} not found in {self!r}") + + def __contains__(self, idx: str | c_pe.RT) -> bool: + if isinstance(idx, str): + idx = TAG_TO_LCID.get(idx, idx) + + if isinstance(idx, int): + return self.entry.get(idx) is not None + + return False + + def languages(self) -> list[str]: + """Return a list of languages for this resource.""" + return [LCID_TO_TAG.get(name, str(name)) for name, _ in self.entry.iterdir()] + + def data(self, language: str | int | None = None) -> bytes: + """Get the resource data for a specific language. + + Args: + language: The language of the resource to open. If ``None``, the first available resource is opened. + """ + with self.open(language) as fh: + return fh.read() + + def open(self, language: str | int | None = None) -> RangeStream: + """Open the resource data as a stream. + + Args: + language: The language of the resource to open. If ``None``, the first available resource is opened. + """ + if language is None: + return next(self.entry.iterdir())[1].open() + + if isinstance(language, str): + language = TAG_TO_LCID.get(language, language) + + if isinstance(language, int) and (entry := self.entry.get(language)) is not None: + return entry.open() + + raise KeyError(f"Resource with language {language!r} not found in {self!r}") + + +class ResourceEntry: + """Base class for resource entries in a PE file.""" + + def __init__(self, rsrc: ResourceDirectory, address: int): + self.rsrc = rsrc + self.address = address + + @cached_property + def entry(self) -> c_pe.IMAGE_RESOURCE_DATA_ENTRY: + raise NotImplementedError + + +class ResourceDataEntry(ResourceEntry): + """A resource data entry in a PE file.""" + + def __repr__(self) -> str: + return f"" + + @cached_property + def entry(self) -> c_pe.IMAGE_RESOURCE_DATA_ENTRY: + """The resource data entry structure.""" + self.rsrc.pe.vfh.seek(self.address) + return c_pe.IMAGE_RESOURCE_DATA_ENTRY(self.rsrc.pe.vfh) + + @property + def offset_to_data(self) -> int: + """The offset to the resource data in the file.""" + return self.entry.OffsetToData + + @property + def size(self) -> int: + """The size of the resource data.""" + return self.entry.Size + + @property + def code_page(self) -> int: + """The code page of the resource data.""" + return self.entry.CodePage + + @property + def data(self) -> bytes: + """The raw resource data.""" + self.rsrc.pe.vfh.seek(self.offset_to_data) + return self.rsrc.pe.vfh.read(self.size) + + def open(self) -> RangeStream: + """Open the resource data as a stream.""" + return RangeStream(self.rsrc.pe.vfh, self.offset_to_data, self.size) + + +class ResourceDirectoryEntry(ResourceEntry): + """A resource directory entry in a PE file.""" + + def __repr__(self) -> str: + return f"" # noqa: E501 + + @cached_property + def entry(self) -> c_pe.IMAGE_RESOURCE_DIRECTORY: + """The resource directory entry structure.""" + self.rsrc.pe.vfh.seek(self.address) + return c_pe.IMAGE_RESOURCE_DIRECTORY(self.rsrc.pe.vfh) + + @property + def timestamp(self) -> datetime.datetime | None: + """The timestamp of this resource directory, or ``None`` if the PE file is compiled as reproducible.""" + if self.rsrc.pe.is_reproducible(): + return None + return from_unix(self.entry.TimeDateStamp) + + def get(self, name: int | str | c_pe.RT) -> ResourceDataEntry | ResourceDirectoryEntry | None: + """Get a resource entry by name.""" + for id, entry in self.iterdir(): + if id == name: + return entry + return None + + def listdir(self) -> dict[int | str, ResourceEntry]: + """Return a dictionary of the entries in this resource directory.""" + return dict(self.iterdir()) + + def iterdir(self) -> Iterator[tuple[int | str, ResourceDataEntry | ResourceDirectoryEntry]]: + """Iterate over the entries in this resource directory.""" + vfh = self.rsrc.pe.vfh + offset = self.address + len(c_pe.IMAGE_RESOURCE_DIRECTORY) + for _ in range(self.entry.NumberOfNamedEntries + self.entry.NumberOfIdEntries): + vfh.seek(offset) + entry = c_pe.IMAGE_RESOURCE_DIRECTORY_ENTRY(vfh) + + if entry.NameIsString: + vfh.seek(self.rsrc.address + entry.NameOffset) + name = c_pe.IMAGE_RESOURCE_DIR_STRING_U(vfh).NameString + else: + name = entry.Id + + if entry.DataIsDirectory: + obj = ResourceDirectoryEntry(self.rsrc, self.rsrc.address + entry.OffsetToDirectory) + else: + obj = ResourceDataEntry(self.rsrc, self.rsrc.address + entry.OffsetToData) + + yield name, obj + + offset += len(c_pe.IMAGE_RESOURCE_DIRECTORY_ENTRY) diff --git a/dissect/executable/pe/directory/security.py b/dissect/executable/pe/directory/security.py new file mode 100644 index 0000000..5692bdb --- /dev/null +++ b/dissect/executable/pe/directory/security.py @@ -0,0 +1,76 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + from collections.abc import Iterator + + +class SecurityDirectory(DataDirectory): + """The security directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.entries) + + def __iter__(self) -> Iterator[Certificate]: + return iter(self.entries) + + def __getitem__(self, idx: int) -> Certificate: + return self.entries[idx] + + @cached_property + def entries(self) -> list[Certificate]: + """List of certificates in the security directory.""" + result = [] + + offset = self.address + while offset < self.address + self.size: + # Note: the offset here is a file offset, not an RVA + self.pe.fh.seek(offset) + + certificate = c_pe.WIN_CERTIFICATE(self.pe.fh) + if certificate.dwLength == 0: + break + + result.append(Certificate(certificate)) + offset += certificate.dwLength + offset += -offset & 7 # Align to 8 bytes + + return result + + +class Certificate: + """A single certificate entry in the security directory.""" + + def __init__(self, certificate: c_pe.WIN_CERTIFICATE): + self.certificate = certificate + + def __repr__(self) -> str: + return f"" + + @property + def revision(self) -> int: + """The revision of the certificate.""" + return self.certificate.wRevision + + @property + def type(self) -> c_pe.WIN_CERT_TYPE: + """The type of the certificate.""" + return self.certificate.wCertificateType + + @property + def size(self) -> int: + """The size of the certificate.""" + return self.certificate.dwLength + + @property + def data(self) -> bytes: + """The raw data of the certificate.""" + return self.certificate.bCertificate diff --git a/dissect/executable/pe/directory/tls.py b/dissect/executable/pe/directory/tls.py new file mode 100644 index 0000000..652dff9 --- /dev/null +++ b/dissect/executable/pe/directory/tls.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory.base import DataDirectory + +if TYPE_CHECKING: + from collections.abc import Iterator + + +class TlsDirectory(DataDirectory): + """The TLS (Thread Local Storage) directory of a PE file.""" + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return len(self.callbacks) + + def __iter__(self) -> Iterator[int]: + return iter(self.callbacks) + + def __getitem__(self, idx: int) -> int: + return self.callbacks[idx] + + @cached_property + def header(self) -> c_pe.IMAGE_TLS_DIRECTORY32 | c_pe.IMAGE_TLS_DIRECTORY64: + """The TLS directory header.""" + self.pe.vfh.seek(self.address) + ctype = c_pe.IMAGE_TLS_DIRECTORY64 if self.pe.is_64bit() else c_pe.IMAGE_TLS_DIRECTORY32 + return ctype(self.pe.vfh) + + @cached_property + def callbacks(self) -> list[int]: + """List of callback addresses.""" + if not self.header.AddressOfCallBacks: + return [] + + self.pe.vfh.seek(self.pe.va_to_rva(self.header.AddressOfCallBacks)) + ctype = c_pe.ULONGLONG if self.pe.is_64bit() else c_pe.ULONG + try: + return ctype[None](self.pe.vfh) + except EOFError: + return [] diff --git a/dissect/executable/pe/locale_id.py b/dissect/executable/pe/locale_id.py new file mode 100644 index 0000000..96ffdeb --- /dev/null +++ b/dissect/executable/pe/locale_id.py @@ -0,0 +1,609 @@ +# Various constants and mappings for locale IDs (LCIDs) and code pages (CPs) used in PE files +from __future__ import annotations + +LCID_TO_TAG = { + 0x0000: "neutral", # Neutral locale + 0x0001: "ar", + 0x0002: "bg", + 0x0003: "ca", + 0x0004: "zh-Hans", + 0x0005: "cs", + 0x0006: "da", + 0x0007: "de", + 0x0008: "el", + 0x0009: "en", + 0x000A: "es", + 0x000B: "fi", + 0x000C: "fr", + 0x000D: "he", + 0x000E: "hu", + 0x000F: "is", + 0x0010: "it", + 0x0011: "ja", + 0x0012: "ko", + 0x0013: "nl", + 0x0014: "no", + 0x0015: "pl", + 0x0016: "pt", + 0x0017: "rm", + 0x0018: "ro", + 0x0019: "ru", + 0x001A: "hr", + 0x001B: "sk", + 0x001C: "sq", + 0x001D: "sv", + 0x001E: "th", + 0x001F: "tr", + 0x0020: "ur", + 0x0021: "id", + 0x0022: "uk", + 0x0023: "be", + 0x0024: "sl", + 0x0025: "et", + 0x0026: "lv", + 0x0027: "lt", + 0x0028: "tg", + 0x0029: "fa", + 0x002A: "vi", + 0x002B: "hy", + 0x002C: "az", + 0x002D: "eu", + 0x002E: "hsb", + 0x002F: "mk", + 0x0030: "st", + 0x0031: "ts", + 0x0032: "tn", + 0x0033: "ve", + 0x0034: "xh", + 0x0035: "zu", + 0x0036: "af", + 0x0037: "ka", + 0x0038: "fo", + 0x0039: "hi", + 0x003A: "mt", + 0x003B: "se", + 0x003C: "ga", + 0x003D: "yi", # reserved + 0x003E: "ms", + 0x003F: "kk", + 0x0040: "ky", + 0x0041: "sw", + 0x0042: "tk", + 0x0043: "uz", + 0x0044: "tt", + 0x0045: "bn", + 0x0046: "pa", + 0x0047: "gu", + 0x0048: "or", + 0x0049: "ta", + 0x004A: "te", + 0x004B: "kn", + 0x004C: "ml", + 0x004D: "as", + 0x004E: "mr", + 0x004F: "sa", + 0x0050: "mn", + 0x0051: "bo", + 0x0052: "cy", + 0x0053: "km", + 0x0054: "lo", + 0x0055: "my", + 0x0056: "gl", + 0x0057: "kok", + 0x0058: "mni", # reserved + 0x0059: "sd", + 0x005A: "syr", + 0x005B: "si", + 0x005C: "chr", + 0x005D: "iu", + 0x005E: "am", + 0x005F: "tzm", + 0x0060: "ks", + 0x0061: "ne", + 0x0062: "fy", + 0x0063: "ps", + 0x0064: "fil", + 0x0065: "dv", + 0x0066: "bin", # reserved + 0x0067: "ff", + 0x0068: "ha", + 0x0069: "ibb", # reserved + 0x006A: "yo", + 0x006B: "quz", + 0x006C: "nso", + 0x006D: "ba", + 0x006E: "lb", + 0x006F: "kl", + 0x0070: "ig", + 0x0071: "kr", # reserved + 0x0072: "om", + 0x0073: "ti", + 0x0074: "gn", + 0x0075: "haw", + 0x0076: "la", # reserved + 0x0077: "so", # reserved + 0x0078: "ii", + 0x0079: "pap", # reserved + 0x007A: "arn", + 0x007C: "moh", + 0x007E: "br", + 0x0080: "ug", + 0x0081: "mi", + 0x0082: "oc", + 0x0083: "co", + 0x0084: "gsw", + 0x0085: "sah", + 0x0086: "qut", + 0x0087: "rw", + 0x0088: "wo", + 0x008C: "prs", + 0x0091: "gd", + 0x0092: "ku", + 0x0093: "quc", # reserved + 0x0401: "ar-SA", + 0x0402: "bg-BG", + 0x0403: "ca-ES", + 0x0404: "zh-TW", + 0x0405: "cs-CZ", + 0x0406: "da-DK", + 0x0407: "de-DE", + 0x0408: "el-GR", + 0x0409: "en-US", + 0x040A: "es-ES_tradnl", + 0x040B: "fi-FI", + 0x040C: "fr-FR", + 0x040D: "he-IL", + 0x040E: "hu-HU", + 0x040F: "is-IS", + 0x0410: "it-IT", + 0x0411: "ja-JP", + 0x0412: "ko-KR", + 0x0413: "nl-NL", + 0x0414: "nb-NO", + 0x0415: "pl-PL", + 0x0416: "pt-BR", + 0x0417: "rm-CH", + 0x0418: "ro-RO", + 0x0419: "ru-RU", + 0x041A: "hr-HR", + 0x041B: "sk-SK", + 0x041C: "sq-AL", + 0x041D: "sv-SE", + 0x041E: "th-TH", + 0x041F: "tr-TR", + 0x0420: "ur-PK", + 0x0421: "id-ID", + 0x0422: "uk-UA", + 0x0423: "be-BY", + 0x0424: "sl-SI", + 0x0425: "et-EE", + 0x0426: "lv-LV", + 0x0427: "lt-LT", + 0x0428: "tg-Cyrl-TJ", + 0x0429: "fa-IR", + 0x042A: "vi-VN", + 0x042B: "hy-AM", + 0x042C: "az-Latn-AZ", + 0x042D: "eu-ES", + 0x042E: "hsb-DE", + 0x042F: "mk-MK", + 0x0430: "st-ZA", + 0x0431: "ts-ZA", + 0x0432: "tn-ZA", + 0x0433: "ve-ZA", + 0x0434: "xh-ZA", + 0x0435: "zu-ZA", + 0x0436: "af-ZA", + 0x0437: "ka-GE", + 0x0438: "fo-FO", + 0x0439: "hi-IN", + 0x043A: "mt-MT", + 0x043B: "se-NO", + 0x043D: "yi-001", + 0x043E: "ms-MY", + 0x043F: "kk-KZ", + 0x0440: "ky-KG", + 0x0441: "sw-KE", + 0x0442: "tk-TM", + 0x0443: "uz-Latn-UZ", + 0x0444: "tt-RU", + 0x0445: "bn-IN", + 0x0446: "pa-IN", + 0x0447: "gu-IN", + 0x0448: "or-IN", + 0x0449: "ta-IN", + 0x044A: "te-IN", + 0x044B: "kn-IN", + 0x044C: "ml-IN", + 0x044D: "as-IN", + 0x044E: "mr-IN", + 0x044F: "sa-IN", + 0x0450: "mn-MN", + 0x0451: "bo-CN", + 0x0452: "cy-GB", + 0x0453: "km-KH", + 0x0454: "lo-LA", + 0x0455: "my-MM", + 0x0456: "gl-ES", + 0x0457: "kok-IN", + 0x0458: "mni-IN", # reserved + 0x0459: "sd-Deva-IN", # reserved + 0x045A: "syr-SY", + 0x045B: "si-LK", + 0x045C: "chr-Cher-US", + 0x045D: "iu-Cans-CA", + 0x045E: "am-ET", + 0x045F: "tzm-Arab-MA", + 0x0460: "ks-Arab", + 0x0461: "ne-NP", + 0x0462: "fy-NL", + 0x0463: "ps-AF", + 0x0464: "fil-PH", + 0x0465: "dv-MV", + 0x0466: "bin-NG", # reserved + 0x0467: "ff-NG", # ff-Latn-NG + 0x0468: "ha-Latn-NG", + 0x0469: "ibb-NG", # reserved + 0x046A: "yo-NG", + 0x046B: "quz-BO", + 0x046C: "nso-ZA", + 0x046D: "ba-RU", + 0x046E: "lb-LU", + 0x046F: "kl-GL", + 0x0470: "ig-NG", + 0x0471: "kr-Latn-NG", + 0x0472: "om-ET", + 0x0473: "ti-ET", + 0x0474: "gn-PY", + 0x0475: "haw-US", + 0x0476: "la-VA", + 0x0477: "so-SO", + 0x0478: "ii-CN", + 0x0479: "pap-029", # reserved + 0x047A: "arn-CL", + 0x047C: "moh-CA", + 0x047E: "br-FR", + 0x0480: "ug-CN", + 0x0481: "mi-NZ", + 0x0482: "oc-FR", + 0x0483: "co-FR", + 0x0484: "gsw-FR", + 0x0485: "sah-RU", + 0x0486: "qut-GT", # reserved + 0x0487: "rw-RW", + 0x0488: "wo-SN", + 0x048C: "prs-AF", + 0x048D: "plt-MG", # reserved + 0x048E: "zh-yue-HK", # reserved + 0x048F: "tdd-Tale-CN", # reserved + 0x0490: "khb-Talu-CN", # reserved + 0x0491: "gd-GB", + 0x0492: "ku-Arab-IQ", + 0x0493: "quc-CO", # reserved + 0x0501: "qps-ploc", + 0x05FE: "qps-ploca", + 0x0801: "ar-IQ", + 0x0803: "ca-ES-valencia", + 0x0804: "zh-CN", + 0x0807: "de-CH", + 0x0809: "en-GB", + 0x080A: "es-MX", + 0x080C: "fr-BE", + 0x0810: "it-CH", + 0x0811: "ja-Ploc-JP", # reserved + 0x0813: "nl-BE", + 0x0814: "nn-NO", + 0x0816: "pt-PT", + 0x0818: "ro-MD", + 0x0819: "ru-MD", + 0x081A: "sr-Latn-CS", + 0x081D: "sv-FI", + 0x0820: "ur-IN", + 0x0827: "Invalid", + 0x082C: "az-Cyrl-AZ", # reserved + 0x082E: "dsb-DE", + 0x0832: "tn-BW", + 0x083B: "se-SE", + 0x083C: "ga-IE", + 0x083E: "ms-BN", + 0x083F: "kk-Latn-KZ", # reserved + 0x0843: "uz-Cyrl-UZ", # reserved + 0x0845: "bn-BD", + 0x0846: "pa-Arab-PK", + 0x0849: "ta-LK", + 0x0850: "mn-Mong-CN", # reserved + 0x0851: "bo-BT", # reserved + 0x0859: "sd-Arab-PK", + 0x085D: "iu-Latn-CA", + 0x085F: "tzm-Latn-DZ", + 0x0860: "ks-Deva-IN", + 0x0861: "ne-IN", + 0x0867: "ff-Latn-SN", + 0x086B: "quz-EC", + 0x0873: "ti-ER", + 0x09FF: "qps-plocm", + 0x0C01: "ar-EG", + 0x0C04: "zh-HK", + 0x0C07: "de-AT", + 0x0C09: "en-AU", + 0x0C0A: "es-ES", + 0x0C0C: "fr-CA", + 0x0C1A: "sr-Cyrl-CS", + 0x0C3B: "se-FI", + 0x0C50: "mn-Mong-MN", + 0x0C51: "dz-BT", + 0x0C5F: "tmz-MA", # reserved + 0x0C6B: "quz-PE", + 0x1001: "ar-LY", + 0x1004: "zh-SG", + 0x1007: "de-LU", + 0x1009: "en-CA", + 0x100A: "es-GT", + 0x100C: "fr-CH", + 0x101A: "hr-BA", + 0x103B: "smj-NO", + 0x105F: "tzm-Tfng-MA", + 0x1401: "ar-DZ", + 0x1404: "zh-MO", + 0x1407: "de-LI", + 0x1409: "en-NZ", + 0x140A: "es-CR", + 0x140C: "fr-LU", + 0x141A: "bs-Latn-BA", + 0x143B: "smj-SE", + 0x1801: "ar-MA", + 0x1809: "en-IE", + 0x180A: "es-PA", + 0x180C: "fr-MC", + 0x181A: "sr-Latn-BA", + 0x183B: "sma-NO", + 0x1C01: "ar-TN", + 0x1C09: "en-ZA", + 0x1C0A: "es-DO", + 0x1C0C: "fr-029", + 0x1C1A: "sr-Cyrl-BA", + 0x1C3B: "sma-SE", + 0x2001: "ar-OM", + 0x2009: "en-JM", + 0x200A: "es-VE", + 0x200C: "fr-RE", + 0x201A: "bs-Cyrl-BA", + 0x203B: "sms-FI", + 0x2401: "ar-YE", + 0x2409: "en-029", # reserved + 0x240A: "es-CO", + 0x240C: "fr-CD", + 0x241A: "sr-Latn-RS", + 0x243B: "smn-FI", + 0x2801: "ar-SY", + 0x2809: "en-BZ", + 0x280A: "es-PE", + 0x280C: "fr-SN", + 0x281A: "sr-Cyrl-RS", + 0x2C01: "ar-JO", + 0x2C09: "en-TT", + 0x2C0A: "es-AR", + 0x2C0C: "fr-CM", + 0x2C1A: "sr-Latn-ME", + 0x3001: "ar-LB", + 0x3009: "en-ZW", + 0x300A: "es-EC", + 0x300C: "fr-CI", + 0x301A: "sr-Cyrl-ME", + 0x3401: "ar-KW", + 0x3409: "en-PH", + 0x340A: "es-CL", + 0x340C: "fr-ML", + 0x3801: "ar-AE", + 0x3809: "en-ID", # reserved + 0x380A: "es-UY", + 0x380C: "fr-MA", + 0x3C01: "ar-BH", + 0x3C09: "en-HK", + 0x3C0A: "es-PY", + 0x3C0C: "fr-HT", + 0x4001: "ar-QA", + 0x4009: "en-IN", + 0x400A: "es-BO", + 0x4401: "ar-Ploc-SA", # reserved + 0x4409: "en-MY", + 0x440A: "es-SV", + 0x4801: "ar-145", # reserved + 0x4809: "en-SG", + 0x480A: "es-HN", + 0x4C09: "en-AE", + 0x4C0A: "es-NI", + 0x5009: "en-BH", # reserved + 0x500A: "es-PR", + 0x5409: "en-EG", # reserved + 0x540A: "es-US", + 0x5809: "en-JO", # reserved + 0x580A: "es-419", # reserved + 0x5C09: "en-KW", # reserved + 0x5C0A: "es-CU", + 0x6009: "en-TR", # reserved + 0x6409: "en-YE", # reserved + 0x641A: "bs-Cyrl", + 0x681A: "bs-Latn", + 0x6C1A: "sr-Cyrl", + 0x701A: "sr-Latn", + 0x703B: "smn", + 0x742C: "az-Cyrl", + 0x743B: "sms", + 0x7804: "zh", + 0x7814: "nn", + 0x781A: "bs", + 0x782C: "az-Latn", + 0x783B: "sma", + 0x783F: "kk-Cyrl", # reserved + 0x7843: "uz-Cyrl", + 0x7850: "mn-Cyrl", + 0x785D: "iu-Cans", + 0x785F: "tzm-Tfng", + 0x7C04: "zh-Hant", + 0x7C14: "nb", + 0x7C1A: "sr", + 0x7C28: "tg-Cyrl", + 0x7C2E: "dsb", + 0x7C3B: "smj", + 0x7C3F: "kk-Latn", # reserved + 0x7C43: "uz-Latn", + 0x7C46: "pa-Arab", + 0x7C50: "mn-Mong", + 0x7C59: "sd-Arab", + 0x7C5C: "chr-Cher", + 0x7C5D: "iu-Latn", + 0x7C5F: "tzm-Latn", + 0x7C67: "ff-Latn", + 0x7C68: "ha-Latn", + 0x7C92: "ku-Arab", + 0xE40C: "fr-015", # reserved +} + +TAG_TO_LCID = {v: k for k, v in LCID_TO_TAG.items()} + + +CP_TO_NAME = { + 37: "IBM037", + 437: "IBM437", + 500: "IBM500", + 708: "ASMO-708", + 720: "DOS-720", + 737: "ibm737", + 775: "ibm775", + 850: "ibm850", + 852: "ibm852", + 855: "IBM855", + 857: "ibm857", + 858: "IBM00858", + 860: "IBM860", + 861: "ibm861", + 862: "DOS-862", + 863: "IBM863", + 864: "IBM864", + 865: "IBM865", + 866: "cp866", + 869: "ibm869", + 870: "IBM870", + 874: "windows-874", + 875: "cp875", + 932: "shift_jis", + 936: "gb2312", + 949: "ks_c_5601-1987", + 950: "big5", + 1026: "IBM1026", + 1047: "IBM01047", + 1140: "IBM01140", + 1141: "IBM01141", + 1142: "IBM01142", + 1143: "IBM01143", + 1144: "IBM01144", + 1145: "IBM01145", + 1146: "IBM01146", + 1147: "IBM01147", + 1148: "IBM01148", + 1149: "IBM01149", + 1200: "utf-16", + 1201: "unicodeFFFE", + 1250: "windows-1250", + 1251: "windows-1251", + 1252: "windows-1252", + 1253: "windows-1253", + 1254: "windows-1254", + 1255: "windows-1255", + 1256: "windows-1256", + 1257: "windows-1257", + 1258: "windows-1258", + 1361: "Johab", + 10000: "macintosh", + 10001: "x-mac-japanese", + 10002: "x-mac-chinesetrad", + 10003: "x-mac-korean", + 10004: "x-mac-arabic", + 10005: "x-mac-hebrew", + 10006: "x-mac-greek", + 10007: "x-mac-cyrillic", + 10008: "x-mac-chinesesimp", + 10010: "x-mac-romanian", + 10017: "x-mac-ukrainian", + 10021: "x-mac-thai", + 10029: "x-mac-ce", + 10079: "x-mac-icelandic", + 10081: "x-mac-turkish", + 10082: "x-mac-croatian", + 12000: "utf-32", + 12001: "utf-32BE", + 20000: "x-Chinese_CNS", + 20001: "x-cp20001", + 20002: "x_Chinese-Eten", + 20003: "x-cp20003", + 20004: "x-cp20004", + 20005: "x-cp20005", + 20105: "x-IA5", + 20106: "x-IA5-German", + 20107: "x-IA5-Swedish", + 20108: "x-IA5-Norwegian", + 20127: "us-ascii", + 20261: "x-cp20261", + 20269: "x-cp20269", + 20273: "IBM273", + 20277: "IBM277", + 20278: "IBM278", + 20280: "IBM280", + 20284: "IBM284", + 20285: "IBM285", + 20290: "IBM290", + 20297: "IBM297", + 20420: "IBM420", + 20423: "IBM423", + 20424: "IBM424", + 20833: "x-EBCDIC-KoreanExtended", + 20838: "IBM-Thai", + 20866: "koi8-r", + 20871: "IBM871", + 20880: "IBM880", + 20905: "IBM905", + 20924: "IBM00924", + 20932: "EUC-JP", + 20936: "x-cp20936", + 20949: "x-cp20949", + 21025: "cp1025", + 21866: "koi8-u", + 28591: "iso-8859-1", + 28592: "iso-8859-2", + 28593: "iso-8859-3", + 28594: "iso-8859-4", + 28595: "iso-8859-5", + 28596: "iso-8859-6", + 28597: "iso-8859-7", + 28598: "iso-8859-8", + 28599: "iso-8859-9", + 28603: "iso-8859-13", + 28605: "iso-8859-15", + 29001: "x-Europa", + 38598: "iso-8859-8-i", + 50220: "iso-2022-jp", + 50221: "csISO2022JP", + 50222: "iso-2022-jp", + 50225: "iso-2022-kr", + 50227: "x-cp50227", + 51932: "euc-jp", + 51936: "EUC-CN", + 51949: "euc-kr", + 52936: "hz-gb-2312", + 54936: "GB18030", + 57002: "x-iscii-de", + 57003: "x-iscii-be", + 57004: "x-iscii-ta", + 57005: "x-iscii-te", + 57006: "x-iscii-as", + 57007: "x-iscii-or", + 57008: "x-iscii-ka", + 57009: "x-iscii-ma", + 57010: "x-iscii-gu", + 57011: "x-iscii-pa", + 65000: "utf-7", + 65001: "utf-8", +} + +NAME_TO_CP = {v: k for k, v in CP_TO_NAME.items()} diff --git a/dissect/executable/pe/pe.py b/dissect/executable/pe/pe.py new file mode 100644 index 0000000..469a418 --- /dev/null +++ b/dissect/executable/pe/pe.py @@ -0,0 +1,448 @@ +from __future__ import annotations + +import io +from bisect import bisect_right +from functools import cached_property +from typing import TYPE_CHECKING, BinaryIO + +from dissect.util.stream import AlignedStream, BufferedStream, RangeStream +from dissect.util.ts import from_unix + +from dissect.executable.exception import InvalidSignatureError +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.directory import ( + BaseRelocationDirectory, + BoundImportDirectory, + ComDescriptorDirectory, + DataDirectory, + DebugDirectory, + DelayImportDirectory, + ExceptionDirectory, + ExportDirectory, + IatDirectory, + ImportDirectory, + LoadConfigDirectory, + ResourceDirectory, + SecurityDirectory, + TlsDirectory, +) + +if TYPE_CHECKING: + import datetime + + +class PE: + """PE file parser. + + Args: + fh: A file-like object of an executable. + virtual: Indicate whether to use virtual addressing instead of physical. + Use this when the file has already been mapped into memory. + """ + + def __init__(self, fh: BinaryIO, virtual: bool = False): + self.fh = fh + self.virtual = virtual + + self.fh.seek(0) + + self.mz_header = c_pe.IMAGE_DOS_HEADER(self.fh) + if self.mz_header.e_magic != c_pe.IMAGE_DOS_SIGNATURE: + raise InvalidSignatureError( + f"File is not a valid PE file, wrong MZ signature: {self.mz_header.e_magic.to_bytes(2, 'little')} " + f"(expected {c_pe.IMAGE_DOS_SIGNATURE.to_bytes(2, 'little')})" + ) + + self.os2_header = None + self.file_header = None + self.optional_header = None + self.sections: list[Section] = [] + self.vfh = None + + self.fh.seek(self.mz_header.e_lfanew) + signature = c_pe.ULONG(fh) + if (signature & 0xFFFF) == c_pe.IMAGE_OS2_SIGNATURE: + self.fh.seek(-4, io.SEEK_CUR) + self.os2_header = c_pe.IMAGE_OS2_HEADER(self.fh) + + elif signature == c_pe.IMAGE_NT_SIGNATURE: + # No need to correct the offset + self.file_header = c_pe.IMAGE_FILE_HEADER(self.fh) + + if self.file_header.SizeOfOptionalHeader: + optional_magic = c_pe.USHORT(self.fh) + self.fh.seek(-2, io.SEEK_CUR) + + if optional_magic == c_pe.IMAGE_NT_OPTIONAL_HDR32_MAGIC: + self.optional_header = c_pe.IMAGE_OPTIONAL_HEADER32(self.fh) + elif optional_magic == c_pe.IMAGE_NT_OPTIONAL_HDR64_MAGIC: + self.optional_header = c_pe.IMAGE_OPTIONAL_HEADER64(self.fh) + else: + raise InvalidSignatureError( + f"File is not a valid PE file, wrong NT header magic: {optional_magic:#x} " + f"(expected {c_pe.IMAGE_NT_OPTIONAL_HDR32_MAGIC:#x} or {c_pe.IMAGE_NT_OPTIONAL_HDR64_MAGIC:#x})" + ) + + self.sections = [Section.from_fh(self, self.fh) for _ in range(self.file_header.NumberOfSections)] + + self.vfh = self.open() + else: + raise InvalidSignatureError( + f"File is not a valid PE file, wrong header signature: {signature.to_bytes(4, 'little')} " + f"(expected {c_pe.IMAGE_NT_SIGNATURE.to_bytes(4, 'little')} (NT) " + f"or {c_pe.IMAGE_OS2_SIGNATURE.to_bytes(2, 'little')} (OS/2))" + ) + + self.fh.seek(len(self.mz_header)) + self.dos_stub = self.fh.read(self.mz_header.e_lfanew - len(self.mz_header)) + + @property + def machine(self) -> c_pe.IMAGE_FILE_MACHINE: + """Return the machine type of the PE file.""" + if not self.file_header: + return c_pe.IMAGE_FILE_MACHINE.UNKNOWN + return self.file_header.Machine + + @property + def image_base(self) -> int: + """Return the image base address of the PE file.""" + if not self.optional_header: + return 0 + return self.optional_header.ImageBase + + @property + def timestamp(self) -> datetime.datetime | None: + """The compilation timestamp of the PE file, or ``None`` if the PE file is compiled as reproducible.""" + if not self.file_header or self.is_reproducible(): + return None + return from_unix(self.file_header.TimeDateStamp) + + def is_pe(self) -> bool: + """Return if the file is a valid PE file.""" + return self.is_nt() + + def is_nt(self) -> bool: + """Return if the file is a valid NT executable.""" + return self.file_header is not None + + def is_os2(self) -> bool: + """Return if the file is an OS/2 executable.""" + return self.os2_header is not None + + def is_64bit(self) -> bool: + """Return if the PE file is 64-bit (PE32+).""" + return self.optional_header is not None and self.optional_header.Magic == c_pe.IMAGE_NT_OPTIONAL_HDR64_MAGIC + + def is_reproducible(self) -> bool: + """Return if the PE file is reproducible (i.e. has a REPRO debug entry).""" + return self.debug is not None and any(entry.type == c_pe.IMAGE_DEBUG_TYPE.REPRO for entry in self.debug.entries) + + def pdb_path(self) -> str | None: + """Return the PDB path, if available.""" + for entry in self.debug.entries if self.debug else []: + if entry.type == c_pe.IMAGE_DEBUG_TYPE.CODEVIEW: + return entry.pdb + return None + + def _data_directory(self, index: c_pe.IMAGE_DIRECTORY_ENTRY) -> c_pe.IMAGE_DATA_DIRECTORY | None: + """Return the data directory at the given index.""" + if not self.optional_header or not self.optional_header.DataDirectory: + return None + if index < 0 or index >= len(self.optional_header.DataDirectory): + return None + if not (entry := self.optional_header.DataDirectory[index]): + return None + return entry + + def data_directories(self) -> dict[c_pe.IMAGE_DIRECTORY_ENTRY, DataDirectory]: + """Return all data directories.""" + result = {} + for index in c_pe.IMAGE_DIRECTORY_ENTRY: + if index == c_pe.IMAGE_DIRECTORY_ENTRY.EXPORT: + result[index] = self.exports + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.IMPORT: + result[index] = self.imports + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.RESOURCE: + result[index] = self.resources + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.EXCEPTION: + result[index] = self.exceptions + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.SECURITY and not self.virtual: + result[index] = self.security + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.BASERELOC: + result[index] = self.base_relocations + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.DEBUG: + result[index] = self.debug + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.TLS: + result[index] = self.tls + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.LOAD_CONFIG: + result[index] = self.load_config + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.BOUND_IMPORT: + result[index] = self.bound_import + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.IAT: + result[index] = self.iat + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.DELAY_IMPORT: + result[index] = self.delay_import + elif index == c_pe.IMAGE_DIRECTORY_ENTRY.COM_DESCRIPTOR: + result[index] = self.com_descriptor + else: + if entry := self._data_directory(index): + result[index] = DataDirectory(self, entry.VirtualAddress, entry.Size) + return result + + @cached_property + def exports(self) -> ExportDirectory | None: + """Return the export directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.EXPORT)): + return None + return ExportDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def imports(self) -> ImportDirectory | None: + """Return the import directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.IMPORT)): + return None + return ImportDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def resources(self) -> ResourceDirectory | None: + """Return the resource directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.RESOURCE)): + return None + return ResourceDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def exceptions(self) -> ExceptionDirectory | None: + """Return the exception directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.EXCEPTION)): + return None + return ExceptionDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def security(self) -> SecurityDirectory | None: + """Return the security directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.SECURITY)) and not self.virtual: + return None + return SecurityDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def base_relocations(self) -> BaseRelocationDirectory | None: + """Return the base relocation directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.BASERELOC)): + return None + return BaseRelocationDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def debug(self) -> DebugDirectory | None: + """Return the debug directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.DEBUG)): + return None + return DebugDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def global_pointer(self) -> int: + """Return the global pointer address, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.GLOBALPTR)): + return None + return entry.VirtualAddress + + @cached_property + def tls(self) -> TlsDirectory | None: + """Return the TLS (Thread Local Storage) directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.TLS)): + return None + return TlsDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def load_config(self) -> LoadConfigDirectory | None: + """Return the load config directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.LOAD_CONFIG)): + return None + return LoadConfigDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def bound_import(self) -> BoundImportDirectory | None: + """Return the bound import directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.BOUND_IMPORT)): + return None + return BoundImportDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def iat(self) -> IatDirectory | None: + """Return the import address table (IAT) directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.IAT)): + return None + return IatDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def delay_import(self) -> DelayImportDirectory | None: + """Return the delay import directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.DELAY_IMPORT)): + return None + return DelayImportDirectory(self, entry.VirtualAddress, entry.Size) + + @cached_property + def com_descriptor(self) -> ComDescriptorDirectory | None: + """Return the COM descriptor directory, if available.""" + if not (entry := self._data_directory(c_pe.IMAGE_DIRECTORY_ENTRY.COM_DESCRIPTOR)): + return None + return ComDescriptorDirectory(self, entry.VirtualAddress, entry.Size) + + def va_to_rva(self, va: int) -> int: + """Return the relative virtual address (RVA) of the given virtual address (VA).""" + return va - self.image_base + + def open(self) -> VirtualStream: + """Return a stream of the virtual address space of the PE file.""" + return VirtualStream(self) if not self.virtual else BufferedStream(self.fh) + + +class Section: + """A section in a PE file.""" + + def __init__(self, pe: PE, header: c_pe.IMAGE_SECTION_HEADER): + self.pe = pe + self.header = header + + def __repr__(self) -> str: + return f"
" # noqa: E501 + + @classmethod + def from_fh(cls, pe: PE, fh: BinaryIO) -> None: + """Read a section header from the file-like object. + + Args: + pe: The PE object to which this section belongs. + fh: The file-like object from which to read the section header. + """ + header = c_pe.IMAGE_SECTION_HEADER(fh) + return cls(pe, header) + + def open(self) -> RangeStream: + """Return a stream for the section data.""" + return SectionStream(self) + + @property + def name(self) -> str: + """Return the name of the section.""" + return self.header.Name.decode().strip("\x00") + + @property + def virtual_size(self) -> int: + """Return the virtual size of the section. + + Returns: + The virtual size of the section as an `int`. + """ + return self.header.Misc.VirtualSize + + @property + def virtual_address(self) -> int: + """Return the virtual address of the section. + + Returns: + The virtual address of the section as an `int`. + """ + return self.header.VirtualAddress + + @property + def raw_size(self) -> int: + """Return the raw size of the section. + + Returns: + The raw size of the section as an `int`. + """ + return self.header.SizeOfRawData + + @property + def pointer_to_raw_data(self) -> int: + """Return the pointer to raw data of the section. + + Returns: + The pointer to raw data of the section as an `int`. + """ + return self.header.PointerToRawData + + +class VirtualStream(AlignedStream): + """Read from a PE file as if it's been mapped into the virtual address space.""" + + def __init__(self, pe: PE): + self.pe = pe + self._sections = sorted(pe.sections, key=lambda s: s.virtual_address) + self._lookup = [s.virtual_address for s in self._sections] + super().__init__(pe.optional_header.SizeOfImage, pe.optional_header.SectionAlignment) + + def _read(self, offset: int, length: int) -> bytes: + result = [] + + # Read from the file header + if offset < self.pe.optional_header.SizeOfHeaders: + self.pe.fh.seek(offset) + read_length = min(length, self.pe.optional_header.SizeOfHeaders - offset) + result.append(self.pe.fh.read(read_length)) + + length -= read_length + offset += read_length + + section_idx = bisect_right(self._lookup, offset) + + while length > 0: + # Read from the sections or fill in gaps + current_section = self._sections[section_idx - 1] if section_idx > 0 else None + next_section = self._sections[section_idx] if section_idx < len(self._sections) else None + + if not current_section and not next_section: + # What + result.append(b"\x00" * length) + break + + if not current_section or offset >= current_section.virtual_address + current_section.virtual_size: + # In between sections or after the last section + read_length = min(length, (next_section.virtual_address if next_section else self.size) - offset) + result.append(b"\x00" * read_length) + + length -= read_length + offset += read_length + section_idx += 1 + continue + + if ( + current_section.virtual_address + <= offset + < current_section.virtual_address + current_section.virtual_size + ): + # Within the current section + offset_in_section = offset - current_section.virtual_address + if offset_in_section < current_section.raw_size: + read_length = min(length, current_section.raw_size - offset_in_section) + + self.pe.fh.seek(current_section.pointer_to_raw_data + offset_in_section) + result.append(self.pe.fh.read(read_length)) + + length -= read_length + offset += read_length + # Stay in the same section + continue + + return b"".join(result) + + +class SectionStream(AlignedStream): + """A stream that reads the section data from a PE file.""" + + def __init__(self, section: Section): + self.section = section + super().__init__(section.virtual_size) + + def _read(self, offset: int, length: int) -> bytes: + result = [] + + if raw_remaining := min(length, max(0, self.section.raw_size - offset)): + self.section.pe.fh.seek(self.section.pointer_to_raw_data + offset) + result.append(self.section.pe.fh.read(raw_remaining)) + length -= raw_remaining + + if length: + result.append(b"\x00" * length) + + return b"".join(result) diff --git a/pyproject.toml b/pyproject.toml index 9da98eb..fd1bb2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ classifiers = [ "Topic :: Utilities", ] dependencies = [ - "dissect.cstruct>=4,<5", + "dissect.cstruct>=4.6.dev,<5", # TODO: remove on release "dissect.util>=3,<4", ] dynamic = ["version"] @@ -37,7 +37,7 @@ repository = "https://github.com/fox-it/dissect.executable" [project.optional-dependencies] dev = [ - "dissect.cstruct>=4.0.dev,<5.0.dev", + "dissect.cstruct>=4.6.dev,<5.0.dev", "dissect.util>=3.0.dev,<4.0.dev", ] @@ -87,6 +87,7 @@ ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM1 [tool.ruff.lint.per-file-ignores] "tests/_docs/**" = ["INP001"] +"**/*.pyi" = ["PYI042", "PYI047", "PYI054"] [tool.ruff.lint.isort] known-first-party = ["dissect.executable"] diff --git a/tests/_data/pe/16/DPMIRES.EXE b/tests/_data/pe/16/DPMIRES.EXE new file mode 100644 index 0000000..f96bfc0 Binary files /dev/null and b/tests/_data/pe/16/DPMIRES.EXE differ diff --git a/tests/_data/pe/32/Dummy.dll b/tests/_data/pe/32/Dummy.dll new file mode 100644 index 0000000..76116d0 Binary files /dev/null and b/tests/_data/pe/32/Dummy.dll differ diff --git a/tests/_data/pe/32/Microsoft.Windows.SoftwareLogo.Binscope.resources.dll b/tests/_data/pe/32/Microsoft.Windows.SoftwareLogo.Binscope.resources.dll new file mode 100644 index 0000000..1f93017 Binary files /dev/null and b/tests/_data/pe/32/Microsoft.Windows.SoftwareLogo.Binscope.resources.dll differ diff --git a/tests/_data/pe/32/NetDbgTLLoc.dll b/tests/_data/pe/32/NetDbgTLLoc.dll new file mode 100644 index 0000000..c4c9ef9 Binary files /dev/null and b/tests/_data/pe/32/NetDbgTLLoc.dll differ diff --git a/tests/_data/pe/32/OLEACCHOOKS.DLL b/tests/_data/pe/32/OLEACCHOOKS.DLL new file mode 100644 index 0000000..1509102 Binary files /dev/null and b/tests/_data/pe/32/OLEACCHOOKS.DLL differ diff --git a/tests/_data/pe/32/PUNZIP.EXE b/tests/_data/pe/32/PUNZIP.EXE new file mode 100644 index 0000000..2010f0d Binary files /dev/null and b/tests/_data/pe/32/PUNZIP.EXE differ diff --git a/tests/_data/pe/32/TpmCertResources.dll b/tests/_data/pe/32/TpmCertResources.dll new file mode 100644 index 0000000..b1e54a7 Binary files /dev/null and b/tests/_data/pe/32/TpmCertResources.dll differ diff --git a/tests/_data/pe/32/UWPEnum.dll b/tests/_data/pe/32/UWPEnum.dll new file mode 100644 index 0000000..edf7d12 Binary files /dev/null and b/tests/_data/pe/32/UWPEnum.dll differ diff --git a/tests/_data/pe/32/aborttest.exe b/tests/_data/pe/32/aborttest.exe new file mode 100644 index 0000000..089b433 Binary files /dev/null and b/tests/_data/pe/32/aborttest.exe differ diff --git a/tests/_data/pe/32/mingwm10.dll b/tests/_data/pe/32/mingwm10.dll new file mode 100644 index 0000000..6090f6f Binary files /dev/null and b/tests/_data/pe/32/mingwm10.dll differ diff --git a/tests/_data/pe/64/comres.dll b/tests/_data/pe/64/comres.dll new file mode 100644 index 0000000..38c0696 Binary files /dev/null and b/tests/_data/pe/64/comres.dll differ diff --git a/tests/_data/pe/64/test.exe b/tests/_data/pe/64/test.exe new file mode 100644 index 0000000..04a7d72 Binary files /dev/null and b/tests/_data/pe/64/test.exe differ diff --git a/tests/_utils.py b/tests/_utils.py index 8d43746..7574f55 100644 --- a/tests/_utils.py +++ b/tests/_utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from pathlib import Path diff --git a/tests/pe/__init__.py b/tests/pe/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/pe/directory/__init__.py b/tests/pe/directory/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/pe/directory/test_basereloc.py b/tests/pe/directory/test_basereloc.py new file mode 100644 index 0000000..b608a06 --- /dev/null +++ b/tests/pe/directory/test_basereloc.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_basereloc() -> None: + """Test the base relocations directory.""" + with absolute_path("_data/pe/32/PUNZIP.EXE").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "R4000" + assert len(pe.base_relocations) == 5454 + assert list(pe.base_relocations) + + assert pe.base_relocations[0].rva == 0x102C + assert pe.base_relocations[0].type == c_pe.IMAGE_REL_BASED.MIPS_JMPADDR diff --git a/tests/pe/directory/test_bound_import.py b/tests/pe/directory/test_bound_import.py new file mode 100644 index 0000000..d60303e --- /dev/null +++ b/tests/pe/directory/test_bound_import.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import datetime + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_bound_import() -> None: + """Test the bound imports directory.""" + with absolute_path("_data/pe/32/NetDbgTLLoc.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert len(pe.bound_import) == 2 + assert list(pe.bound_import) + + assert pe.bound_import[0].name == "KERNEL32.dll" + assert len(pe.bound_import[0].forwarders) == 1 + assert pe.bound_import[0].forwarders[0].name == "NTDLL.DLL" + + assert pe.bound_import["MSVCR71.dll"].timestamp == datetime.datetime( + 2003, 2, 21, 12, 42, 20, tzinfo=datetime.timezone.utc + ) diff --git a/tests/pe/directory/test_com_descriptor.py b/tests/pe/directory/test_com_descriptor.py new file mode 100644 index 0000000..aa972a5 --- /dev/null +++ b/tests/pe/directory/test_com_descriptor.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_com_descriptor() -> None: + """Test the COM descriptor directory.""" + with absolute_path("_data/pe/32/Microsoft.Windows.SoftwareLogo.Binscope.resources.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + + assert pe.com_descriptor + assert len(pe.com_descriptor.metadata.streams) == 4 + assert [stream.name for stream in pe.com_descriptor.metadata.streams] == ["#~", "#Strings", "#US", "#GUID"] diff --git a/tests/pe/directory/test_debug.py b/tests/pe/directory/test_debug.py new file mode 100644 index 0000000..530b738 --- /dev/null +++ b/tests/pe/directory/test_debug.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_debug_codeview() -> None: + """Test the CodeView debug entry.""" + with absolute_path("_data/pe/32/NetDbgTLLoc.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + + assert pe.debug + assert len(pe.debug) == 2 + + assert pe.debug[0].type.name == "CODEVIEW" + assert str(pe.debug[0].signature) == "434b5c0d-1ee4-4bc8-bdf0-2e87ea897763" + assert pe.debug[0].age == 2 + assert pe.debug[0].pdb == "I:\\VS70Builds\\3077\\vsbuilt\\retail\\Bin\\i386\\opt\\natdbgtlloc.pdb" + + assert pe.pdb_path() == "I:\\VS70Builds\\3077\\vsbuilt\\retail\\Bin\\i386\\opt\\natdbgtlloc.pdb" + + +def test_debug_vc_feature() -> None: + """Test the VC feature debug entry.""" + with absolute_path("_data/pe/32/aborttest.exe").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + + assert pe.debug + assert len(pe.debug) == 2 + + assert pe.debug[1].type.name == "VC_FEATURE" + assert pe.debug[1].pre_vc11 == 0 + assert pe.debug[1].ccpp == 23 + assert pe.debug[1].gs == 23 + assert pe.debug[1].sdl == 0 + assert pe.debug[1].guards == 0 + + +def test_debug_pogo() -> None: + """Test the POGO debug entry.""" + with absolute_path("_data/pe/32/Dummy.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + + assert pe.debug + assert len(pe.debug) == 2 + + assert pe.debug[0].type.name == "POGO" + assert len(pe.debug[0]) == 4 + assert list(pe.debug[0]) == [ + (4096, 56, ".rdata"), + (4152, 120, ".rdata$zzzdbg"), + (8192, 96, ".rsrc$01"), + (8288, 928, ".rsrc$02"), + ] + + +def test_debug_repro() -> None: + """Test the REPRO debug entry.""" + with absolute_path("_data/pe/32/Dummy.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + + assert pe.debug + assert len(pe.debug) == 2 + + assert pe.debug[1].type.name == "REPRO" + assert pe.debug[1].hash.hex() == "884f504ffad2de5c25d4bbddff0f8b1fbaa2c8341f2dbdaff5f181ce1300f2e4" diff --git a/tests/pe/directory/test_delay_import.py b/tests/pe/directory/test_delay_import.py new file mode 100644 index 0000000..5a37a1f --- /dev/null +++ b/tests/pe/directory/test_delay_import.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_delay_import() -> None: + """Test the delay imports directory.""" + with absolute_path("_data/pe/32/OLEACCHOOKS.DLL").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert len(pe.delay_import) == 1 + assert list(pe.delay_import) + + assert pe.delay_import[0].name == "USER32.dll" + assert pe.delay_import["USER32.dll"] == pe.delay_import[0] + assert len(list(pe.delay_import[0])) == 2 + + assert pe.delay_import[0].functions[0].name == "RegisterWindowMessageW" + assert pe.delay_import[0].functions[0].ordinal == 755 + assert pe.delay_import[0].functions[0].address == 0x10001FBC + assert pe.delay_import[0].functions[1].name == "CallNextHookEx" + assert pe.delay_import[0].functions[1].ordinal == 31 + assert pe.delay_import[0].functions[1].address == 0x10001FA1 + + assert pe.delay_import[0]["RegisterWindowMessageW"] == pe.delay_import[0].functions[0] + assert pe.delay_import[0][755] == pe.delay_import[0].functions[0] diff --git a/tests/pe/directory/test_exception.py b/tests/pe/directory/test_exception.py new file mode 100644 index 0000000..0e64720 --- /dev/null +++ b/tests/pe/directory/test_exception.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_exception() -> None: + """Test the exception directory.""" + with absolute_path("_data/pe/32/PUNZIP.EXE").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "R4000" + assert len(pe.exceptions) == 172 + assert list(pe.exceptions) + + assert pe.exceptions[0].BeginAddress == 0x11010 + assert pe.exceptions[0].EndAddress == 0x11068 diff --git a/tests/pe/directory/test_export.py b/tests/pe/directory/test_export.py new file mode 100644 index 0000000..1912c6f --- /dev/null +++ b/tests/pe/directory/test_export.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_export() -> None: + """Test the export directory.""" + with absolute_path("_data/pe/32/NetDbgTLLoc.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert pe.exports + assert len(list(pe.exports)) == 2 + + assert pe.exports.name == "NatDbgTLLoc.dll" + assert pe.exports[1].ordinal == 1 + assert pe.exports[1].name == "OSDebug4VersionCheck" + assert pe.exports[1].address == 0x10DD + assert pe.exports[2].ordinal == 2 + assert pe.exports[2].name == "TLFunc" + assert pe.exports[2].address == 0x1590 + + assert pe.exports["OSDebug4VersionCheck"].ordinal == 1 + assert pe.exports["TLFunc"].ordinal == 2 diff --git a/tests/pe/directory/test_iat.py b/tests/pe/directory/test_iat.py new file mode 100644 index 0000000..771da74 --- /dev/null +++ b/tests/pe/directory/test_iat.py @@ -0,0 +1,40 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_iat() -> None: + """Test the IAT directory.""" + with absolute_path("_data/pe/32/NetDbgTLLoc.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert len(pe.iat) == 24 + assert list(pe.iat) == [ + 0x7C811476, + 0x7C80AA66, + 0x7C80AC28, + 0x7C801D77, + 0x7C809FA1, + 0x7C91188A, + 0x7C809794, + 0x7C80994E, + 0x7C809737, + 0x7C8092AC, + 0x7C80A417, + 0x7C859B5C, + 0x7C8017E5, + 0x0, + 0x7C360951, + 0x7C342151, + 0x7C341CBE, + 0x7C3416E9, + 0x7C38C940, + 0x7C34C45B, + 0x7C34240D, + 0x7C34C095, + 0x7C341D5F, + 0x0, + ] diff --git a/tests/pe/directory/test_import.py b/tests/pe/directory/test_import.py new file mode 100644 index 0000000..7270061 --- /dev/null +++ b/tests/pe/directory/test_import.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_import() -> None: + """Test the import directory.""" + with absolute_path("_data/pe/32/OLEACCHOOKS.DLL").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert len(pe.imports) == 12 + assert list(pe.imports) + + assert pe.imports[0].name == "msvcrt.dll" + assert pe.imports["msvcrt.dll"] == pe.imports[0] + assert len(list(pe.imports[0])) == 7 + + assert pe.imports[0].functions[0].name == "_vsnwprintf" + assert pe.imports[0].functions[0].ordinal == 1004 + + assert pe.imports[0]["_vsnwprintf"] == pe.imports[0].functions[0] + assert pe.imports[0][1004] == pe.imports[0].functions[0] diff --git a/tests/pe/directory/test_load_config.py b/tests/pe/directory/test_load_config.py new file mode 100644 index 0000000..01fe8af --- /dev/null +++ b/tests/pe/directory/test_load_config.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_load_config() -> None: + """Test the load config directory.""" + with absolute_path("_data/pe/64/comres.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "ARM64" + assert pe.load_config + + assert pe.load_config.security_cookie == 0x180004000 + assert pe.load_config.guard_flags.name == "CF_INSTRUMENTED" + + assert pe.load_config.chpe.Version == 1 diff --git a/tests/pe/directory/test_resource.py b/tests/pe/directory/test_resource.py new file mode 100644 index 0000000..e1350c4 --- /dev/null +++ b/tests/pe/directory/test_resource.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +import hashlib + +from dissect.executable.pe.c_pe import c_pe +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_resource() -> None: + """Test the resource directory.""" + with absolute_path("_data/pe/64/comres.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "ARM64" + assert pe.resources + + # Test the raw tree first + assert list(pe.resources.tree.listdir().keys()) == ["MUI", 16] + assert list(pe.resources.tree.get("MUI").listdir().keys()) == [1] + assert list(pe.resources.tree.get("MUI").get(1).listdir().keys()) == [1033] + assert pe.resources.tree.get("MUI").get(1).get(1033).address == 0x7080 + assert pe.resources.tree.get("MUI").get(1).get(1033).size == 280 + assert ( + hashlib.sha1(pe.resources.tree.get("MUI").get(1).get(1033).data).hexdigest() + == "eeee31518d39d8234ec870d0c3a7eba0eebd728d" + ) + + # Test the higher level API + assert len(list(pe.resources)) == 2 + assert len(pe.resources["MUI"]) == 1 + assert pe.resources["MUI"][0].name == 1 + assert pe.resources["MUI"][0].languages() == ["en-US"] + assert hashlib.sha1(pe.resources["MUI"][0].data()).hexdigest() == "eeee31518d39d8234ec870d0c3a7eba0eebd728d" + + assert pe.resources.vs_version_info() == { + "VS_VERSION_INFO": { + "FileVersion": "2001.12.10941.16384", + "ProductVersion": "10.0.22621.1", + "FileOS": "NT_WINDOWS32", + "FileType": "DLL", + "StringFileInfo": { + "en-US_utf-16": { + "CompanyName": "Microsoft Corporation", + "FileDescription": "COM+ Resources", + "FileVersion": "2001.12.10941.16384 (WinBuild.160101.0800)", + "InternalName": "COMRES.DLL", + "LegalCopyright": "© Microsoft Corporation. All rights reserved.", + "OriginalFilename": "COMRES.DLL", + "ProductName": "Microsoft® Windows® Operating System", + "ProductVersion": "10.0.22621.1", + } + }, + "VarFileInfo": {"Translation": ["en-US_utf-16"]}, + } + } + + +def test_resource_accelerator_table() -> None: + """Test the accelerator resource parsing.""" + with absolute_path("_data/pe/32/PUNZIP.EXE").open("rb") as fh: + pe = PE(fh) + + assert pe.resources.accelerator_table() == [ + (c_pe.VK.A, 40009, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT | c_pe.ACCEL_F.CONTROL), + (c_pe.VK.E, 40004, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT | c_pe.ACCEL_F.CONTROL), + (c_pe.VK.O, 40001, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT | c_pe.ACCEL_F.CONTROL), + (c_pe.VK.T, 40006, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT | c_pe.ACCEL_F.CONTROL), + (c_pe.VK.RETURN, 40008, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT), + (c_pe.VK.RETURN, 40002, c_pe.ACCEL_F.VIRTKEY | c_pe.ACCEL_F.NOINVERT | c_pe.ACCEL_F.ALT), + ] + + +def test_resource_string_table() -> None: + """Test the string table resource parsing.""" + with absolute_path("_data/pe/32/TpmCertResources.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.resources.string_table() == { + 7673: "https://ekop.intel.com/ekcertservice", + 9298: "http://127.0.0.1:27015/EkCertService", + 33224: "https://ekcert.spserv.microsoft.com/EKCertificate/GetEKCertificate/v1", + 58380: "http://ftpm.amd.com/pki/aia", + 59629: "https://ekcert.spserv.microsoft.com/EKCertificate/GetEKCertificate/v1", + } diff --git a/tests/pe/directory/test_security.py b/tests/pe/directory/test_security.py new file mode 100644 index 0000000..3e9ca61 --- /dev/null +++ b/tests/pe/directory/test_security.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +import hashlib + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_security() -> None: + """Test the security directory.""" + with absolute_path("_data/pe/32/UWPEnum.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert pe.security + + assert pe.security[0].revision == 512 + assert pe.security[0].type.name == "PKCS_SIGNED_DATA" + assert hashlib.sha1(pe.security[0].data).hexdigest() == "933f765d09486cc41091e2bfd305be723e9e4b53" diff --git a/tests/pe/directory/test_tls.py b/tests/pe/directory/test_tls.py new file mode 100644 index 0000000..76c0f9a --- /dev/null +++ b/tests/pe/directory/test_tls.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_tls() -> None: + """Test the TLS directory.""" + with absolute_path("_data/pe/32/mingwm10.dll").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert pe.machine.name == "I386" + assert len(pe.tls) == 2 + assert list(pe.tls) == [0x6FBC1480, 0x6FBC1430] diff --git a/tests/pe/test_pe.py b/tests/pe/test_pe.py new file mode 100644 index 0000000..6d79979 --- /dev/null +++ b/tests/pe/test_pe.py @@ -0,0 +1,56 @@ +# Most test data is from: +# - https://github.com/cubiclesoft/windows-pe-artifact-library + +from __future__ import annotations + +import datetime +from io import BytesIO + +import pytest + +from dissect.executable.exception import InvalidSignatureError +from dissect.executable.pe.pe import PE +from tests._utils import absolute_path + + +def test_pe_invalid_signature() -> None: + with pytest.raises(InvalidSignatureError): + PE(BytesIO(b"MZ" + b"\x00" * 400)) + + +def test_pe_basic() -> None: + """Test basic properties of a PE file.""" + with absolute_path("_data/pe/64/test.exe").open("rb") as fh: + pe = PE(fh) + + assert pe.is_pe() + assert not pe.is_os2() + assert pe.is_64bit() + assert not pe.is_reproducible() + + assert pe.timestamp == datetime.datetime(2024, 3, 8, 8, 6, 29, tzinfo=datetime.timezone.utc) + + +def test_pe_sections() -> None: + """Test that the PE file has the expected sections.""" + with absolute_path("_data/pe/64/test.exe").open("rb") as fh: + pe = PE(fh) + + assert [section.name for section in pe.sections] == [ + ".dissect", + ".text", + ".rdata", + ".idata", + ".rsrc", + ".reloc", + ".tls", + ] + + +def test_pe_os2() -> None: + """Test an OS/2 executable.""" + with absolute_path("_data/pe/16/DPMIRES.EXE").open("rb") as fh: + pe = PE(fh) + + assert pe.is_os2() + assert not pe.is_pe()