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::{FromFFI, AsFFI};
7 : use crate::declare_iterator;
8 : use crate::generic;
9 :
10 : use std::marker::PhantomData;
11 :
12 : pub struct Export<'a> {
13 : ptr: cxx::UniquePtr<ffi::PE_Export>,
14 : _owner: PhantomData<&'a ffi::PE_Binary>,
15 : }
16 :
17 : impl Export<'_> {
18 : /// Create a new Export object
19 0 : pub fn new() -> Export<'static> {
20 0 : Export::from_ffi(ffi::PE_Export::create())
21 0 : }
22 :
23 : /// According to the PE specifications this value is reserved and should be set to 0
24 80 : pub fn export_flags(&self) -> u32 {
25 80 : self.ptr.export_flags()
26 80 : }
27 :
28 : /// The time and date that the export data was created
29 80 : pub fn timestamp(&self) -> u32 {
30 80 : self.ptr.timestamp()
31 80 : }
32 :
33 : /// The major version number (can be user-defined)
34 80 : pub fn major_version(&self) -> u16 {
35 80 : self.ptr.major_version()
36 80 : }
37 :
38 : /// The minor version number (can be user-defined)
39 80 : pub fn minor_version(&self) -> u16 {
40 80 : self.ptr.minor_version()
41 80 : }
42 :
43 : /// The starting number for the exports. Usually this value is set to 1
44 80 : pub fn ordinal_base(&self) -> u32 {
45 80 : self.ptr.ordinal_base()
46 80 : }
47 :
48 : /// The name of the library exported (e.g. `KERNEL32.dll`)
49 80 : pub fn name(&self) -> String {
50 80 : self.ptr.name().to_string()
51 80 : }
52 :
53 : /// Iterator over the different [`Entry`] exported by this table
54 80 : pub fn entries(&self) -> ExportEntries {
55 80 : ExportEntries::new(self.ptr.entries())
56 80 : }
57 :
58 : /// Address of the ASCII DLL's name (RVA)
59 0 : pub fn name_rva(&self) -> u32 {
60 0 : self.ptr.name_rva()
61 0 : }
62 :
63 : /// RVA to the list of exported names
64 0 : pub fn names_addr_table_rva(&self) -> u32 {
65 0 : self.ptr.names_addr_table_rva()
66 0 : }
67 :
68 : /// Number of exports by name
69 0 : pub fn names_addr_table_cnt(&self) -> u32 {
70 0 : self.ptr.names_addr_table_cnt()
71 0 : }
72 :
73 : /// RVA of the export address table
74 0 : pub fn export_addr_table_rva(&self) -> u32 {
75 0 : self.ptr.export_addr_table_rva()
76 0 : }
77 :
78 : /// Number of entries in the export address table
79 0 : pub fn export_addr_table_cnt(&self) -> u32 {
80 0 : self.ptr.export_addr_table_cnt()
81 0 : }
82 :
83 : /// RVA to the list of exported ordinals
84 0 : pub fn ord_addr_table_rva(&self) -> u32 {
85 0 : self.ptr.ord_addr_table_rva()
86 0 : }
87 :
88 : /// Change or set the export flags
89 0 : pub fn set_export_flags(&mut self, flags: u32) -> &mut Self {
90 0 : self.ptr.pin_mut().set_export_flags(flags);
91 0 : self
92 0 : }
93 :
94 : /// Change or set the timestamp
95 0 : pub fn set_timestamp(&mut self, timestamp: u32) -> &mut Self {
96 0 : self.ptr.pin_mut().set_export_flags(timestamp);
97 0 : self
98 0 : }
99 :
100 : /// Change or set the major version of the DLL
101 0 : pub fn set_major_version(&mut self, version: u32) -> &mut Self {
102 0 : self.ptr.pin_mut().set_major_version(version);
103 0 : self
104 0 : }
105 :
106 : /// Change or set the minor version of the DLL
107 0 : pub fn set_minor_version(&mut self, version: u32) -> &mut Self {
108 0 : self.ptr.pin_mut().set_minor_version(version);
109 0 : self
110 0 : }
111 :
112 : /// Change or set the name of the DLL
113 0 : pub fn set_name(&mut self, name: &str) -> &mut Self {
114 0 : self.ptr.pin_mut().set_name(name);
115 0 : self
116 0 : }
117 :
118 : /// Find the export entry with the given name
119 0 : pub fn entry_by_name(&self, name: &str) -> Option<Entry> {
120 0 : into_optional(self.ptr.entry_by_name(name))
121 0 : }
122 :
123 : /// Find the export entry with the given ordinal number
124 0 : pub fn entry_by_ordinal(&self, ordinal: u32) -> Option<Entry> {
125 0 : into_optional(self.ptr.entry_by_ordinal(ordinal))
126 0 : }
127 :
128 : /// Find the export entry at the provided RVA
129 0 : pub fn entry_at_rva(&self, rva: u32) -> Option<Entry> {
130 0 : into_optional(self.ptr.entry_at_rva(rva))
131 0 : }
132 :
133 : /// Add the given export and return the newly created and added export
134 0 : pub fn add_entry(&mut self, entry: &Entry) -> Entry {
135 0 : Entry::from_ffi(self.ptr.pin_mut().add_entry(entry.ptr.as_ref().unwrap()))
136 0 : }
137 :
138 : /// Add a new export entry given its name and its RVA
139 0 : pub fn add_entry_by_name(&mut self, name: &str, rva: u32) -> Entry {
140 0 : Entry::from_ffi(self.ptr.pin_mut().add_entry_by_name(name, rva))
141 0 : }
142 :
143 : /// Remove the given export entry
144 0 : pub fn remove_entry(&mut self, entry: Entry) -> bool {
145 0 : self.ptr.pin_mut().remove_entry(entry.ptr)
146 0 : }
147 :
148 : /// Remove the export entry with the given RVA
149 0 : pub fn remove_entry_at(&mut self, rva: u32) -> bool {
150 0 : self.ptr.pin_mut().remove_entry_at(rva)
151 0 : }
152 :
153 : /// Remove the export entry with the given RVA
154 0 : pub fn remove_entry_by_name(&mut self, name: &str) -> bool {
155 0 : self.ptr.pin_mut().remove_entry_by_name(name)
156 0 : }
157 :
158 : }
159 :
160 : impl std::fmt::Debug for Export<'_> {
161 80 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 80 : f.debug_struct("Export")
163 80 : .field("export_flags", &self.export_flags())
164 80 : .field("timestamp", &self.timestamp())
165 80 : .field("major_version", &self.major_version())
166 80 : .field("minor_version", &self.minor_version())
167 80 : .field("ordinal_base", &self.ordinal_base())
168 80 : .field("name", &self.name())
169 80 : .finish()
170 80 : }
171 : }
172 :
173 : impl<'a> FromFFI<ffi::PE_Export> for Export<'a> {
174 80 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Export>) -> Self {
175 80 : Export {
176 80 : ptr,
177 80 : _owner: PhantomData,
178 80 : }
179 80 : }
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 124260 : pub fn ordinal(&self) -> u16 {
207 124260 : self.ptr.ordinal()
208 124260 : }
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 124260 : pub fn address(&self) -> u32 {
215 124260 : self.ptr.address()
216 124260 : }
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(self.ptr.fwd_library().to_string(), self.ptr.fwd_function().to_string()))
241 0 : }
242 :
243 0 : pub fn set_ordinal(&mut self, ordinal: u16) -> &mut Self {
244 0 : self.ptr.pin_mut().set_ordinal(ordinal);
245 0 : self
246 0 : }
247 :
248 0 : pub fn set_address(&mut self, address: u32) -> &mut Self {
249 0 : self.ptr.pin_mut().set_address(address);
250 0 : self
251 0 : }
252 : }
253 :
254 : impl generic::Symbol for Entry<'_> {
255 372780 : fn as_generic(&self) -> &ffi::AbstractSymbol {
256 372780 : self.ptr.as_ref().unwrap().as_ref()
257 372780 : }
258 : }
259 :
260 : impl std::fmt::Debug for Entry<'_> {
261 124260 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
262 124260 : let base = self as &dyn generic::Symbol;
263 124260 : f.debug_struct("ExportEntry")
264 124260 : .field("base", &base)
265 124260 : .field("ordinal", &self.ordinal())
266 124260 : .field("address", &self.address())
267 124260 : .finish()
268 124260 : }
269 : }
270 :
271 : impl<'a> FromFFI<ffi::PE_ExportEntry> for Entry<'a> {
272 124260 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExportEntry>) -> Self {
273 124260 : Entry {
274 124260 : ptr,
275 124260 : _owner: PhantomData,
276 124260 : }
277 124260 : }
278 : }
279 :
280 : pub struct ForwardInfo {
281 : pub library: String,
282 : pub function: String,
283 : }
284 :
285 : impl ForwardInfo {
286 0 : pub fn with_values(library: String, function: String) -> Self {
287 0 : Self {
288 0 : library, function
289 0 : }
290 0 : }
291 : }
292 :
293 124260 : declare_iterator!(
294 124260 : ExportEntries,
295 124260 : Entry<'a>,
296 124260 : ffi::PE_ExportEntry,
297 124260 : ffi::PE_Export,
298 124260 : ffi::PE_Export_it_entries
299 124260 : );
|