Line data Source code
1 : //! PE export module
2 :
3 : use lief_ffi as ffi;
4 :
5 : use crate::common::into_optional;
6 : use crate::common::{AsFFI, FromFFI};
7 : use crate::declare_iterator;
8 : use crate::generic;
9 : use std::pin::Pin;
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 104 : pub fn export_flags(&self) -> u32 {
26 104 : self.ptr.export_flags()
27 104 : }
28 :
29 : /// The time and date that the export data was created
30 104 : pub fn timestamp(&self) -> u32 {
31 104 : self.ptr.timestamp()
32 104 : }
33 :
34 : /// The major version number (can be user-defined)
35 104 : pub fn major_version(&self) -> u16 {
36 104 : self.ptr.major_version()
37 104 : }
38 :
39 : /// The minor version number (can be user-defined)
40 104 : pub fn minor_version(&self) -> u16 {
41 104 : self.ptr.minor_version()
42 104 : }
43 :
44 : /// The starting number for the exports. Usually this value is set to 1
45 104 : pub fn ordinal_base(&self) -> u32 {
46 104 : self.ptr.ordinal_base()
47 104 : }
48 :
49 : /// The name of the library exported (e.g. `KERNEL32.dll`)
50 104 : pub fn name(&self) -> String {
51 104 : self.ptr.name().to_string()
52 104 : }
53 :
54 : /// Iterator over the different [`Entry`] exported by this table
55 104 : pub fn entries(&self) -> ExportEntries<'_> {
56 104 : ExportEntries::new(self.ptr.entries())
57 104 : }
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 : impl std::fmt::Debug for Export<'_> {
161 104 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 104 : f.debug_struct("Export")
163 104 : .field("export_flags", &self.export_flags())
164 104 : .field("timestamp", &self.timestamp())
165 104 : .field("major_version", &self.major_version())
166 104 : .field("minor_version", &self.minor_version())
167 104 : .field("ordinal_base", &self.ordinal_base())
168 104 : .field("name", &self.name())
169 104 : .finish()
170 104 : }
171 : }
172 :
173 : impl<'a> FromFFI<ffi::PE_Export> for Export<'a> {
174 104 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Export>) -> Self {
175 104 : Export {
176 104 : ptr,
177 104 : _owner: PhantomData,
178 104 : }
179 104 : }
180 : }
181 :
182 : impl<'a> AsFFI<ffi::PE_Export> for Export<'a> {
183 0 : fn as_ffi(&self) -> &ffi::PE_Export {
184 0 : self.ptr.as_ref().unwrap()
185 0 : }
186 :
187 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_Export> {
188 0 : self.ptr.pin_mut()
189 0 : }
190 : }
191 :
192 : /// Structure which represents an entry in the export table.
193 : ///
194 : /// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
195 : /// [`generic::Symbol::value`].
196 : pub struct Entry<'a> {
197 : ptr: cxx::UniquePtr<ffi::PE_ExportEntry>,
198 : _owner: PhantomData<&'a ffi::PE_Export>,
199 : }
200 :
201 : impl Entry<'_> {
202 : /// Ordinal value associated with this exported entry.
203 : ///
204 : /// This value is computed as the index of this entry in the address table
205 : /// plus the ordinal base ([`Export::ordinal_base`])
206 161538 : pub fn ordinal(&self) -> u16 {
207 161538 : self.ptr.ordinal()
208 161538 : }
209 :
210 : /// Address of the current exported function in the DLL.
211 : ///
212 : /// If this entry is **external** to the DLL then it returns 0
213 : /// and the external address is returned by [`Entry::function_rva`]
214 161538 : pub fn address(&self) -> u32 {
215 161538 : self.ptr.address()
216 161538 : }
217 :
218 0 : pub fn function_rva(&self) -> u32 {
219 0 : self.ptr.function_rva()
220 0 : }
221 :
222 0 : pub fn is_extern(&self) -> bool {
223 0 : self.ptr.is_extern()
224 0 : }
225 :
226 0 : pub fn is_forwarded(&self) -> bool {
227 0 : self.ptr.is_forwarded()
228 0 : }
229 :
230 : /// Demangled representation of the symbol or an empty string if it can't
231 : /// be demangled
232 0 : pub fn demangled_name(&self) -> String {
233 0 : self.ptr.demangled_name().to_string()
234 0 : }
235 :
236 0 : pub fn forward_info(&self) -> Option<ForwardInfo> {
237 0 : if !self.ptr.is_forwarded() {
238 0 : return None;
239 0 : }
240 0 : Some(ForwardInfo::with_values(
241 0 : self.ptr.fwd_library().to_string(),
242 0 : self.ptr.fwd_function().to_string(),
243 0 : ))
244 0 : }
245 :
246 0 : pub fn set_ordinal(&mut self, ordinal: u16) -> &mut Self {
247 0 : self.ptr.pin_mut().set_ordinal(ordinal);
248 0 : self
249 0 : }
250 :
251 0 : pub fn set_address(&mut self, address: u32) -> &mut Self {
252 0 : self.ptr.pin_mut().set_address(address);
253 0 : self
254 0 : }
255 : }
256 :
257 : impl generic::Symbol for Entry<'_> {
258 484614 : fn as_generic(&self) -> &ffi::AbstractSymbol {
259 484614 : self.ptr.as_ref().unwrap().as_ref()
260 484614 : }
261 :
262 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
263 0 : unsafe {
264 0 : Pin::new_unchecked({
265 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
266 0 : as *mut ffi::AbstractSymbol)
267 0 : .as_mut()
268 0 : .unwrap()
269 0 : })
270 0 : }
271 0 : }
272 : }
273 :
274 : impl std::fmt::Debug for Entry<'_> {
275 161538 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
276 161538 : let base = self as &dyn generic::Symbol;
277 161538 : f.debug_struct("ExportEntry")
278 161538 : .field("base", &base)
279 161538 : .field("ordinal", &self.ordinal())
280 161538 : .field("address", &self.address())
281 161538 : .finish()
282 161538 : }
283 : }
284 :
285 : impl<'a> FromFFI<ffi::PE_ExportEntry> for Entry<'a> {
286 161538 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExportEntry>) -> Self {
287 161538 : Entry {
288 161538 : ptr,
289 161538 : _owner: PhantomData,
290 161538 : }
291 161538 : }
292 : }
293 :
294 : pub struct ForwardInfo {
295 : pub library: String,
296 : pub function: String,
297 : }
298 :
299 : impl ForwardInfo {
300 0 : pub fn with_values(library: String, function: String) -> Self {
301 0 : Self { library, function }
302 0 : }
303 : }
304 :
305 161538 : declare_iterator!(
306 161538 : ExportEntries,
307 161538 : Entry<'a>,
308 161538 : ffi::PE_ExportEntry,
309 161538 : ffi::PE_Export,
310 161538 : ffi::PE_Export_it_entries
311 161538 : );
|