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