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