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