wraith/structures/pe/
section_header.rs

1//! Section header (IMAGE_SECTION_HEADER)
2
3pub const SECTION_NAME_SIZE: usize = 8;
4
5#[repr(C)]
6#[derive(Debug, Clone, Copy)]
7pub struct SectionHeader {
8    pub name: [u8; SECTION_NAME_SIZE],
9    pub virtual_size: u32,
10    pub virtual_address: u32,
11    pub size_of_raw_data: u32,
12    pub pointer_to_raw_data: u32,
13    pub pointer_to_relocations: u32,
14    pub pointer_to_linenumbers: u32,
15    pub number_of_relocations: u16,
16    pub number_of_linenumbers: u16,
17    pub characteristics: u32,
18}
19
20// section characteristics flags
21pub const IMAGE_SCN_CNT_CODE: u32 = 0x00000020;
22pub const IMAGE_SCN_CNT_INITIALIZED_DATA: u32 = 0x00000040;
23pub const IMAGE_SCN_CNT_UNINITIALIZED_DATA: u32 = 0x00000080;
24pub const IMAGE_SCN_MEM_EXECUTE: u32 = 0x20000000;
25pub const IMAGE_SCN_MEM_READ: u32 = 0x40000000;
26pub const IMAGE_SCN_MEM_WRITE: u32 = 0x80000000;
27pub const IMAGE_SCN_MEM_DISCARDABLE: u32 = 0x02000000;
28
29/// macro for generating section characteristic check methods with `#[must_use]`
30macro_rules! define_section_check {
31    ($(#[$attr:meta])* $name:ident, $flag:ident) => {
32        $(#[$attr])*
33        #[must_use]
34        pub fn $name(&self) -> bool {
35            self.characteristics & $flag != 0
36        }
37    };
38}
39
40impl SectionHeader {
41    /// get section name as string (may not be null-terminated)
42    #[must_use]
43    pub fn name_str(&self) -> &str {
44        let end = self
45            .name
46            .iter()
47            .position(|&b| b == 0)
48            .unwrap_or(SECTION_NAME_SIZE);
49        core::str::from_utf8(&self.name[..end]).unwrap_or("")
50    }
51
52    define_section_check!(
53        /// check if section is executable
54        is_executable, IMAGE_SCN_MEM_EXECUTE
55    );
56
57    define_section_check!(
58        /// check if section is readable
59        is_readable, IMAGE_SCN_MEM_READ
60    );
61
62    define_section_check!(
63        /// check if section is writable
64        is_writable, IMAGE_SCN_MEM_WRITE
65    );
66
67    define_section_check!(
68        /// check if section contains code
69        contains_code, IMAGE_SCN_CNT_CODE
70    );
71
72    define_section_check!(
73        /// check if section contains initialized data
74        contains_initialized_data, IMAGE_SCN_CNT_INITIALIZED_DATA
75    );
76
77    define_section_check!(
78        /// check if section contains uninitialized data
79        contains_uninitialized_data, IMAGE_SCN_CNT_UNINITIALIZED_DATA
80    );
81
82    define_section_check!(
83        /// check if section is discardable
84        is_discardable, IMAGE_SCN_MEM_DISCARDABLE
85    );
86
87    /// convert section characteristics to memory protection flags
88    #[must_use]
89    pub fn to_protection(&self) -> u32 {
90        let r = self.is_readable();
91        let w = self.is_writable();
92        let x = self.is_executable();
93
94        // PAGE_* constants
95        const PAGE_NOACCESS: u32 = 0x01;
96        const PAGE_READONLY: u32 = 0x02;
97        const PAGE_READWRITE: u32 = 0x04;
98        const PAGE_EXECUTE: u32 = 0x10;
99        const PAGE_EXECUTE_READ: u32 = 0x20;
100        const PAGE_EXECUTE_READWRITE: u32 = 0x40;
101
102        match (r, w, x) {
103            (false, false, false) => PAGE_NOACCESS,
104            (true, false, false) => PAGE_READONLY,
105            (true, true, false) => PAGE_READWRITE,
106            (false, false, true) => PAGE_EXECUTE,
107            (true, false, true) => PAGE_EXECUTE_READ,
108            (true, true, true) => PAGE_EXECUTE_READWRITE,
109            (false, true, false) => PAGE_READWRITE,          // fallback
110            (false, true, true) => PAGE_EXECUTE_READWRITE,   // fallback
111        }
112    }
113}