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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use alloc::vec::Vec;
pub mod header;
pub mod optional_header;
pub mod characteristic;
pub mod section_table;
pub mod data_directories;
pub mod export;
pub mod import;
pub mod debug;
mod utils;
use error;
use container;
const COFF_SYMBOL_SIZE: u32 = 18;
#[derive(Debug)]
pub struct PE<'a> {
pub header: header::Header,
pub sections: Vec<section_table::SectionTable>,
pub size: usize,
pub name: Option<&'a str>,
pub is_lib: bool,
pub is_64: bool,
pub entry: usize,
pub image_base: usize,
pub export_data: Option<export::ExportData<'a>>,
pub import_data: Option<import::ImportData<'a>>,
pub exports: Vec<export::Export<'a>>,
pub imports: Vec<import::Import<'a>>,
pub libraries: Vec<&'a str>,
pub debug_data: Option<debug::DebugData<'a>>
}
impl<'a> PE<'a> {
pub fn parse(bytes: &'a [u8]) -> error::Result<Self> {
let header = header::Header::parse(bytes)?;
debug!("{:#?}", header);
let offset = &mut (header.dos_header.pe_pointer as usize + header::SIZEOF_COFF_HEADER + header.coff_header.size_of_optional_header as usize);
let nsections = header.coff_header.number_of_sections as usize;
let mut sections = Vec::with_capacity(nsections);
let string_table_offset = header.coff_header.pointer_to_symbol_table + header.coff_header.number_of_symbol_table * COFF_SYMBOL_SIZE;
for i in 0..nsections {
let section = section_table::SectionTable::parse(bytes, offset, string_table_offset as usize)?;
debug!("({}) {:#?}", i, section);
sections.push(section);
}
let is_lib = characteristic::is_dll(header.coff_header.characteristics);
let mut entry = 0;
let mut image_base = 0;
let mut exports = vec![];
let mut export_data = None;
let mut name = None;
let mut imports = vec![];
let mut import_data = None;
let mut libraries = vec![];
let mut debug_data = None;
let mut is_64 = false;
if let Some(optional_header) = header.optional_header {
entry = optional_header.standard_fields.address_of_entry_point as usize;
image_base = optional_header.windows_fields.image_base as usize;
is_64 = optional_header.container()? == container::Container::Big;
debug!("entry {:#x} image_base {:#x} is_64: {}", entry, image_base, is_64);
let file_alignment = optional_header.windows_fields.file_alignment;
if let &Some(export_table) = optional_header.data_directories.get_export_table() {
if let Ok(ed) = export::ExportData::parse(bytes, &export_table, §ions, file_alignment) {
debug!("export data {:#?}", ed);
exports = export::Export::parse(bytes, &ed, §ions, file_alignment)?;
name = ed.name;
debug!("name: {:#?}", name);
export_data = Some(ed);
}
}
debug!("exports: {:#?}", exports);
if let &Some(import_table) = optional_header.data_directories.get_import_table() {
let id = if is_64 {
import::ImportData::parse::<u64>(bytes, &import_table, §ions, file_alignment)?
} else {
import::ImportData::parse::<u32>(bytes, &import_table, §ions, file_alignment)?
};
debug!("import data {:#?}", id);
if is_64 {
imports = import::Import::parse::<u64>(bytes, &id, §ions)?
} else {
imports = import::Import::parse::<u32>(bytes, &id, §ions)?
}
libraries = id.import_data.iter().map( | data | { data.name }).collect::<Vec<&'a str>>();
libraries.sort();
libraries.dedup();
import_data = Some(id);
}
debug!("imports: {:#?}", imports);
if let &Some(debug_table) = optional_header.data_directories.get_debug_table() {
debug_data = Some(debug::DebugData::parse(bytes, &debug_table, §ions, file_alignment)?);
}
}
Ok( PE {
header: header,
sections: sections,
size: 0,
name: name,
is_lib: is_lib,
is_64: is_64,
entry: entry,
image_base: image_base,
export_data: export_data,
import_data: import_data,
exports: exports,
imports: imports,
libraries: libraries,
debug_data: debug_data,
})
}
}