Line data Source code
1 : //! This module represents PE's Imports
2 :
3 : use std::marker::PhantomData;
4 : use std::pin::Pin;
5 :
6 : use crate::common::into_optional;
7 : use crate::declare_iterator;
8 : use crate::pe::DataDirectory;
9 : use crate::{common::FromFFI, generic};
10 : use lief_ffi as ffi;
11 :
12 : pub struct Import<'a> {
13 : ptr: cxx::UniquePtr<ffi::PE_Import>,
14 : _owner: PhantomData<&'a ffi::PE_Binary>,
15 : }
16 :
17 : impl std::fmt::Debug for Import<'_> {
18 2444 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 2444 : f.debug_struct("Import")
20 2444 : .field("name", &self.name())
21 2444 : .field("forwarder_chain", &self.forwarder_chain())
22 2444 : .field("timedatestamp", &self.timedatestamp())
23 2444 : .field("import_address_table_rva", &self.import_address_table_rva())
24 2444 : .field("import_lookup_table_rva", &self.import_lookup_table_rva())
25 2444 : .field("directory", &self.directory())
26 2444 : .field("iat_directory", &self.iat_directory())
27 2444 : .finish()
28 2444 : }
29 : }
30 :
31 : impl<'a> FromFFI<ffi::PE_Import> for Import<'a> {
32 2457 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Import>) -> Self {
33 2457 : Import {
34 2457 : ptr,
35 2457 : _owner: PhantomData,
36 2457 : }
37 2457 : }
38 : }
39 :
40 : impl<'a> crate::common::AsFFI<ffi::PE_Import> for Import<'a> {
41 0 : fn as_ffi(&self) -> &ffi::PE_Import {
42 0 : self.ptr.as_ref().unwrap()
43 0 : }
44 :
45 0 : fn as_mut_ffi(&mut self) -> Pin<&mut ffi::PE_Import> {
46 0 : self.ptr.pin_mut()
47 0 : }
48 : }
49 :
50 : impl Import<'_> {
51 : /// Iterator over the [`ImportEntry`]
52 2444 : pub fn entries(&self) -> ImportEntries<'_> {
53 2444 : ImportEntries::new(self.ptr.entries())
54 2444 : }
55 :
56 : /// The index of the first forwarder reference
57 2444 : pub fn forwarder_chain(&self) -> u32 {
58 2444 : self.ptr.forwarder_chain()
59 2444 : }
60 :
61 : /// The stamp that is set to zero until the image is bound.
62 : /// After the image is bound, this field is set to the time/data stamp of the DLL
63 2444 : pub fn timedatestamp(&self) -> u32 {
64 2444 : self.ptr.timedatestamp()
65 2444 : }
66 :
67 : /// The RVA of the import address table (`IAT`). The content of this table is
68 : /// **identical** to the content of the Import Lookup Table (`ILT`) until the image is bound.
69 : ///
70 : /// <div class="warning">This address could change when re-building the binary</div>
71 2444 : pub fn import_address_table_rva(&self) -> u32 {
72 2444 : self.ptr.import_address_table_rva()
73 2444 : }
74 :
75 : /// Return the relative virtual address of the import lookup table
76 : ///
77 : /// <div class="warning">This address could change when re-building the binary</div>
78 2444 : pub fn import_lookup_table_rva(&self) -> u32 {
79 2444 : self.ptr.import_lookup_table_rva()
80 2444 : }
81 :
82 : /// Return the library's name (e.g. `kernel32.dll`)
83 2444 : pub fn name(&self) -> String {
84 2444 : self.ptr.name().to_string()
85 2444 : }
86 :
87 : /// Return the [`DataDirectory`] associated with this import.
88 2444 : pub fn directory(&self) -> Option<DataDirectory<'_>> {
89 2444 : into_optional(self.ptr.directory())
90 2444 : }
91 :
92 : /// Return the [`DataDirectory`] associated with the IAT (import address table).
93 2444 : pub fn iat_directory(&self) -> Option<DataDirectory<'_>> {
94 2444 : into_optional(self.ptr.iat_directory())
95 2444 : }
96 :
97 : /// Try to find an [`ImportEntry`] by its name
98 0 : pub fn entry_by_name(&self, name: &str) -> Option<ImportEntry<'_>> {
99 0 : into_optional(self.ptr.entry_by_name(name))
100 0 : }
101 :
102 : /// The original name rva
103 0 : pub fn name_rva(&self) -> u32 {
104 0 : self.ptr.name_rva()
105 0 : }
106 :
107 : /// Remove the import entry with the given name.
108 : ///
109 : /// Return true if the deletion succeed, false otherwise
110 0 : pub fn remove_entry_by_name(&mut self, name: &str) -> bool {
111 0 : self.ptr.pin_mut().remove_entry_by_name(name)
112 0 : }
113 :
114 : /// Remove the import entry with the given ordinal number
115 : ///
116 : /// Return true if the deletion succeed, false otherwise
117 0 : pub fn remove_entry_by_ordinal(&mut self, ord: u32) -> bool {
118 0 : self.ptr.pin_mut().remove_entry_by_ordinal(ord)
119 0 : }
120 :
121 : /// Add a new entry with the given name
122 0 : pub fn add_entry_by_name<'a>(&'a mut self, name: &str) -> ImportEntry<'a> {
123 0 : ImportEntry::from_ffi(self.ptr.pin_mut().add_entry_by_name(name))
124 0 : }
125 :
126 : /// Set the name of the import
127 0 : pub fn set_name(&mut self, name: &str) {
128 0 : self.ptr.pin_mut().set_name(name.to_string());
129 0 : }
130 : }
131 :
132 : /// Structure that represents an entry (i.e. an import) in the regular import table.
133 : ///
134 : /// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
135 : /// [`generic::Symbol::value`].
136 : pub struct ImportEntry<'a> {
137 : ptr: cxx::UniquePtr<ffi::PE_ImportEntry>,
138 : _owner: PhantomData<&'a ffi::PE_Import>,
139 : }
140 :
141 : impl ImportEntry<'_> {
142 : /// `True` if it is an import by ordinal
143 0 : pub fn is_ordinal(&self) -> bool {
144 0 : self.ptr.is_ordinal()
145 0 : }
146 :
147 : /// The ordinal value
148 30797 : pub fn ordinal(&self) -> u16 {
149 30797 : self.ptr.ordinal()
150 30797 : }
151 30797 : pub fn hint_name_rva(&self) -> u64 {
152 30797 : self.ptr.hint_name_rva()
153 30797 : }
154 :
155 : /// Index into the export table that is used to speed-up the resolution
156 30797 : pub fn hint(&self) -> u16 {
157 30797 : self.ptr.hint()
158 30797 : }
159 :
160 : /// Value of the current entry in the Import Address Table.
161 : /// It should match the lookup table value
162 30797 : pub fn iat_value(&self) -> u64 {
163 30797 : self.ptr.iat_value()
164 30797 : }
165 :
166 : /// Original value in the import lookup table.
167 : ///
168 : /// This value should match the [`ImportEntry::iat_value`].
169 0 : pub fn ilt_value(&self) -> u64 {
170 0 : self.ptr.ilt_value()
171 0 : }
172 :
173 : /// Set the value of the current entry in the Import Address Table.
174 0 : pub fn set_iat_value(&mut self, value: u64) -> &mut Self {
175 0 : self.ptr.pin_mut().set_iat_value(value);
176 0 : self
177 0 : }
178 :
179 : /// Set the original value in the Import Lookup Table.
180 0 : pub fn set_ilt_value(&mut self, value: u64) -> &mut Self {
181 0 : self.ptr.pin_mut().set_ilt_value(value);
182 0 : self
183 0 : }
184 :
185 : /// Raw value
186 30797 : pub fn data(&self) -> u64 {
187 30797 : self.ptr.data()
188 30797 : }
189 :
190 : /// **Original** address of the entry in the Import Address Table
191 30797 : pub fn iat_address(&self) -> u64 {
192 30797 : self.ptr.iat_address()
193 30797 : }
194 :
195 : /// Demangled representation of the symbol or an empty string if it can't
196 : /// be demangled
197 0 : pub fn demangled_name(&self) -> String {
198 0 : self.ptr.demangled_name().to_string()
199 0 : }
200 : }
201 :
202 : impl<'a> FromFFI<ffi::PE_ImportEntry> for ImportEntry<'a> {
203 30797 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ImportEntry>) -> Self {
204 30797 : ImportEntry {
205 30797 : ptr,
206 30797 : _owner: PhantomData,
207 30797 : }
208 30797 : }
209 : }
210 :
211 : impl generic::Symbol for ImportEntry<'_> {
212 92391 : fn as_generic(&self) -> &ffi::AbstractSymbol {
213 92391 : self.ptr.as_ref().unwrap().as_ref()
214 92391 : }
215 :
216 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
217 0 : unsafe {
218 0 : Pin::new_unchecked({
219 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
220 0 : as *mut ffi::AbstractSymbol)
221 0 : .as_mut()
222 0 : .unwrap()
223 0 : })
224 0 : }
225 0 : }
226 : }
227 :
228 : impl std::fmt::Debug for ImportEntry<'_> {
229 30797 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230 30797 : let base = self as &dyn generic::Symbol;
231 30797 : f.debug_struct("ImportEntry")
232 30797 : .field("base", &base)
233 30797 : .field("ordinal", &self.ordinal())
234 30797 : .field("hint_name_rva", &self.hint_name_rva())
235 30797 : .field("hint", &self.hint())
236 30797 : .field("iat_value", &self.iat_value())
237 30797 : .field("data", &self.data())
238 30797 : .field("iat_address", &self.iat_address())
239 30797 : .finish()
240 30797 : }
241 : }
242 :
243 30797 : declare_iterator!(
244 30797 : ImportEntries,
245 30797 : ImportEntry<'a>,
246 30797 : ffi::PE_ImportEntry,
247 30797 : ffi::PE_Import,
248 30797 : ffi::PE_Import_it_entries
249 30797 : );
250 2444 : declare_iterator!(
251 2444 : Imports,
252 2444 : Import<'a>,
253 2444 : ffi::PE_Import,
254 2444 : ffi::PE_Binary,
255 2444 : ffi::PE_Binary_it_imports
256 2444 : );
|