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 : }
|