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