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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//! PE Delayed import module
use crate::{common::FromFFI, declare_iterator, generic};
use lief_ffi as ffi;
use std::marker::PhantomData;
use std::pin::Pin;
pub struct DelayImport<'a> {
ptr: cxx::UniquePtr<ffi::PE_DelayImport>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl DelayImport<'_> {
/// According to the official PE specifications, this value is reserved and should be set to 0
pub fn attribute(&self) -> u32 {
self.ptr.attribute()
}
/// Return the library's name (e.g. `kernel32.dll`)
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
/// The RVA of the module handle (in the ``.data`` section).
/// It is used for storage by the routine that is supplied to manage delay-loading.
pub fn handle(&self) -> u32 {
self.ptr.handle()
}
/// RVA of the delay-load import address table.
pub fn iat(&self) -> u32 {
self.ptr.iat()
}
/// RVA of the delay-load import names table.
///
/// The content of this table has the layout as the Import lookup table
pub fn names_table(&self) -> u32 {
self.ptr.names_table()
}
/// RVA of the **bound** delay-load import address table or 0 if the table does not exist.
pub fn biat(&self) -> u32 {
self.ptr.biat()
}
/// RVA of the **unload** delay-load import address table or 0
/// if the table does not exist.
///
/// According to the PE specifications, this table is an
/// exact copy of the delay import address table that can be
/// used to to restore the original IAT the case of unloading.
pub fn uiat(&self) -> u32 {
self.ptr.uiat()
}
/// The timestamp of the DLL to which this image has been bound.
pub fn timestamp(&self) -> u32 {
self.ptr.timestamp()
}
/// Iterator over the DelayImport's entries ([`DelayImportEntry`])
pub fn entries(&self) -> Entries<'_> {
Entries::new(self.ptr.entries())
}
}
impl std::fmt::Debug for DelayImport<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DelayImport")
.field("attribute", &self.attribute())
.field("name", &self.name())
.field("handle", &self.handle())
.field("iat", &self.iat())
.field("names_table", &self.names_table())
.field("biat", &self.biat())
.field("uiat", &self.uiat())
.field("timestamp", &self.timestamp())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_DelayImport> for DelayImport<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DelayImport>) -> Self {
DelayImport {
ptr,
_owner: PhantomData,
}
}
}
/// Structure that represents an entry (i.e. an import) in the delay import table.
///
/// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
/// [`generic::Symbol::value`].
///
/// The meaning of [`generic::Symbol::value`] for this PE object is the address (as an RVA) in the
/// IAT where the resolution should take place.
pub struct DelayImportEntry<'a> {
ptr: cxx::UniquePtr<ffi::PE_DelayImportEntry>,
_owner: PhantomData<&'a ffi::PE_DelayImport>,
}
impl DelayImportEntry<'_> {
/// `True` if it is an import by ordinal
pub fn is_ordinal(&self) -> bool {
self.ptr.is_ordinal()
}
/// The ordinal value
pub fn ordinal(&self) -> u16 {
self.ptr.ordinal()
}
/// See: [`DelayImportEntry::data`]
pub fn hint_name_rva(&self) -> u64 {
self.ptr.hint_name_rva()
}
/// Index into the export table that is used to speed-up the symbol resolution
pub fn hint(&self) -> u16 {
self.ptr.hint()
}
/// Value of the current entry in the Import Address Table.
pub fn iat_value(&self) -> u64 {
self.ptr.iat_value()
}
/// Raw value
pub fn data(&self) -> u64 {
self.ptr.data()
}
/// Demangled representation of the symbol or an empty string if it can't
/// be demangled
pub fn demangled_name(&self) -> String {
self.ptr.demangled_name().to_string()
}
}
impl generic::Symbol for DelayImportEntry<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
unsafe {
Pin::new_unchecked({
(self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
as *mut ffi::AbstractSymbol)
.as_mut()
.unwrap()
})
}
}
}
impl std::fmt::Debug for DelayImportEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("DelayImportEntry")
.field("base", &base)
.field("ordinal", &self.ordinal())
.field("hint_name_rva", &self.hint_name_rva())
.field("hint", &self.hint())
.field("iat_value", &self.iat_value())
.field("data", &self.data())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_DelayImportEntry> for DelayImportEntry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DelayImportEntry>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
DelayImports,
DelayImport<'a>,
ffi::PE_DelayImport,
ffi::PE_Binary,
ffi::PE_Binary_it_delay_imports
);
declare_iterator!(
Entries,
DelayImportEntry<'a>,
ffi::PE_DelayImportEntry,
ffi::PE_DelayImport,
ffi::PE_DelayImport_it_entries
);