use crate::exec::{Architecture, Import, Imports, Section};
use crate::utils::{string_from_offset, u16_from_offset, u32_from_offset, u64_from_offset};
use crate::Ordering;
use std::fmt::{Debug, Display, Formatter};
use std::mem::size_of;
use std::time::{Duration, SystemTime};
use anyhow::Result;
use chrono::{DateTime, Utc};
use flagset::{flags, FlagSet};
use tracing::{info, instrument};
#[repr(C, packed)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct COFFHeader {
pub machine: u16,
pub num_sections: u16,
pub time_date_stamp: u32,
pub pointer_to_symbol_table: u32,
pub num_symbols: u32,
pub size_of_optional_header: u16,
pub characteristics: FlagSet<CoffCharacteristics>,
}
impl AsRef<[u8; size_of::<Self>()]> for COFFHeader {
#[allow(clippy::transmute_ptr_to_ptr)]
fn as_ref(&self) -> &[u8; size_of::<Self>()] {
unsafe { std::mem::transmute::<_, &[u8; size_of::<Self>()]>(self) }
}
}
flags! {
pub enum CoffCharacteristics: u16 {
RelocsStripped = 0x0001,
ExecutableImage = 0x0002,
LineNumsStripped = 0x0004,
LocalSymbolsStripped = 0x0008,
AggressiveTrimWorkingSet = 0x0010,
LargeAddressAware = 0x0020,
Reserved = 0x0040,
BytesReversedLo = 0x0080,
ThirtyTwoBitMachine = 0x0100,
DebugStripped = 0x0200,
RemovableRunFromSwap = 0x0400,
NetRunFromSwap = 0x0800,
FileSystem = 0x1000,
FileDLL = 0x2000,
UPSystemOnly = 0x4000,
BytesReversedHi = 0x8000,
}
}
impl COFFHeader {
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn cast(raw: &[u8; size_of::<Self>()]) -> &Self {
unsafe { std::mem::transmute(raw) }
}
pub fn from(contents: &[u8]) -> Result<&Self> {
let temp: &[u8; 20] = contents[0..20].try_into()?;
Ok(COFFHeader::cast(temp))
}
pub fn architecture(&self) -> Architecture {
match self.machine {
0x184 => Architecture::Alpha,
0x284 => Architecture::Alpha64,
0x1c0 => Architecture::ARM,
0x1c4 | 0x1c2 => Architecture::ARMThumb,
0xAA64 | 0xA641 | 0xA64E => Architecture::ARM64, 0x1a2 | 0x1a3 => Architecture::HitachiSH3, 0x1a6 => Architecture::HitachiSH4,
0x1a8 => Architecture::HitachiSH5,
0x6232 => Architecture::LoongArch32,
0x6264 => Architecture::LoongArch64,
0x169 | 0x266 | 0x366 | 0x466 | 0x166 => Architecture::MIPSEL,
0x1f0 | 0x1f1 => Architecture::PowerPCLE, 0x5032 => Architecture::RISCV,
0x5064 => Architecture::RISCV64,
0x5128 => Architecture::RISCV128,
0x14c => Architecture::X86,
0x8664 => Architecture::X86_64,
0 => Architecture::Unknown,
other => Architecture::Other(u32::from(other)),
}
}
pub fn compiled_date(&self) -> DateTime<Utc> {
let d = SystemTime::UNIX_EPOCH + Duration::from_secs(u64::from(self.time_date_stamp));
DateTime::<Utc>::from(d)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum OptionalHeader {
OptionalHeader32(OptionalHeader32),
OptionalHeader64(OptionalHeader64),
}
impl OptionalHeader {
pub fn from(contents: &[u8]) -> Option<Self> {
match u16_from_offset(contents, 0, Ordering::LittleEndian) {
Some(0x020B) => Some(OptionalHeader::OptionalHeader64(OptionalHeader64::from(
contents,
))),
Some(_) => Some(OptionalHeader::OptionalHeader32(OptionalHeader32::from(
contents,
))),
None => None,
}
}
pub fn subsystem(&self) -> Option<u16> {
match self {
OptionalHeader::OptionalHeader32(h32) => h32.subsystem,
OptionalHeader::OptionalHeader64(h64) => h64.subsystem,
}
}
pub fn is_64bit(&self) -> bool {
match self {
OptionalHeader::OptionalHeader32(_) => false,
OptionalHeader::OptionalHeader64(_) => true,
}
}
pub fn data_directories(&self) -> Option<DataDirectories> {
match self {
OptionalHeader::OptionalHeader32(h32) => h32.data_directories,
OptionalHeader::OptionalHeader64(h64) => h64.data_directories,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ImportDirectoryEntry {
pub import_lookup_table_rva: u32,
pub date_time_stamp: u32,
pub forwarder_chain: u32,
pub name_rva: u32,
pub import_address_table_rva: u32,
}
impl ImportDirectoryEntry {
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn cast(raw: &[u8; size_of::<Self>()]) -> &Self {
unsafe { std::mem::transmute(raw) }
}
pub fn from(contents: &[u8]) -> &Self {
let temp: &[u8; 20] = contents[0..20].try_into().unwrap();
ImportDirectoryEntry::cast(temp)
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct DataDirectory {
pub virtual_address: u32,
pub size: u32,
pub name: &'static str,
}
impl DataDirectory {
#[inline]
pub fn new(
virtual_address: Option<u32>,
size: Option<u32>,
name: &'static str,
) -> Option<Self> {
Some(Self {
virtual_address: virtual_address?,
size: size?,
name,
})
}
}
impl Display for DataDirectory {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}: Address: 0x{:02X}, Size: 0x{:02X}",
self.name, self.virtual_address, self.size
)
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct DataDirectories {
pub export_table: DataDirectory,
pub import_table: DataDirectory,
pub resource_table: DataDirectory,
pub exception_table: DataDirectory,
pub certificate_table: DataDirectory,
pub base_relocation_table: DataDirectory,
pub debug: DataDirectory,
pub architecture: DataDirectory,
pub global_ptr: DataDirectory,
pub tls_table: DataDirectory,
pub load_config_table: DataDirectory,
pub bound_import: DataDirectory,
pub iat: DataDirectory,
pub delay_import_descriptor: DataDirectory,
pub clr_runtime_header: DataDirectory,
pub reserved: DataDirectory,
is_64bit: bool,
}
impl DataDirectories {
#[allow(clippy::too_many_lines)]
pub fn from(contents: &[u8], offset: usize, is_64bit: bool) -> Option<Self> {
if contents.len() < offset + 128 {
return None;
}
Some(Self {
export_table: DataDirectory::new(
u32_from_offset(contents, offset, Ordering::LittleEndian),
u32_from_offset(contents, offset + 4, Ordering::LittleEndian),
"Export Directory",
)?,
import_table: DataDirectory::new(
u32_from_offset(contents, offset + 8, Ordering::LittleEndian),
u32_from_offset(contents, offset + 12, Ordering::LittleEndian),
"Import Directory",
)?,
resource_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 16, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 20, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Resource Directory",
},
exception_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 24, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 28, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Exception Directory",
},
certificate_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 32, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 36, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Certificate Directory",
},
base_relocation_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 40, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 44, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Base Relocation Table",
},
debug: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 48, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 52, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Debug Directory",
},
architecture: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 56, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 60, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Architecture Specific Data",
},
global_ptr: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 64, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 68, Ordering::LittleEndian)
.unwrap_or_default(),
name: "RVA of Global Pointer Register",
},
tls_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 72, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 76, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Thread Local Storage Directory",
},
load_config_table: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 80, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 84, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Load Configuration Directory",
},
bound_import: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 88, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 92, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Bound Import Directory",
},
iat: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 96, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 100, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Import Address Table",
},
delay_import_descriptor: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 104, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 108, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Delay Load Import Descriptors",
},
clr_runtime_header: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 112, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 116, Ordering::LittleEndian)
.unwrap_or_default(),
name: ".Net (Common Language Runtime) Header",
},
reserved: DataDirectory {
virtual_address: u32_from_offset(contents, offset + 120, Ordering::LittleEndian)
.unwrap_or_default(),
size: u32_from_offset(contents, offset + 124, Ordering::LittleEndian)
.unwrap_or_default(),
name: "Reserved (should be zero)",
},
is_64bit,
})
}
#[allow(clippy::cast_possible_truncation)]
#[instrument]
pub fn imports(&self, num_imports: usize, section: &Section) -> Imports {
const IMPORT_ENTRY_SIZE: usize = 20usize;
let mut imports = Vec::new();
if self.import_table.size == 0
|| self.import_table.virtual_address == 0
|| section.data.is_none()
{
return Imports {
imports,
expected_imports: num_imports as u32,
};
}
if let Some(section_data) = section.data {
for import_num in 0..num_imports {
let offset = import_num * IMPORT_ENTRY_SIZE;
if offset > section_data.len() || offset + IMPORT_ENTRY_SIZE > section_data.len() {
info!("PE32: Offset {offset} or offset + import entry size {IMPORT_ENTRY_SIZE} is beyond section data size {}.", section_data.len());
break;
}
let import_directory =
ImportDirectoryEntry::from(§ion_data[offset..offset + IMPORT_ENTRY_SIZE]);
if import_directory.name_rva == 0 {
continue;
}
if import_directory.name_rva < section.virtual_address {
continue;
}
if import_directory.import_lookup_table_rva < section.virtual_address {
continue;
}
let dll_name_offset =
import_directory.name_rva as usize - section.virtual_address as usize;
let dll_name = if dll_name_offset < section_data.len() {
string_from_offset(section_data, dll_name_offset).unwrap_or_default()
} else {
info!("PE2: failed to get dll string name, offset {dll_name_offset} beyond buffer size {}.", section_data.len());
String::new()
};
let import_data_offset =
(import_directory.import_lookup_table_rva - section.virtual_address) as usize;
if 4 + import_data_offset > section_data.len() {
info!(
"PE32: Import data offset {import_data_offset} beyond section data buffer size {}.",
section_data.len()
);
continue;
}
let mut the_imports = §ion_data[import_data_offset..];
loop {
if the_imports.is_empty() {
info!("PE32: Import data buffer is empty at {import_data_offset}.");
break;
}
let va = if self.is_64bit {
u64_from_offset(the_imports, 0, Ordering::LittleEndian)
} else {
u32_from_offset(the_imports, 0, Ordering::LittleEndian).map(u64::from)
}
.unwrap_or_default();
if va == 0 {
break;
}
if (va & 0x8000_0000_0000_0000) > 0 {
info!("PE32: binary uses ordinals, which isn't yet implemented.");
} else {
let function_name = if section.virtual_address as usize + 2 < va as usize {
let function_name_offset =
va as usize - section.virtual_address as usize + 2;
if function_name_offset < section_data.len() {
string_from_offset(section_data, function_name_offset)
.unwrap_or_default()
} else {
info!("PE32: function name offset {function_name_offset} beyond section data size {}.", section_data.len());
String::new()
}
} else {
info!(
"PE32: function name: virtual address {}+2 is greater than va {va}.",
section.virtual_address
);
String::new()
};
imports.push(Import {
library: dll_name.clone(),
function: function_name,
});
}
the_imports = &the_imports[4..];
if self.is_64bit {
the_imports = &the_imports[4..];
}
}
}
} else {
info!("PE32: Import section data buffer is empty.");
}
Imports {
imports,
expected_imports: num_imports as u32,
}
}
}
pub struct DataDirectoryIterator {
item: DataDirectories,
index: usize,
}
impl IntoIterator for DataDirectories {
type Item = DataDirectory;
type IntoIter = DataDirectoryIterator;
fn into_iter(self) -> Self::IntoIter {
DataDirectoryIterator {
item: self,
index: 0,
}
}
}
impl Iterator for DataDirectoryIterator {
type Item = DataDirectory;
fn next(&mut self) -> Option<Self::Item> {
let result = match self.index {
0 => self.item.export_table,
1 => self.item.import_table,
2 => self.item.resource_table,
3 => self.item.exception_table,
4 => self.item.certificate_table,
5 => self.item.base_relocation_table,
6 => self.item.debug,
7 => self.item.architecture,
8 => self.item.global_ptr,
9 => self.item.tls_table,
10 => self.item.load_config_table,
11 => self.item.bound_import,
12 => self.item.iat,
13 => self.item.delay_import_descriptor,
14 => self.item.clr_runtime_header,
15 => self.item.reserved,
_ => {
return None;
}
};
self.index += 1;
Some(result)
}
fn count(self) -> usize
where
Self: Sized,
{
16
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
Some(self.item.clr_runtime_header)
}
}
impl Display for DataDirectories {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for directory in self.into_iter() {
writeln!(f, "{directory}")?;
}
Ok(())
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OptionalHeader32 {
pub magic: u16,
pub major_linker_version: u8,
pub minor_linker_version: u8,
pub size_of_code: u32,
pub size_of_initialized_data: u32,
pub size_of_uninitialized_data: u32,
pub address_of_entry_point: u32,
pub base_of_code: u32,
pub base_of_data: u32,
pub image_base: Option<u32>,
pub section_alignment: Option<u32>,
pub file_alignment: Option<u32>,
pub major_operating_system_version: Option<u16>,
pub minor_operating_system_version: Option<u16>,
pub major_image_version: Option<u16>,
pub minor_image_version: Option<u16>,
pub major_subsystem_version: Option<u16>,
pub minor_subsystem_version: Option<u16>,
pub win32_version_value: Option<u32>,
pub size_of_image: Option<u32>,
pub size_of_headers: Option<u32>,
pub checksum: Option<u32>,
pub subsystem: Option<u16>,
pub dll_characteristics: Option<FlagSet<DLLCharacteristics>>,
pub size_of_stack_reserve: Option<u32>,
pub size_of_stack_commit: Option<u32>,
pub size_of_heap_reserve: Option<u32>,
pub size_of_heap_commit: Option<u32>,
pub loader_flags: Option<u32>,
pub num_rva_and_sizes: Option<u32>,
pub data_directories: Option<DataDirectories>,
}
impl OptionalHeader32 {
pub fn from(contents: &[u8]) -> Self {
Self {
magic: u16_from_offset(contents, 0, Ordering::LittleEndian).unwrap_or_default(),
major_linker_version: contents[2],
minor_linker_version: contents[3],
size_of_code: u32_from_offset(contents, 4, Ordering::LittleEndian).unwrap_or_default(),
size_of_initialized_data: u32_from_offset(contents, 8, Ordering::LittleEndian)
.unwrap_or_default(),
size_of_uninitialized_data: u32_from_offset(contents, 12, Ordering::LittleEndian)
.unwrap_or_default(),
address_of_entry_point: u32_from_offset(contents, 16, Ordering::LittleEndian)
.unwrap_or_default(),
base_of_code: u32_from_offset(contents, 20, Ordering::LittleEndian).unwrap_or_default(),
base_of_data: u32_from_offset(contents, 24, Ordering::LittleEndian).unwrap_or_default(),
image_base: u32_from_offset(contents, 28, Ordering::LittleEndian),
section_alignment: u32_from_offset(contents, 32, Ordering::LittleEndian),
file_alignment: u32_from_offset(contents, 36, Ordering::LittleEndian),
major_operating_system_version: u16_from_offset(contents, 40, Ordering::LittleEndian),
minor_operating_system_version: u16_from_offset(contents, 42, Ordering::LittleEndian),
major_image_version: u16_from_offset(contents, 44, Ordering::LittleEndian),
minor_image_version: u16_from_offset(contents, 46, Ordering::LittleEndian),
major_subsystem_version: u16_from_offset(contents, 48, Ordering::LittleEndian),
minor_subsystem_version: u16_from_offset(contents, 50, Ordering::LittleEndian),
win32_version_value: u32_from_offset(contents, 52, Ordering::LittleEndian),
size_of_image: u32_from_offset(contents, 56, Ordering::LittleEndian),
size_of_headers: u32_from_offset(contents, 60, Ordering::LittleEndian),
checksum: u32_from_offset(contents, 64, Ordering::LittleEndian),
subsystem: u16_from_offset(contents, 68, Ordering::LittleEndian),
dll_characteristics: {
if let Some(val) = u16_from_offset(contents, 70, Ordering::LittleEndian) {
FlagSet::<DLLCharacteristics>::new(val).ok()
} else {
None
}
},
size_of_stack_reserve: u32_from_offset(contents, 72, Ordering::LittleEndian),
size_of_stack_commit: u32_from_offset(contents, 76, Ordering::LittleEndian),
size_of_heap_reserve: u32_from_offset(contents, 80, Ordering::LittleEndian),
size_of_heap_commit: u32_from_offset(contents, 84, Ordering::LittleEndian),
loader_flags: u32_from_offset(contents, 88, Ordering::LittleEndian),
num_rva_and_sizes: u32_from_offset(contents, 92, Ordering::LittleEndian),
data_directories: DataDirectories::from(contents, 96, false),
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OptionalHeader64 {
pub magic: u16,
pub major_linker_version: u8,
pub minor_linker_version: u8,
pub size_of_code: u32,
pub size_of_initialized_data: u32,
pub size_of_uninitialized_data: u32,
pub address_of_entry_point: u32,
pub base_of_code: u32,
pub image_base: Option<u64>,
pub section_alignment: Option<u32>,
pub file_alignment: Option<u32>,
pub major_operating_system_version: Option<u16>,
pub minor_operating_system_version: Option<u16>,
pub major_image_version: Option<u16>,
pub minor_image_version: Option<u16>,
pub major_subsystem_version: Option<u16>,
pub minor_subsystem_version: Option<u16>,
pub win32_version_value: Option<u32>,
pub size_of_image: Option<u32>,
pub size_of_headers: Option<u32>,
pub checksum: Option<u32>,
pub subsystem: Option<u16>,
pub dll_characteristics: Option<FlagSet<DLLCharacteristics>>,
pub size_of_stack_reserve: Option<u64>,
pub size_of_stack_commit: Option<u64>,
pub size_of_heap_reserve: Option<u64>,
pub size_of_heap_commit: Option<u64>,
pub loader_flags: Option<u32>,
pub num_rva_and_sizes: Option<u32>,
pub data_directories: Option<DataDirectories>,
}
impl OptionalHeader64 {
pub fn from(contents: &[u8]) -> Self {
Self {
magic: u16_from_offset(contents, 0, Ordering::LittleEndian).unwrap_or_default(),
major_linker_version: contents[2],
minor_linker_version: contents[3],
size_of_code: u32_from_offset(contents, 4, Ordering::LittleEndian).unwrap_or_default(),
size_of_initialized_data: u32_from_offset(contents, 8, Ordering::LittleEndian)
.unwrap_or_default(),
size_of_uninitialized_data: u32_from_offset(contents, 12, Ordering::LittleEndian)
.unwrap_or_default(),
address_of_entry_point: u32_from_offset(contents, 16, Ordering::LittleEndian)
.unwrap_or_default(),
base_of_code: u32_from_offset(contents, 20, Ordering::LittleEndian).unwrap_or_default(),
image_base: u64_from_offset(contents, 24, Ordering::LittleEndian),
section_alignment: u32_from_offset(contents, 32, Ordering::LittleEndian),
file_alignment: u32_from_offset(contents, 36, Ordering::LittleEndian),
major_operating_system_version: u16_from_offset(contents, 40, Ordering::LittleEndian),
minor_operating_system_version: u16_from_offset(contents, 42, Ordering::LittleEndian),
major_image_version: u16_from_offset(contents, 44, Ordering::LittleEndian),
minor_image_version: u16_from_offset(contents, 46, Ordering::LittleEndian),
major_subsystem_version: u16_from_offset(contents, 48, Ordering::LittleEndian),
minor_subsystem_version: u16_from_offset(contents, 50, Ordering::LittleEndian),
win32_version_value: u32_from_offset(contents, 52, Ordering::LittleEndian),
size_of_image: u32_from_offset(contents, 56, Ordering::LittleEndian),
size_of_headers: u32_from_offset(contents, 60, Ordering::LittleEndian),
checksum: u32_from_offset(contents, 64, Ordering::LittleEndian),
subsystem: u16_from_offset(contents, 68, Ordering::LittleEndian),
dll_characteristics: {
if let Some(val) = u16_from_offset(contents, 70, Ordering::LittleEndian) {
FlagSet::<DLLCharacteristics>::new(val).ok()
} else {
None
}
},
size_of_stack_reserve: u64_from_offset(contents, 72, Ordering::LittleEndian),
size_of_stack_commit: u64_from_offset(contents, 80, Ordering::LittleEndian),
size_of_heap_reserve: u64_from_offset(contents, 88, Ordering::LittleEndian),
size_of_heap_commit: u64_from_offset(contents, 96, Ordering::LittleEndian),
loader_flags: u32_from_offset(contents, 104, Ordering::LittleEndian),
num_rva_and_sizes: u32_from_offset(contents, 108, Ordering::LittleEndian),
data_directories: DataDirectories::from(contents, 112, true),
}
}
}
flags! {
pub enum DLLCharacteristics: u16 {
Reserved1 = 0x0001,
Reserved2 = 0x0002,
Reserved3 = 0x0004,
Reserved4 = 0x0008,
HighEntropyVA = 0x0020,
DynamicBase = 0x0040,
ForceIntegrity = 0x0080,
NXCompat = 0x0100,
NoIsolation = 0x0200,
NoSEH = 0x0400,
NoBind = 0x0800,
AppContainer = 0x1000,
WDMDriver = 0x2000,
GuardCF = 0x4000,
TerminalServerAware = 0x8000,
}
pub enum SectionFlags: u32 {
Reserved1 = 0x0000_0000,
Reserved2 = 0x0000_0001,
Reserved3 = 0x0000_0002,
Reserved4 = 0x0000_0004,
NoPadding = 0x0000_0008,
Reserved5 = 0x0000_0010,
ContainsCode = 0x0000_0020,
InitializedData = 0x0000_0040,
UninitializedData = 0x0000_0080,
LinkOther = 0x0000_0100,
LinkInfo = 0x0000_0200,
Reserved6 = 0x0000_0400,
Remove = 0x0000_0800,
Comdat = 0x0000_1000,
GlobalPointerReferenced = 0x0000_8000,
MemPurgeable = 0x0002_0000,
Mem16bit = 0x0002_0000,
MemLocked = 0x0004_0000,
MemPreload = 0x0008_0000,
Align1Bytes = 0x0010_0000,
Align2Bytes = 0x0020_0000,
Align4Bytes = 0x0030_0000,
Align8Bytes = 0x0040_0000,
Align16Bytes = 0x0050_0000,
Align32Bytes = 0x0060_0000,
Align64Bytes = 0x0070_0000,
Align128Bytes = 0x0080_0000,
Align256Bytes = 0x0090_0000,
Align512Bytes = 0x00A0_0000,
Align1024Bytes = 0x00B0_0000,
Align2048Bytes = 0x00C0_0000,
Align4096Bytes = 0x00D0_0000,
Align8192Bytes = 0x00E0_0000,
ExtendedRel = 0x0100_0000,
Discardable = 0x0200_0000,
NotCacheable = 0x0400_0000,
NotPageable = 0x0800_0000,
Shareable = 0x1000_0000,
Executable = 0x2000_0000,
Readable = 0x4000_0000,
Writeable = 0x8000_0000,
}
}