Line data Source code
1 : //! PE export module
2 :
3 : use lief_ffi as ffi;
4 :
5 : use std::pin::Pin;
6 : use crate::common::into_optional;
7 : use crate::common::{FromFFI, AsFFI};
8 : use crate::declare_iterator;
9 : use crate::generic;
10 :
11 : use std::marker::PhantomData;
12 :
13 : pub struct Export<'a> {
14 : ptr: cxx::UniquePtr<ffi::PE_Export>,
15 : _owner: PhantomData<&'a ffi::PE_Binary>,
16 : }
17 :
18 : impl Export<'_> {
19 : /// Create a new Export object
20 0 : pub fn new() -> Export<'static> {
21 0 : Export::from_ffi(ffi::PE_Export::create())
22 0 : }
23 :
24 : /// According to the PE specifications this value is reserved and should be set to 0
25 96 : pub fn export_flags(&self) -> u32 {
26 96 : self.ptr.export_flags()
27 96 : }
28 :
29 : /// The time and date that the export data was created
30 96 : pub fn timestamp(&self) -> u32 {
31 96 : self.ptr.timestamp()
32 96 : }
33 :
34 : /// The major version number (can be user-defined)
35 96 : pub fn major_version(&self) -> u16 {
36 96 : self.ptr.major_version()
37 96 : }
38 :
39 : /// The minor version number (can be user-defined)
40 96 : pub fn minor_version(&self) -> u16 {
41 96 : self.ptr.minor_version()
42 96 : }
43 :
44 : /// The starting number for the exports. Usually this value is set to 1
45 96 : pub fn ordinal_base(&self) -> u32 {
46 96 : self.ptr.ordinal_base()
47 96 : }
48 :
49 : /// The name of the library exported (e.g. `KERNEL32.dll`)
50 96 : pub fn name(&self) -> String {
51 96 : self.ptr.name().to_string()
52 96 : }
53 :
54 : /// Iterator over the different [`Entry`] exported by this table
55 96 : pub fn entries(&self) -> ExportEntries {
56 96 : ExportEntries::new(self.ptr.entries())
57 96 : }
58 :
59 : /// Address of the ASCII DLL's name (RVA)
60 0 : pub fn name_rva(&self) -> u32 {
61 0 : self.ptr.name_rva()
62 0 : }
63 :
64 : /// RVA to the list of exported names
65 0 : pub fn names_addr_table_rva(&self) -> u32 {
66 0 : self.ptr.names_addr_table_rva()
67 0 : }
68 :
69 : /// Number of exports by name
70 0 : pub fn names_addr_table_cnt(&self) -> u32 {
71 0 : self.ptr.names_addr_table_cnt()
72 0 : }
73 :
74 : /// RVA of the export address table
75 0 : pub fn export_addr_table_rva(&self) -> u32 {
76 0 : self.ptr.export_addr_table_rva()
77 0 : }
78 :
79 : /// Number of entries in the export address table
80 0 : pub fn export_addr_table_cnt(&self) -> u32 {
81 0 : self.ptr.export_addr_table_cnt()
82 0 : }
83 :
84 : /// RVA to the list of exported ordinals
85 0 : pub fn ord_addr_table_rva(&self) -> u32 {
86 0 : self.ptr.ord_addr_table_rva()
87 0 : }
88 :
89 : /// Change or set the export flags
90 0 : pub fn set_export_flags(&mut self, flags: u32) -> &mut Self {
91 0 : self.ptr.pin_mut().set_export_flags(flags);
92 0 : self
93 0 : }
94 :
95 : /// Change or set the timestamp
96 0 : pub fn set_timestamp(&mut self, timestamp: u32) -> &mut Self {
97 0 : self.ptr.pin_mut().set_export_flags(timestamp);
98 0 : self
99 0 : }
100 :
101 : /// Change or set the major version of the DLL
102 0 : pub fn set_major_version(&mut self, version: u32) -> &mut Self {
103 0 : self.ptr.pin_mut().set_major_version(version);
104 0 : self
105 0 : }
106 :
107 : /// Change or set the minor version of the DLL
108 0 : pub fn set_minor_version(&mut self, version: u32) -> &mut Self {
109 0 : self.ptr.pin_mut().set_minor_version(version);
110 0 : self
111 0 : }
112 :
113 : /// Change or set the name of the DLL
114 0 : pub fn set_name(&mut self, name: &str) -> &mut Self {
115 0 : self.ptr.pin_mut().set_name(name);
116 0 : self
117 0 : }
118 :
119 : /// Find the export entry with the given name
120 0 : pub fn entry_by_name(&self, name: &str) -> Option<Entry> {
121 0 : into_optional(self.ptr.entry_by_name(name))
122 0 : }
123 :
124 : /// Find the export entry with the given ordinal number
125 0 : pub fn entry_by_ordinal(&self, ordinal: u32) -> Option<Entry> {
126 0 : into_optional(self.ptr.entry_by_ordinal(ordinal))
127 0 : }
128 :
129 : /// Find the export entry at the provided RVA
130 0 : pub fn entry_at_rva(&self, rva: u32) -> Option<Entry> {
131 0 : into_optional(self.ptr.entry_at_rva(rva))
132 0 : }
133 :
134 : /// Add the given export and return the newly created and added export
135 0 : pub fn add_entry(&mut self, entry: &Entry) -> Entry {
136 0 : Entry::from_ffi(self.ptr.pin_mut().add_entry(entry.ptr.as_ref().unwrap()))
137 0 : }
138 :
139 : /// Add a new export entry given its name and its RVA
140 0 : pub fn add_entry_by_name(&mut self, name: &str, rva: u32) -> Entry {
141 0 : Entry::from_ffi(self.ptr.pin_mut().add_entry_by_name(name, rva))
142 0 : }
143 :
144 : /// Remove the given export entry
145 0 : pub fn remove_entry(&mut self, entry: Entry) -> bool {
146 0 : self.ptr.pin_mut().remove_entry(entry.ptr)
147 0 : }
148 :
149 : /// Remove the export entry with the given RVA
150 0 : pub fn remove_entry_at(&mut self, rva: u32) -> bool {
151 0 : self.ptr.pin_mut().remove_entry_at(rva)
152 0 : }
153 :
154 : /// Remove the export entry with the given RVA
155 0 : pub fn remove_entry_by_name(&mut self, name: &str) -> bool {
156 0 : self.ptr.pin_mut().remove_entry_by_name(name)
157 0 : }
158 :
159 : }
160 :
161 : impl std::fmt::Debug for Export<'_> {
162 96 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 96 : f.debug_struct("Export")
164 96 : .field("export_flags", &self.export_flags())
165 96 : .field("timestamp", &self.timestamp())
166 96 : .field("major_version", &self.major_version())
167 96 : .field("minor_version", &self.minor_version())
168 96 : .field("ordinal_base", &self.ordinal_base())
169 96 : .field("name", &self.name())
170 96 : .finish()
171 96 : }
172 : }
173 :
174 : impl<'a> FromFFI<ffi::PE_Export> for Export<'a> {
175 96 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Export>) -> Self {
176 96 : Export {
177 96 : ptr,
178 96 : _owner: PhantomData,
179 96 : }
180 96 : }
181 : }
182 :
183 : impl<'a> AsFFI<ffi::PE_Export> for Export<'a> {
184 0 : fn as_ffi(&self) -> &ffi::PE_Export {
185 0 : self.ptr.as_ref().unwrap()
186 0 : }
187 :
188 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_Export> {
189 0 : self.ptr.pin_mut()
190 0 : }
191 : }
192 :
193 : /// Structure which represents an entry in the export table.
194 : ///
195 : /// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
196 : /// [`generic::Symbol::value`].
197 : pub struct Entry<'a> {
198 : ptr: cxx::UniquePtr<ffi::PE_ExportEntry>,
199 : _owner: PhantomData<&'a ffi::PE_Export>,
200 : }
201 :
202 : impl Entry<'_> {
203 : /// Ordinal value associated with this exported entry.
204 : ///
205 : /// This value is computed as the index of this entry in the address table
206 : /// plus the ordinal base ([`Export::ordinal_base`])
207 149112 : pub fn ordinal(&self) -> u16 {
208 149112 : self.ptr.ordinal()
209 149112 : }
210 :
211 : /// Address of the current exported function in the DLL.
212 : ///
213 : /// If this entry is **external** to the DLL then it returns 0
214 : /// and the external address is returned by [`Entry::function_rva`]
215 149112 : pub fn address(&self) -> u32 {
216 149112 : self.ptr.address()
217 149112 : }
218 :
219 0 : pub fn function_rva(&self) -> u32 {
220 0 : self.ptr.function_rva()
221 0 : }
222 :
223 0 : pub fn is_extern(&self) -> bool {
224 0 : self.ptr.is_extern()
225 0 : }
226 :
227 0 : pub fn is_forwarded(&self) -> bool {
228 0 : self.ptr.is_forwarded()
229 0 : }
230 :
231 : /// Demangled representation of the symbol or an empty string if it can't
232 : /// be demangled
233 0 : pub fn demangled_name(&self) -> String {
234 0 : self.ptr.demangled_name().to_string()
235 0 : }
236 :
237 0 : pub fn forward_info(&self) -> Option<ForwardInfo> {
238 0 : if !self.ptr.is_forwarded() {
239 0 : return None;
240 0 : }
241 0 : Some(ForwardInfo::with_values(self.ptr.fwd_library().to_string(), self.ptr.fwd_function().to_string()))
242 0 : }
243 :
244 0 : pub fn set_ordinal(&mut self, ordinal: u16) -> &mut Self {
245 0 : self.ptr.pin_mut().set_ordinal(ordinal);
246 0 : self
247 0 : }
248 :
249 0 : pub fn set_address(&mut self, address: u32) -> &mut Self {
250 0 : self.ptr.pin_mut().set_address(address);
251 0 : self
252 0 : }
253 : }
254 :
255 : impl generic::Symbol for Entry<'_> {
256 447336 : fn as_generic(&self) -> &ffi::AbstractSymbol {
257 447336 : self.ptr.as_ref().unwrap().as_ref()
258 447336 : }
259 :
260 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
261 0 : unsafe {
262 0 : Pin::new_unchecked({
263 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
264 0 : as *mut ffi::AbstractSymbol)
265 0 : .as_mut()
266 0 : .unwrap()
267 0 : })
268 0 : }
269 0 : }
270 : }
271 :
272 : impl std::fmt::Debug for Entry<'_> {
273 149112 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274 149112 : let base = self as &dyn generic::Symbol;
275 149112 : f.debug_struct("ExportEntry")
276 149112 : .field("base", &base)
277 149112 : .field("ordinal", &self.ordinal())
278 149112 : .field("address", &self.address())
279 149112 : .finish()
280 149112 : }
281 : }
282 :
283 : impl<'a> FromFFI<ffi::PE_ExportEntry> for Entry<'a> {
284 149112 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExportEntry>) -> Self {
285 149112 : Entry {
286 149112 : ptr,
287 149112 : _owner: PhantomData,
288 149112 : }
289 149112 : }
290 : }
291 :
292 : pub struct ForwardInfo {
293 : pub library: String,
294 : pub function: String,
295 : }
296 :
297 : impl ForwardInfo {
298 0 : pub fn with_values(library: String, function: String) -> Self {
299 0 : Self {
300 0 : library, function
301 0 : }
302 0 : }
303 : }
304 :
305 149112 : declare_iterator!(
306 149112 : ExportEntries,
307 149112 : Entry<'a>,
308 149112 : ffi::PE_ExportEntry,
309 149112 : ffi::PE_Export,
310 149112 : ffi::PE_Export_it_entries
311 149112 : );
|