1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use pe::error;
use super::data_directories;
use scroll::{self, Gread};
#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone, Default)]
#[derive(Pread, Pwrite)]
pub struct StandardFields {
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 const SIZEOF_STANDARD_FIELDS: usize = (3 * 8) + 4;
pub const MAGIC_32: u16 = 0x10b;
pub const MAGIC_64: u16 = 0x20b;
impl StandardFields {
pub fn parse<B: AsRef<[u8]>> (bytes: &B, offset: &mut usize) -> error::Result<Self> {
let mut standard_fields = StandardFields::default();
standard_fields.magic = bytes.gread_with(offset, scroll::LE)?;
standard_fields.major_linker_version = bytes.gread_with(offset, scroll::LE)?;
standard_fields.minor_linker_version = bytes.gread_with(offset, scroll::LE)?;
standard_fields.size_of_code = bytes.gread_with(offset, scroll::LE)?;
standard_fields.size_of_initialized_data = bytes.gread_with(offset, scroll::LE)?;
standard_fields.size_of_uninitialized_data = bytes.gread_with(offset, scroll::LE)?;
standard_fields.address_of_entry_point = bytes.gread_with(offset, scroll::LE)?;
standard_fields.base_of_code = bytes.gread_with(offset, scroll::LE)?;
standard_fields.base_of_data = bytes.gread_with(offset, scroll::LE)?;
Ok(standard_fields)
}
}
#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone, Default)]
pub struct WindowsFields {
pub image_base: u32,
pub section_alignment: u32,
pub file_alignment: u32,
pub major_operating_system_version: u16,
pub minor_operating_system_version: u16,
pub major_image_version: u16,
pub minor_image_version: u16,
pub major_subsystem_version: u16,
pub minor_subsystem_version: u16,
pub win32_version_value: u32,
pub size_of_image: u32,
pub size_of_headers: u32,
pub check_sum: u32,
pub subsystem: u16,
pub dll_characteristics: u16,
pub size_of_stack_reserve: u32,
pub size_of_stack_commit: u32,
pub size_of_heap_reserve: u32,
pub size_of_heap_commit: u32,
pub loader_flags: u32,
pub number_of_rva_and_sizes: u32,
}
pub const SIZEOF_WINDOWS_FIELDS: usize = (8 * 8) + 4;
impl WindowsFields {
pub fn parse<B: AsRef<[u8]>> (bytes: &B, offset: &mut usize) -> error::Result<Self> {
let mut windows_fields = WindowsFields::default();
windows_fields.image_base = bytes.gread_with(offset, scroll::LE)?;
windows_fields.section_alignment = bytes.gread_with(offset, scroll::LE)?;
windows_fields.file_alignment = bytes.gread_with(offset, scroll::LE)?;
windows_fields.major_operating_system_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.minor_operating_system_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.major_image_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.minor_image_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.major_subsystem_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.minor_subsystem_version = bytes.gread_with(offset, scroll::LE)?;
windows_fields.win32_version_value = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_image = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_headers = bytes.gread_with(offset, scroll::LE)?;
windows_fields.check_sum = bytes.gread_with(offset, scroll::LE)?;
windows_fields.subsystem = bytes.gread_with(offset, scroll::LE)?;
windows_fields.dll_characteristics = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_stack_reserve = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_stack_commit = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_heap_reserve = bytes.gread_with(offset, scroll::LE)?;
windows_fields.size_of_heap_commit = bytes.gread_with(offset, scroll::LE)?;
windows_fields.loader_flags = bytes.gread_with(offset, scroll::LE)?;
windows_fields.number_of_rva_and_sizes = bytes.gread_with(offset, scroll::LE)?;
Ok(windows_fields)
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct OptionalHeader {
pub standard_fields: StandardFields,
pub windows_fields: WindowsFields,
pub data_directories: data_directories::DataDirectories
}
impl OptionalHeader {
pub fn parse<B: AsRef<[u8]>> (bytes: &B, offset: &mut usize) -> error::Result<Self> {
let standard_fields = StandardFields::parse(bytes, offset)?;
let windows_fields = WindowsFields::parse(bytes, offset)?;
let data_directories = data_directories::DataDirectories::parse(bytes, windows_fields.number_of_rva_and_sizes as usize, offset)?;
Ok (OptionalHeader {
standard_fields: standard_fields,
windows_fields: windows_fields,
data_directories: data_directories,
})
}
}