LCOV - code coverage report
Current view: top level - src/pe - headers.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 53.3 % 538 287
Test Date: 2026-04-12:00:00:00 Functions: 64.5 % 110 71

            Line data    Source code
       1              : //! This module exposes the different headers that we can find in a PE binary.
       2              : //! It includes:
       3              : //! - [`DosHeader`]
       4              : //! - [`Header`]
       5              : //! - [`OptionalHeader`]
       6              : 
       7              : use bitflags::bitflags;
       8              : use std::marker::PhantomData;
       9              : 
      10              : use crate::common::FromFFI;
      11              : use lief_ffi as ffi;
      12              : 
      13              : /// Structure which represents the DosHeader, the **first** structure presents at the beginning of
      14              : /// a PE file.
      15              : ///
      16              : /// Most of the attributes of this structures are no longer relevant
      17              : pub struct DosHeader<'a> {
      18              :     ptr: cxx::UniquePtr<ffi::PE_DosHeader>,
      19              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      20              : }
      21              : 
      22              : impl FromFFI<ffi::PE_DosHeader> for DosHeader<'_> {
      23          169 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DosHeader>) -> Self {
      24          169 :         Self {
      25          169 :             ptr,
      26          169 :             _owner: PhantomData,
      27          169 :         }
      28          169 :     }
      29              : }
      30              : 
      31              : impl<'a> DosHeader<'a> {
      32              :     /// Magic bytes identifying a DOS/PE binary
      33          169 :     pub fn magic(&self) -> u16 {
      34          169 :         self.ptr.magic()
      35          169 :     }
      36              : 
      37          169 :     pub fn used_bytes_in_last_page(&self) -> u16 {
      38          169 :         self.ptr.used_bytes_in_last_page()
      39          169 :     }
      40              : 
      41          169 :     pub fn file_size_in_pages(&self) -> u16 {
      42          169 :         self.ptr.file_size_in_pages()
      43          169 :     }
      44              : 
      45          169 :     pub fn numberof_relocation(&self) -> u16 {
      46          169 :         self.ptr.numberof_relocation()
      47          169 :     }
      48              : 
      49          169 :     pub fn header_size_in_paragraphs(&self) -> u16 {
      50          169 :         self.ptr.header_size_in_paragraphs()
      51          169 :     }
      52              : 
      53          169 :     pub fn minimum_extra_paragraphs(&self) -> u16 {
      54          169 :         self.ptr.minimum_extra_paragraphs()
      55          169 :     }
      56              : 
      57          169 :     pub fn maximum_extra_paragraphs(&self) -> u16 {
      58          169 :         self.ptr.maximum_extra_paragraphs()
      59          169 :     }
      60              : 
      61          169 :     pub fn initial_relative_ss(&self) -> u16 {
      62          169 :         self.ptr.initial_relative_ss()
      63          169 :     }
      64              : 
      65          169 :     pub fn initial_sp(&self) -> u16 {
      66          169 :         self.ptr.initial_sp()
      67          169 :     }
      68              : 
      69          169 :     pub fn checksum(&self) -> u16 {
      70          169 :         self.ptr.checksum()
      71          169 :     }
      72              : 
      73          169 :     pub fn initial_ip(&self) -> u16 {
      74          169 :         self.ptr.initial_ip()
      75          169 :     }
      76              : 
      77          169 :     pub fn initial_relative_cs(&self) -> u16 {
      78          169 :         self.ptr.initial_relative_cs()
      79          169 :     }
      80              : 
      81          169 :     pub fn addressof_relocation_table(&self) -> u16 {
      82          169 :         self.ptr.addressof_relocation_table()
      83          169 :     }
      84              : 
      85          169 :     pub fn overlay_number(&self) -> u16 {
      86          169 :         self.ptr.overlay_number()
      87          169 :     }
      88              : 
      89          169 :     pub fn reserved(&self) -> Vec<u16> {
      90          676 :         Vec::from_iter(self.ptr.reserved().iter().map(|x| *x as u16))
      91          169 :     }
      92              : 
      93          169 :     pub fn oem_id(&self) -> u16 {
      94          169 :         self.ptr.oem_id()
      95          169 :     }
      96              : 
      97          169 :     pub fn oem_info(&self) -> u16 {
      98          169 :         self.ptr.oem_info()
      99          169 :     }
     100              : 
     101          169 :     pub fn reserved2(&self) -> Vec<u16> {
     102         1690 :         Vec::from_iter(self.ptr.reserved2().iter().map(|x| *x as u16))
     103          169 :     }
     104              : 
     105              :     /// Return the offset to the [`Header`] structure.
     106          169 :     pub fn addressof_new_exeheader(&self) -> u32 {
     107          169 :         self.ptr.addressof_new_exeheader()
     108          169 :     }
     109              : }
     110              : 
     111              : impl std::fmt::Debug for DosHeader<'_> {
     112          169 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     113          169 :         f.debug_struct("DosHeader")
     114          169 :             .field("magic", &self.magic())
     115          169 :             .field("used_bytes_in_last_page", &self.used_bytes_in_last_page())
     116          169 :             .field("file_size_in_pages", &self.file_size_in_pages())
     117          169 :             .field("numberof_relocation", &self.numberof_relocation())
     118          169 :             .field(
     119          169 :                 "header_size_in_paragraphs",
     120          169 :                 &self.header_size_in_paragraphs(),
     121          169 :             )
     122          169 :             .field("minimum_extra_paragraphs", &self.minimum_extra_paragraphs())
     123          169 :             .field("maximum_extra_paragraphs", &self.maximum_extra_paragraphs())
     124          169 :             .field("initial_relative_ss", &self.initial_relative_ss())
     125          169 :             .field("initial_sp", &self.initial_sp())
     126          169 :             .field("checksum", &self.checksum())
     127          169 :             .field("initial_ip", &self.initial_ip())
     128          169 :             .field("initial_relative_cs", &self.initial_relative_cs())
     129          169 :             .field(
     130          169 :                 "addressof_relocation_table",
     131          169 :                 &self.addressof_relocation_table(),
     132          169 :             )
     133          169 :             .field("overlay_number", &self.overlay_number())
     134          169 :             .field("reserved", &self.reserved())
     135          169 :             .field("oem_info", &self.oem_info())
     136          169 :             .field("oem_id", &self.oem_id())
     137          169 :             .field("reserved2", &self.reserved2())
     138          169 :             .field("addressof_new_exeheader", &self.addressof_new_exeheader())
     139          169 :             .finish()
     140          169 :     }
     141              : }
     142              : 
     143              : /// Structure that represents the PE header (which follows the [`DosHeader`])
     144              : pub struct Header<'a> {
     145              :     ptr: cxx::UniquePtr<ffi::PE_Header>,
     146              :     _owner: PhantomData<&'a ffi::PE_Binary>,
     147              : }
     148              : 
     149              : impl FromFFI<ffi::PE_Header> for Header<'_> {
     150          169 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Header>) -> Self {
     151          169 :         Self {
     152          169 :             ptr,
     153          169 :             _owner: PhantomData,
     154          169 :         }
     155          169 :     }
     156              : }
     157              : 
     158              : #[allow(non_camel_case_types)]
     159          260 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     160              : pub enum MachineType {
     161              :     /// Alpha AXP, 32-bit address space
     162              :     ALPHA,
     163              :     /// Alpha AXP, 64-bit address space
     164              :     ALPHA64,
     165              :     /// Matsushita AM33
     166              :     AM33,
     167              :     /// AMD x64
     168              :     AMD64,
     169              :     /// ARM little endian
     170              :     ARM,
     171              :     /// ARMv7 Thumb mode only
     172              :     ARMNT,
     173              :     /// ARMv8 in 64-bits mode
     174              :     ARM64,
     175              :     /// EFI byte code
     176              :     EBC,
     177              :     /// Intel 386 or later
     178              :     I386,
     179              :     /// Intel Itanium processor family
     180              :     IA64,
     181              :     /// LoongArch 32-bit processor family
     182              :     LOONGARCH32,
     183              :     /// LoongArch 64-bit processor family
     184              :     LOONGARCH64,
     185              :     /// Mitsubishi M32R little endian
     186              :     M32R,
     187              :     /// MIPS16
     188              :     MIPS16,
     189              :     /// MIPS with FPU
     190              :     MIPSFPU,
     191              :     /// MIPS16 with FPU
     192              :     MIPSFPU16,
     193              :     /// Power PC little endian
     194              :     POWERPC,
     195              :     /// Power PC with floating point
     196              :     POWERPCFP,
     197              :     /// Power PC big endian
     198              :     POWERPCBE,
     199              :     /// MIPS with little endian
     200              :     R4000,
     201              :     /// RISC-V 32-bit address space
     202              :     RISCV32,
     203              :     /// RISC-V 64-bit address space
     204              :     RISCV64,
     205              :     /// RISC-V 128-bit address space
     206              :     RISCV128,
     207              :     /// Hitachi SH3
     208              :     SH3,
     209              :     /// Hitachi SH3 DSP
     210              :     SH3DSP,
     211              :     /// Hitachi SH4
     212              :     SH4,
     213              :     /// Hitachi SH5
     214              :     SH5,
     215              :     /// ARM or Thumb
     216              :     THUMB,
     217              :     /// MIPS little-endian WCE v2
     218              :     WCEMIPSV2,
     219              :     ARM64EC,
     220              :     ARM64X,
     221              :     CHPE_X86,
     222              :     UNKNOWN(u32),
     223              : }
     224              : 
     225              : impl From<u32> for MachineType {
     226          260 :     fn from(value: u32) -> Self {
     227          260 :         match value {
     228            0 :             0x00000184 => MachineType::ALPHA,
     229            0 :             0x00000284 => MachineType::ALPHA64,
     230            0 :             0x000001d3 => MachineType::AM33,
     231          156 :             0x00008664 => MachineType::AMD64,
     232            0 :             0x000001c0 => MachineType::ARM,
     233            0 :             0x000001c4 => MachineType::ARMNT,
     234           52 :             0x0000aa64 => MachineType::ARM64,
     235            0 :             0x00000ebc => MachineType::EBC,
     236           52 :             0x0000014c => MachineType::I386,
     237            0 :             0x00000200 => MachineType::IA64,
     238            0 :             0x00006232 => MachineType::LOONGARCH32,
     239            0 :             0x00006264 => MachineType::LOONGARCH64,
     240            0 :             0x00009041 => MachineType::M32R,
     241            0 :             0x00000266 => MachineType::MIPS16,
     242            0 :             0x00000366 => MachineType::MIPSFPU,
     243            0 :             0x00000466 => MachineType::MIPSFPU16,
     244            0 :             0x000001f0 => MachineType::POWERPC,
     245            0 :             0x000001f1 => MachineType::POWERPCFP,
     246            0 :             0x000001f2 => MachineType::POWERPCBE,
     247            0 :             0x00000166 => MachineType::R4000,
     248            0 :             0x00005032 => MachineType::RISCV32,
     249            0 :             0x00005064 => MachineType::RISCV64,
     250            0 :             0x00005128 => MachineType::RISCV128,
     251            0 :             0x000001a2 => MachineType::SH3,
     252            0 :             0x000001a3 => MachineType::SH3DSP,
     253            0 :             0x000001a6 => MachineType::SH4,
     254            0 :             0x000001a8 => MachineType::SH5,
     255            0 :             0x000001c2 => MachineType::THUMB,
     256            0 :             0x00000169 => MachineType::WCEMIPSV2,
     257            0 :             0x0000a641 => MachineType::ARM64EC,
     258            0 :             0x0000a64e => MachineType::ARM64X,
     259            0 :             0x00003a64 => MachineType::CHPE_X86,
     260            0 :             _ => MachineType::UNKNOWN(value),
     261              :         }
     262          260 :     }
     263              : }
     264              : impl From<MachineType> for u32 {
     265            0 :     fn from(value: MachineType) -> u32 {
     266            0 :         match value {
     267            0 :             MachineType::ALPHA => 0x184,
     268            0 :             MachineType::ALPHA64 => 0x284,
     269            0 :             MachineType::AM33 => 0x000001d3,
     270            0 :             MachineType::AMD64 => 0x00008664,
     271            0 :             MachineType::ARM => 0x000001c0,
     272            0 :             MachineType::ARMNT => 0x000001c4,
     273            0 :             MachineType::ARM64 => 0x0000aa64,
     274            0 :             MachineType::EBC => 0x00000ebc,
     275            0 :             MachineType::I386 => 0x0000014c,
     276            0 :             MachineType::IA64 => 0x00000200,
     277            0 :             MachineType::LOONGARCH32 => 0x6232,
     278            0 :             MachineType::LOONGARCH64 => 0x6264,
     279            0 :             MachineType::M32R => 0x00009041,
     280            0 :             MachineType::MIPS16 => 0x00000266,
     281            0 :             MachineType::MIPSFPU => 0x00000366,
     282            0 :             MachineType::MIPSFPU16 => 0x00000466,
     283            0 :             MachineType::POWERPC => 0x000001f0,
     284            0 :             MachineType::POWERPCFP => 0x000001f1,
     285            0 :             MachineType::POWERPCBE => 0x000001f2,
     286            0 :             MachineType::R4000 => 0x00000166,
     287            0 :             MachineType::RISCV32 => 0x00005032,
     288            0 :             MachineType::RISCV64 => 0x00005064,
     289            0 :             MachineType::RISCV128 => 0x00005128,
     290            0 :             MachineType::SH3 => 0x000001a2,
     291            0 :             MachineType::SH3DSP => 0x000001a3,
     292            0 :             MachineType::SH4 => 0x000001a6,
     293            0 :             MachineType::SH5 => 0x000001a8,
     294            0 :             MachineType::THUMB => 0x000001c2,
     295            0 :             MachineType::WCEMIPSV2 => 0x00000169,
     296            0 :             MachineType::ARM64EC => 0x0000a641,
     297            0 :             MachineType::ARM64X => 0x0000a64e,
     298            0 :             MachineType::CHPE_X86 => 0x00003a64,
     299            0 :             MachineType::UNKNOWN(_) => 0,
     300              :         }
     301            0 :     }
     302              : }
     303              : 
     304            0 : bitflags! {
     305          169 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     306            0 :     pub struct Characteristics: u32 {
     307            0 :         const NONE = 0x0;
     308            0 : 
     309            0 :         /// The file does not contain base relocations and must be loaded at its preferred base.
     310            0 :         /// If this cannot be done, the loader will error.
     311            0 :         const RELOCS_STRIPPED = 0x1;
     312            0 : 
     313            0 :         /// File is executable (i.e. no unresolved externel references).
     314            0 :         const EXECUTABLE_IMAGE = 0x2;
     315            0 : 
     316            0 :         /// COFF line numbers have been stripped. This is deprecated and should be 0
     317            0 :         const LINE_NUMS_STRIPPED = 0x4;
     318            0 : 
     319            0 :         /// COFF symbol table entries for local symbols have been removed.
     320            0 :         /// This is deprecated and should be 0.
     321            0 :         const LOCAL_SYMS_STRIPPED = 0x8;
     322            0 : 
     323            0 :         /// Aggressively trim working set. This is deprecated and must be 0.
     324            0 :         const AGGRESSIVE_WS_TRIM = 0x10;
     325            0 : 
     326            0 :         /// App can handle >2gb addresses
     327            0 :         const LARGE_ADDRESS_AWARE = 0x20;
     328            0 : 
     329            0 :         /// Little endian: the LSB precedes the MSB in memory. This is deprecated and should be 0.
     330            0 :         const BYTES_REVERSED_LO = 0x80;
     331            0 : 
     332            0 :         /// Machine is based on a 32bit word architecture.
     333            0 :         const NEED_32BIT_MACHINE = 0x100;
     334            0 : 
     335            0 :         /// Debugging info has been removed.
     336            0 :         const DEBUG_STRIPPED = 0x200;
     337            0 : 
     338            0 :         /// If the image is on removable media, fully load it and copy it to swap.
     339            0 :         const REMOVABLE_RUN_FROM_SWAP = 0x400;
     340            0 : 
     341            0 :         /// If the image is on network media, fully load it and copy it to swap.
     342            0 :         const NET_RUN_FROM_SWAP = 0x800;
     343            0 : 
     344            0 :         /// The image file is a system file, not a user program.
     345            0 :         const SYSTEM = 0x1000;
     346            0 : 
     347            0 :         /// The image file is a DLL.
     348            0 :         const DLL = 0x2000;
     349            0 : 
     350            0 :         /// This file should only be run on a uniprocessor machine.
     351            0 :         const UP_SYSTEM_ONLY = 0x4000;
     352            0 : 
     353            0 :         /// Big endian: the MSB precedes the LSB in memory. This is deprecated
     354            0 :         const BYTES_REVERSED_HI = 0x8000;
     355            0 :     }
     356            0 : }
     357              : 
     358              : impl std::fmt::Display for Characteristics {
     359            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     360            0 :         bitflags::parser::to_writer(self, f)
     361            0 :     }
     362              : }
     363              : 
     364              : impl From<u32> for Characteristics {
     365          169 :     fn from(value: u32) -> Self {
     366          169 :         Characteristics::from_bits_truncate(value)
     367          169 :     }
     368              : }
     369              : impl From<Characteristics> for u32 {
     370            0 :     fn from(value: Characteristics) -> Self {
     371            0 :         value.bits()
     372            0 :     }
     373              : }
     374              : 
     375              : impl Header<'_> {
     376              :     /// PE signature (should be `PE\0\0`)
     377            0 :     pub fn signature(&self) -> Vec<u8> {
     378            0 :         Vec::from(self.ptr.signature().as_slice())
     379            0 :             .iter()
     380            0 :             .map(|&v: &u64| v as u8)
     381            0 :             .collect()
     382            0 :     }
     383              : 
     384              :     /// The targeted machine architecture like ARM, x86, AMD64, ...
     385          169 :     pub fn machine(&self) -> MachineType {
     386          169 :         MachineType::from(self.ptr.machine())
     387          169 :     }
     388              : 
     389              :     /// The number of sections in the binary.
     390          169 :     pub fn nb_sections(&self) -> u16 {
     391          169 :         self.ptr.numberof_sections()
     392          169 :     }
     393              : 
     394              :     /// The low 32 bits of the number of seconds since January 1, 1970.
     395              :     /// It **indicates** when the file was created.
     396          169 :     pub fn time_date_stamp(&self) -> u32 {
     397          169 :         self.ptr.time_date_stamp()
     398          169 :     }
     399              : 
     400              :     /// The offset of the **COFF** symbol table.
     401              :     /// This value should be zero for an image because COFF debugging information is deprecated on
     402              :     /// in PE binary
     403          169 :     pub fn pointerto_symbol_table(&self) -> u32 {
     404          169 :         self.ptr.pointerto_symbol_table()
     405          169 :     }
     406              : 
     407              :     /// The number of entries in the symbol table. This data can be used to locate the string table
     408              :     /// which immediately follows the symbol table.
     409              :     ///
     410              :     /// This value should be zero for an image because COFF debugging information is deprecated in
     411              :     /// PE binary
     412          169 :     pub fn numberof_symbols(&self) -> u32 {
     413          169 :         self.ptr.numberof_symbols()
     414          169 :     }
     415              : 
     416              :     /// Size of the OptionalHeader **AND** the data directories which follows this header.
     417              :     ///
     418              :     /// This value is equivalent to:
     419              :     /// `sizeof(pe_optional_header) + NB_DATA_DIR * sizeof(data_directory)`
     420              :     ///
     421              :     /// This size **should** be either:
     422              :     /// * 0xE0 (224) for a PE32  (32 bits)
     423              :     /// * 0xF0 (240) for a PE32+ (64 bits)
     424          169 :     pub fn sizeof_optional_header(&self) -> u16 {
     425          169 :         self.ptr.sizeof_optional_header()
     426          169 :     }
     427              : 
     428              :     /// Characteristics of the binary like whether it is a DLL or an executable
     429          169 :     pub fn characteristics(&self) -> Characteristics {
     430          169 :         Characteristics::from(self.ptr.characteristics())
     431          169 :     }
     432              : 
     433            0 :     pub fn set_machine(&mut self, machine: MachineType) {
     434            0 :         self.ptr.pin_mut().set_machine(u32::from(machine));
     435            0 :     }
     436              : 
     437            0 :     pub fn set_numberof_sections(&mut self, value: u16) {
     438            0 :         self.ptr.pin_mut().set_numberof_sections(value);
     439            0 :     }
     440              : 
     441            0 :     pub fn set_time_date_stamp(&mut self, value: u32) {
     442            0 :         self.ptr.pin_mut().set_time_date_stamp(value);
     443            0 :     }
     444              : 
     445            0 :     pub fn set_pointerto_symbol_table(&mut self, value: u32) {
     446            0 :         self.ptr.pin_mut().set_pointerto_symbol_table(value);
     447            0 :     }
     448              : 
     449            0 :     pub fn set_numberof_symbols(&mut self, value: u32) {
     450            0 :         self.ptr.pin_mut().set_numberof_symbols(value);
     451            0 :     }
     452              : 
     453            0 :     pub fn set_sizeof_optional_header(&mut self, value: u16) {
     454            0 :         self.ptr.pin_mut().set_sizeof_optional_header(value);
     455            0 :     }
     456              : 
     457            0 :     pub fn set_characteristics(&mut self, characteristics: Characteristics) {
     458            0 :         self.ptr
     459            0 :             .pin_mut()
     460            0 :             .set_characteristics(characteristics.bits());
     461            0 :     }
     462              : 
     463            0 :     pub fn add_characteristic(&mut self, characteristics: Characteristics) {
     464            0 :         self.ptr
     465            0 :             .pin_mut()
     466            0 :             .add_characteristic(characteristics.bits());
     467            0 :     }
     468              : 
     469            0 :     pub fn remove_characteristic(&mut self, characteristics: Characteristics) {
     470            0 :         self.ptr
     471            0 :             .pin_mut()
     472            0 :             .remove_characteristic(characteristics.bits());
     473            0 :     }
     474              : }
     475              : 
     476              : impl std::fmt::Debug for Header<'_> {
     477          169 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     478          169 :         f.debug_struct("Header")
     479          169 :             .field("machine", &self.machine())
     480          169 :             .field("nb_sections", &self.nb_sections())
     481          169 :             .field("time_date_stamp", &self.time_date_stamp())
     482          169 :             .field("pointerto_symbol_table", &self.pointerto_symbol_table())
     483          169 :             .field("numberof_symbols", &self.numberof_symbols())
     484          169 :             .field("sizeof_optional_header", &self.sizeof_optional_header())
     485          169 :             .field("characteristics", &self.characteristics())
     486          169 :             .finish()
     487          169 :     }
     488              : }
     489              : 
     490              : /// Structure which represents the PE OptionalHeader (after [`Header`]).
     491              : ///
     492              : /// Note that the term *optional* comes from the COFF specifications but this header is
     493              : /// **mandatory** for a PE binary.
     494              : pub struct OptionalHeader<'a> {
     495              :     ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>,
     496              :     _owner: PhantomData<&'a ffi::PE_Binary>,
     497              : }
     498              : 
     499              : impl FromFFI<ffi::PE_OptionalHeader> for OptionalHeader<'_> {
     500          182 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>) -> Self {
     501          182 :         Self {
     502          182 :             ptr,
     503          182 :             _owner: PhantomData,
     504          182 :         }
     505          182 :     }
     506              : }
     507              : 
     508            0 : bitflags! {
     509          169 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     510            0 :     pub struct DllCharacteristics: u32 {
     511            0 :         /// ASLR with 64 bit address space.
     512            0 :         const HIGH_ENTROPY_VA = 0x20;
     513            0 : 
     514            0 :         /// DLL can be relocated at load time.
     515            0 :         const DYNAMIC_BASE = 0x40;
     516            0 : 
     517            0 :         /// Code integrity checks are enforced.
     518            0 :         const FORCE_INTEGRITY = 0x80;
     519            0 : 
     520            0 :         /// Image is NX compatible.
     521            0 :         const NX_COMPAT = 0x100;
     522            0 : 
     523            0 :         /// Isolation aware, but do not isolate the image.
     524            0 :         const NO_ISOLATION = 0x200;
     525            0 : 
     526            0 :         /// Does not use structured exception handling (SEH).
     527            0 :         /// No SEH handler may be called in this image.
     528            0 :         const NO_SEH = 0x400;
     529            0 : 
     530            0 :         /// Do not bind the image.
     531            0 :         const NO_BIND = 0x800;
     532            0 : 
     533            0 :         /// Image should execute in an AppContainer.
     534            0 :         const APPCONTAINER = 0x1000;
     535            0 : 
     536            0 :         /// A WDM driver.
     537            0 :         const WDM_DRIVER = 0x2000;
     538            0 : 
     539            0 :         /// Image supports Control Flow Guard.
     540            0 :         const GUARD_CF = 0x4000;
     541            0 : 
     542            0 :         /// Terminal Server aware.
     543            0 :         const TERMINAL_SERVER_AWARE = 0x8000;
     544            0 :     }
     545            0 : }
     546              : 
     547              : impl From<u32> for DllCharacteristics {
     548          169 :     fn from(value: u32) -> Self {
     549          169 :         DllCharacteristics::from_bits_truncate(value)
     550          169 :     }
     551              : }
     552              : impl From<DllCharacteristics> for u32 {
     553            0 :     fn from(value: DllCharacteristics) -> Self {
     554            0 :         value.bits()
     555            0 :     }
     556              : }
     557              : impl std::fmt::Display for DllCharacteristics {
     558            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     559            0 :         bitflags::parser::to_writer(self, f)
     560            0 :     }
     561              : }
     562              : 
     563              : #[allow(non_camel_case_types)]
     564          169 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     565              : pub enum Subsystem {
     566              :     /// Device drivers and native Windows processes
     567              :     NATIVE,
     568              : 
     569              :     /// The Windows GUI subsystem.
     570              :     WINDOWS_GUI,
     571              : 
     572              :     /// The Windows character subsystem.
     573              :     WINDOWS_CUI,
     574              : 
     575              :     /// The OS/2 character subsytem.
     576              :     OS2_CUI,
     577              : 
     578              :     /// The POSIX character subsystem.
     579              :     POSIX_CUI,
     580              : 
     581              :     /// Native Windows 9x driver.
     582              :     NATIVE_WINDOWS,
     583              : 
     584              :     /// Windows CE.
     585              :     WINDOWS_CE_GUI,
     586              : 
     587              :     /// An EFI application.
     588              :     EFI_APPLICATION,
     589              : 
     590              :     /// An EFI driver with boot services.
     591              :     EFI_BOOT_SERVICE_DRIVER,
     592              : 
     593              :     /// An EFI driver with run-time services.
     594              :     EFI_RUNTIME_DRIVER,
     595              : 
     596              :     /// An EFI ROM image.
     597              :     EFI_ROM,
     598              : 
     599              :     /// XBOX
     600              :     XBOX,
     601              : 
     602              :     /// A BCD application.
     603              :     WINDOWS_BOOT_APPLICATION,
     604              : 
     605              :     /// Security Metadata Containers
     606              :     XBOX_CODE_CATALOG,
     607              : 
     608              :     /// An unknown subsystem.
     609              :     UNKNOWN(u64),
     610              : }
     611              : 
     612              : impl From<u64> for Subsystem {
     613          169 :     fn from(value: u64) -> Self {
     614          169 :         match value {
     615           13 :             0x00000001 => Subsystem::NATIVE,
     616           91 :             0x00000002 => Subsystem::WINDOWS_GUI,
     617           65 :             0x00000003 => Subsystem::WINDOWS_CUI,
     618            0 :             0x00000005 => Subsystem::OS2_CUI,
     619            0 :             0x00000007 => Subsystem::POSIX_CUI,
     620            0 :             0x00000008 => Subsystem::NATIVE_WINDOWS,
     621            0 :             0x00000009 => Subsystem::WINDOWS_CE_GUI,
     622            0 :             0x0000000a => Subsystem::EFI_APPLICATION,
     623            0 :             0x0000000b => Subsystem::EFI_BOOT_SERVICE_DRIVER,
     624            0 :             0x0000000c => Subsystem::EFI_RUNTIME_DRIVER,
     625            0 :             0x0000000d => Subsystem::EFI_ROM,
     626            0 :             0x0000000e => Subsystem::XBOX,
     627            0 :             0x00000010 => Subsystem::WINDOWS_BOOT_APPLICATION,
     628            0 :             0x00000011 => Subsystem::XBOX_CODE_CATALOG,
     629            0 :             _ => Subsystem::UNKNOWN(value),
     630              :         }
     631          169 :     }
     632              : }
     633              : impl From<Subsystem> for u64 {
     634            0 :     fn from(value: Subsystem) -> u64 {
     635            0 :         match value {
     636            0 :             Subsystem::NATIVE => 0x00000001,
     637            0 :             Subsystem::WINDOWS_GUI => 0x00000002,
     638            0 :             Subsystem::WINDOWS_CUI => 0x00000003,
     639            0 :             Subsystem::OS2_CUI => 0x00000005,
     640            0 :             Subsystem::POSIX_CUI => 0x00000007,
     641            0 :             Subsystem::NATIVE_WINDOWS => 0x00000008,
     642            0 :             Subsystem::WINDOWS_CE_GUI => 0x00000009,
     643            0 :             Subsystem::EFI_APPLICATION => 0x0000000a,
     644            0 :             Subsystem::EFI_BOOT_SERVICE_DRIVER => 0x0000000b,
     645            0 :             Subsystem::EFI_RUNTIME_DRIVER => 0x0000000c,
     646            0 :             Subsystem::EFI_ROM => 0x0000000d,
     647            0 :             Subsystem::XBOX => 0x0000000e,
     648            0 :             Subsystem::WINDOWS_BOOT_APPLICATION => 0x00000010,
     649            0 :             Subsystem::XBOX_CODE_CATALOG => 0x00000011,
     650            0 :             Subsystem::UNKNOWN(_) => 0,
     651              :         }
     652            0 :     }
     653              : }
     654              : 
     655              : impl OptionalHeader<'_> {
     656              :     /// Magic number identifying PE32 (0x10b) or PE32+ (0x20b)
     657            0 :     pub fn magic(&self) -> u32 {
     658            0 :         self.ptr.magic() as u32
     659            0 :     }
     660              : 
     661              :     /// The linker major version
     662          169 :     pub fn major_linker_version(&self) -> u8 {
     663          169 :         self.ptr.major_linker_version()
     664          169 :     }
     665              : 
     666              :     /// The linker minor version
     667          169 :     pub fn minor_linker_version(&self) -> u8 {
     668          169 :         self.ptr.minor_linker_version()
     669          169 :     }
     670              : 
     671              :     /// The size of the code `.text` section or the sum of
     672              :     /// all the sections that contain code (i.e. sections with `CNT_CODE` flag)
     673          169 :     pub fn sizeof_code(&self) -> u32 {
     674          169 :         self.ptr.sizeof_code()
     675          169 :     }
     676              : 
     677              :     /// The size of the initialized data which are usually located in the `.data` section.
     678              :     /// If the initialized data are split across multiple sections, it is the sum of the sections.
     679          169 :     pub fn sizeof_initialized_data(&self) -> u32 {
     680          169 :         self.ptr.sizeof_initialized_data()
     681          169 :     }
     682              : 
     683              :     /// The size of the uninitialized data which are usually located in the `.bss` section.
     684              :     /// If the uninitialized data are split across multiple sections, it is the sum of the sections.
     685          169 :     pub fn sizeof_uninitialized_data(&self) -> u32 {
     686          169 :         self.ptr.sizeof_uninitialized_data()
     687          169 :     }
     688              : 
     689              :     /// The address of the entry point relative to the image base when the executable file is
     690              :     /// loaded into memory. For program images, this is the starting address. For device
     691              :     /// drivers, this is the address of the initialization function.
     692              :     ///
     693              :     /// An entry point is optional for DLLs. When no entry point is present, this field must be zero.
     694          169 :     pub fn addressof_entrypoint(&self) -> u32 {
     695          169 :         self.ptr.addressof_entrypoint()
     696          169 :     }
     697              : 
     698              :     /// Address relative to the imagebase where the binary's code starts.
     699          169 :     pub fn baseof_code(&self) -> u32 {
     700          169 :         self.ptr.baseof_code()
     701          169 :     }
     702              : 
     703              :     /// Address relative to the imagebase where the binary's data starts.
     704              :     ///
     705              :     /// <div class="warning">This value is not present for PE64 files</div>
     706          169 :     pub fn baseof_data(&self) -> u32 {
     707          169 :         self.ptr.baseof_data()
     708          169 :     }
     709              : 
     710              :     /// The preferred base address when mapping the binary in memory
     711          182 :     pub fn imagebase(&self) -> u64 {
     712          182 :         self.ptr.imagebase()
     713          182 :     }
     714              : 
     715              :     /// The alignment (in bytes) of sections when they are loaded into memory.
     716              :     ///
     717              :     /// It must be greater than or equal to file_alignment and
     718              :     /// the default is the page size for the architecture.
     719          169 :     pub fn section_alignment(&self) -> u32 {
     720          169 :         self.ptr.section_alignment()
     721          169 :     }
     722              : 
     723              :     /// The section's file alignment. This value must be a power of 2 between 512 and 64K.
     724              :     /// The default value is usually 512
     725          169 :     pub fn file_alignment(&self) -> u32 {
     726          169 :         self.ptr.file_alignment()
     727          169 :     }
     728              : 
     729              :     /// The **major** version number of the required operating system
     730          169 :     pub fn major_operating_system_version(&self) -> u16 {
     731          169 :         self.ptr.major_operating_system_version()
     732          169 :     }
     733              : 
     734              :     /// The **minor** version number of the required operating system
     735          169 :     pub fn minor_operating_system_version(&self) -> u16 {
     736          169 :         self.ptr.minor_operating_system_version()
     737          169 :     }
     738              : 
     739              :     /// The major version number of the image
     740          169 :     pub fn major_image_version(&self) -> u16 {
     741          169 :         self.ptr.major_image_version()
     742          169 :     }
     743              : 
     744              :     /// The minor version number of the image
     745          169 :     pub fn minor_image_version(&self) -> u16 {
     746          169 :         self.ptr.minor_image_version()
     747          169 :     }
     748              : 
     749              :     /// The major version number of the subsystem
     750          169 :     pub fn major_subsystem_version(&self) -> u16 {
     751          169 :         self.ptr.major_subsystem_version()
     752          169 :     }
     753              : 
     754              :     /// The minor version number of the subsystem
     755          169 :     pub fn minor_subsystem_version(&self) -> u16 {
     756          169 :         self.ptr.minor_subsystem_version()
     757          169 :     }
     758              : 
     759              :     /// According to the official PE specifications, this value
     760              :     /// is reserved and **should** be 0.
     761          169 :     pub fn win32_version_value(&self) -> u32 {
     762          169 :         self.ptr.win32_version_value()
     763          169 :     }
     764              : 
     765              :     /// The size (in bytes) of the image, including all headers, as the image is loaded in memory.
     766              :     ///
     767              :     /// It must be a multiple of section_alignment and should match [`crate::pe::Binary::virtual_size`]
     768          169 :     pub fn sizeof_image(&self) -> u32 {
     769          169 :         self.ptr.sizeof_image()
     770          169 :     }
     771              : 
     772              :     /// Size of the DosHeader + PE Header + Section headers rounded up to a multiple of the file_alignment
     773          169 :     pub fn sizeof_headers(&self) -> u32 {
     774          169 :         self.ptr.sizeof_headers()
     775          169 :     }
     776              : 
     777              :     /// The image file checksum. The algorithm for computing the checksum is incorporated into `IMAGHELP.DLL`.
     778              :     ///
     779              :     /// The following are checked for validation at load time all **drivers**, any **DLL loaded at boot**
     780              :     /// time, and any **DLL** that is loaded into a **critical** Windows process.
     781          338 :     pub fn checksum(&self) -> u32 {
     782          338 :         self.ptr.checksum()
     783          338 :     }
     784              : 
     785              :     /// Target subsystem like Driver, XBox, Windows GUI, ...
     786          169 :     pub fn subsystem(&self) -> Subsystem {
     787          169 :         Subsystem::from(self.ptr.subsystem())
     788          169 :     }
     789              : 
     790              :     /// Some characteristics of the underlying binary like the support of the PIE.
     791              :     /// The prefix ``dll`` comes from the official PE specifications but these characteristics
     792              :     /// are also used for **executables**
     793          169 :     pub fn dll_characteristics(&self) -> DllCharacteristics {
     794          169 :         DllCharacteristics::from(self.ptr.dll_characteristics())
     795          169 :     }
     796              : 
     797              :     /// Size of the stack to reserve when loading the PE binary
     798              :     ///
     799              :     /// Only [`OptionalHeader::sizeof_stack_commit`] is committed, the rest
     800              :     /// available one page at a time until the reserve size is reached.
     801          169 :     pub fn sizeof_stack_reserve(&self) -> u64 {
     802          169 :         self.ptr.sizeof_stack_reserve()
     803          169 :     }
     804              : 
     805              :     /// Size of the stack to commit
     806          169 :     pub fn sizeof_stack_commit(&self) -> u64 {
     807          169 :         self.ptr.sizeof_stack_commit()
     808          169 :     }
     809              : 
     810              :     /// Size of the heap to reserve when loading the PE binary
     811          169 :     pub fn sizeof_heap_reserve(&self) -> u64 {
     812          169 :         self.ptr.sizeof_heap_reserve()
     813          169 :     }
     814              : 
     815              :     /// Size of the stack to commit
     816          169 :     pub fn sizeof_heap_commit(&self) -> u64 {
     817          169 :         self.ptr.sizeof_heap_commit()
     818          169 :     }
     819              : 
     820              :     /// According to the PE specifications, this value is *reserved* and **should** be 0.
     821          169 :     pub fn loader_flags(&self) -> u32 {
     822          169 :         self.ptr.loader_flags()
     823          169 :     }
     824              : 
     825              :     /// The number of DataDirectory that follow this header.
     826          169 :     pub fn numberof_rva_and_size(&self) -> u32 {
     827          169 :         self.ptr.numberof_rva_and_size()
     828          169 :     }
     829              : 
     830            0 :     pub fn set_addressof_entrypoint(&mut self, value: u32) {
     831            0 :         self.ptr.pin_mut().set_addressof_entrypoint(value)
     832            0 :     }
     833              : 
     834            0 :     pub fn set_imagebase(&mut self, value: u64) {
     835            0 :         self.ptr.pin_mut().set_imagebase(value)
     836            0 :     }
     837              : 
     838              :     /// Add a DLL characteristic
     839            0 :     pub fn add_dll_characteristic(&mut self, c: DllCharacteristics) {
     840            0 :         self.ptr.pin_mut().add_dll_characteristic(c.bits());
     841            0 :     }
     842              : 
     843              :     /// Remove a DLL characteristic
     844            0 :     pub fn remove_dll_characteristic(&mut self, c: DllCharacteristics) {
     845            0 :         self.ptr.pin_mut().remove_dll_characteristic(c.bits());
     846            0 :     }
     847              : }
     848              : 
     849              : impl std::fmt::Debug for OptionalHeader<'_> {
     850          169 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     851          169 :         f.debug_struct("OptionalHeader")
     852          169 :             .field("major_linker_version", &self.major_linker_version())
     853          169 :             .field("minor_linker_version", &self.minor_linker_version())
     854          169 :             .field("sizeof_code", &self.sizeof_code())
     855          169 :             .field("sizeof_initialized_data", &self.sizeof_initialized_data())
     856          169 :             .field(
     857          169 :                 "sizeof_uninitialized_data",
     858          169 :                 &self.sizeof_uninitialized_data(),
     859          169 :             )
     860          169 :             .field("addressof_entrypoint", &self.addressof_entrypoint())
     861          169 :             .field("baseof_code", &self.baseof_code())
     862          169 :             .field("baseof_data", &self.baseof_data())
     863          169 :             .field("imagebase", &self.imagebase())
     864          169 :             .field("section_alignment", &self.section_alignment())
     865          169 :             .field("file_alignment", &self.file_alignment())
     866          169 :             .field(
     867          169 :                 "major_operating_system_version",
     868          169 :                 &self.major_operating_system_version(),
     869          169 :             )
     870          169 :             .field(
     871          169 :                 "minor_operating_system_version",
     872          169 :                 &self.minor_operating_system_version(),
     873          169 :             )
     874          169 :             .field("major_image_version", &self.major_image_version())
     875          169 :             .field("minor_image_version", &self.minor_image_version())
     876          169 :             .field("major_subsystem_version", &self.major_subsystem_version())
     877          169 :             .field("minor_subsystem_version", &self.minor_subsystem_version())
     878          169 :             .field("win32_version_value", &self.win32_version_value())
     879          169 :             .field("sizeof_image", &self.sizeof_image())
     880          169 :             .field("sizeof_headers", &self.sizeof_headers())
     881          169 :             .field("checksum", &self.checksum())
     882          169 :             .field("subsystem", &self.subsystem())
     883          169 :             .field("dll_characteristics", &self.dll_characteristics())
     884          169 :             .field("sizeof_stack_reserve", &self.sizeof_stack_reserve())
     885          169 :             .field("sizeof_stack_commit", &self.sizeof_stack_commit())
     886          169 :             .field("sizeof_heap_reserve", &self.sizeof_heap_reserve())
     887          169 :             .field("sizeof_heap_commit", &self.sizeof_heap_commit())
     888          169 :             .field("loader_flags", &self.loader_flags())
     889          169 :             .field("numberof_rva_and_size", &self.numberof_rva_and_size())
     890          169 :             .finish()
     891          169 :     }
     892              : }
        

Generated by: LCOV version 2.1-1