Line data Source code
1 : //! Module for the PE file format support in LIEF.
2 : //!
3 : //! The [`Binary`] structure exposes the main API to inspect a PE file. It can be instantiated,
4 : //! using either: [`crate::pe::parse`], [`crate::pe::Binary::parse`] or [`crate::Binary::parse`]
5 : //!
6 : //! ```
7 : //! let pe = lief::pe::parse("demo.exe").unwrap();
8 : //! for section in pe.sections() {
9 : //! println!("section: {}", section.name());
10 : //! }
11 : //! ```
12 :
13 : use lief_ffi as ffi;
14 : use std::path::Path;
15 :
16 : pub mod binary;
17 : pub mod builder;
18 : pub mod chpe_metadata_arm64;
19 : pub mod chpe_metadata_x86;
20 : pub mod code_integrity;
21 : pub mod data_directory;
22 : pub mod debug;
23 : pub mod delay_import;
24 : pub mod dynamic_fixups;
25 : pub mod dynamic_relocation;
26 : pub mod enclave_configuration;
27 : pub mod exception;
28 : pub mod exception_aarch64;
29 : pub mod exception_x64;
30 : pub mod export;
31 : pub mod factory;
32 : pub mod headers;
33 : pub mod import;
34 : pub mod load_configuration;
35 : pub mod parser_config;
36 : pub mod relocation;
37 : pub mod resources;
38 : pub mod rich_header;
39 : pub mod section;
40 : pub mod signature;
41 : pub mod tls;
42 : pub mod volatile_metadata;
43 :
44 : #[doc(inline)]
45 : pub use binary::Binary;
46 : #[doc(inline)]
47 : pub use data_directory::DataDirectory;
48 : #[doc(inline)]
49 : pub use delay_import::DelayImport;
50 : #[doc(inline)]
51 : pub use dynamic_fixups::DynamicFixup;
52 : #[doc(inline)]
53 : pub use dynamic_relocation::DynamicRelocation;
54 : #[doc(inline)]
55 : pub use enclave_configuration::{EnclaveConfiguration, EnclaveImport};
56 : #[doc(inline)]
57 : pub use exception::{ExceptionInfo, RuntimeExceptionFunction};
58 : #[doc(inline)]
59 : pub use export::Export;
60 : #[doc(inline)]
61 : pub use factory::Factory;
62 : #[doc(inline)]
63 : pub use headers::{DosHeader, Header, OptionalHeader};
64 : #[doc(inline)]
65 : pub use import::Import;
66 : #[doc(inline)]
67 : pub use load_configuration::{CHPEMetadata, LoadConfiguration};
68 : #[doc(inline)]
69 : pub use parser_config::Config as ParserConfig;
70 : #[doc(inline)]
71 : pub use relocation::Relocation;
72 : #[doc(inline)]
73 : pub use resources::Accelerator as ResourceAccelerator;
74 : #[doc(inline)]
75 : pub use resources::Icon as ResourceIcon;
76 : #[doc(inline)]
77 : pub use resources::Manager as ResourcesManager;
78 : #[doc(inline)]
79 : pub use resources::Node as ResourceNode;
80 : #[doc(inline)]
81 : pub use resources::StringEntry as ResourceStringEntry;
82 : #[doc(inline)]
83 : pub use resources::Version as ResourceVersion;
84 : #[doc(inline)]
85 : pub use rich_header::{RichEntry, RichHeader};
86 : #[doc(inline)]
87 : pub use section::Section;
88 : #[doc(inline)]
89 : pub use signature::Signature;
90 : #[doc(inline)]
91 : pub use tls::TLS;
92 : #[doc(inline)]
93 : pub use volatile_metadata::VolatileMetadata;
94 :
95 : use crate::common::AsFFI;
96 :
97 : /// PE type: 32-bit or 64-bit
98 : #[allow(non_camel_case_types)]
99 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
100 : pub enum PE_TYPE {
101 : /// 32-bit PE
102 : PE32,
103 : /// 64-bit PE
104 : PE32_PLUS,
105 : UNKNOWN(u32),
106 : }
107 :
108 : impl From<u32> for PE_TYPE {
109 0 : fn from(value: u32) -> Self {
110 0 : match value {
111 0 : 0x10b => PE_TYPE::PE32,
112 0 : 0x20b => PE_TYPE::PE32_PLUS,
113 0 : _ => PE_TYPE::UNKNOWN(value),
114 : }
115 0 : }
116 : }
117 :
118 : impl From<PE_TYPE> for u32 {
119 0 : fn from(value: PE_TYPE) -> u32 {
120 0 : match value {
121 0 : PE_TYPE::PE32 => 0x10b,
122 0 : PE_TYPE::PE32_PLUS => 0x20b,
123 0 : PE_TYPE::UNKNOWN(v) => v,
124 : }
125 0 : }
126 : }
127 :
128 : #[allow(non_camel_case_types)]
129 1066 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
130 : pub enum Algorithms {
131 : SHA_512,
132 : SHA_384,
133 : SHA_256,
134 : SHA_1,
135 : MD5,
136 : MD4,
137 : MD2,
138 : RSA,
139 : EC,
140 : MD5_RSA,
141 : SHA1_DSA,
142 : SHA1_RSA,
143 : SHA_256_RSA,
144 : SHA_384_RSA,
145 : SHA_512_RSA,
146 : SHA1_ECDSA,
147 : SHA_256_ECDSA,
148 : SHA_384_ECDSA,
149 : SHA_512_ECDSA,
150 : UNKNOWN(u32),
151 : }
152 :
153 : impl From<u32> for Algorithms {
154 1066 : fn from(value: u32) -> Self {
155 1066 : match value {
156 0 : 0x00000001 => Algorithms::SHA_512,
157 0 : 0x00000002 => Algorithms::SHA_384,
158 494 : 0x00000003 => Algorithms::SHA_256,
159 208 : 0x00000004 => Algorithms::SHA_1,
160 39 : 0x00000005 => Algorithms::MD5,
161 0 : 0x00000006 => Algorithms::MD4,
162 0 : 0x00000007 => Algorithms::MD2,
163 260 : 0x00000008 => Algorithms::RSA,
164 0 : 0x00000009 => Algorithms::EC,
165 0 : 0x0000000a => Algorithms::MD5_RSA,
166 0 : 0x0000000b => Algorithms::SHA1_DSA,
167 0 : 0x0000000c => Algorithms::SHA1_RSA,
168 65 : 0x0000000d => Algorithms::SHA_256_RSA,
169 0 : 0x0000000e => Algorithms::SHA_384_RSA,
170 0 : 0x0000000f => Algorithms::SHA_512_RSA,
171 0 : 0x00000010 => Algorithms::SHA1_ECDSA,
172 0 : 0x00000011 => Algorithms::SHA_256_ECDSA,
173 0 : 0x00000012 => Algorithms::SHA_384_ECDSA,
174 0 : 0x00000013 => Algorithms::SHA_512_ECDSA,
175 0 : _ => Algorithms::UNKNOWN(value),
176 : }
177 1066 : }
178 : }
179 :
180 : impl From<Algorithms> for u32 {
181 169 : fn from(value: Algorithms) -> u32 {
182 169 : match value {
183 0 : Algorithms::SHA_512 => 0x00000001,
184 0 : Algorithms::SHA_384 => 0x00000002,
185 169 : Algorithms::SHA_256 => 0x00000003,
186 0 : Algorithms::SHA_1 => 0x00000004,
187 0 : Algorithms::MD5 => 0x00000005,
188 0 : Algorithms::MD4 => 0x00000006,
189 0 : Algorithms::MD2 => 0x00000007,
190 0 : Algorithms::RSA => 0x00000008,
191 0 : Algorithms::EC => 0x00000009,
192 0 : Algorithms::MD5_RSA => 0x0000000a,
193 0 : Algorithms::SHA1_DSA => 0x0000000b,
194 0 : Algorithms::SHA1_RSA => 0x0000000c,
195 0 : Algorithms::SHA_256_RSA => 0x0000000d,
196 0 : Algorithms::SHA_384_RSA => 0x0000000e,
197 0 : Algorithms::SHA_512_RSA => 0x0000000f,
198 0 : Algorithms::SHA1_ECDSA => 0x00000010,
199 0 : Algorithms::SHA_256_ECDSA => 0x00000011,
200 0 : Algorithms::SHA_384_ECDSA => 0x00000012,
201 0 : Algorithms::SHA_512_ECDSA => 0x00000013,
202 0 : Algorithms::UNKNOWN(_) => 0,
203 : }
204 169 : }
205 : }
206 :
207 : /// Parse a PE file from the given file path
208 0 : pub fn parse<P: AsRef<Path>>(path: P) -> Option<Binary> {
209 0 : Binary::parse(path)
210 0 : }
211 :
212 : /// Parse a PE file from the given file path and configuration
213 0 : pub fn parse_with_config<P: AsRef<Path>>(path: P, config: &ParserConfig) -> Option<Binary> {
214 0 : Binary::parse_with_config(path, config)
215 0 : }
216 :
217 : /// Check that the layout of the given binary is correct from the Windows loader
218 : /// perspective
219 0 : pub fn check_layout(binary: &Binary) -> Result<(), String> {
220 0 : cxx::let_cxx_string!(error = "");
221 0 : unsafe {
222 0 : if ffi::PE_Utils::check_layout(binary.as_ffi(), error.as_mut().get_unchecked_mut()) {
223 0 : return Ok(());
224 0 : }
225 0 : }
226 0 : Err(error.to_string())
227 0 : }
228 :
229 : /// Determine the PE type (PE32 or PE32+) of the given file
230 0 : pub fn get_type<P: AsRef<Path>>(path: P) -> Option<PE_TYPE> {
231 0 : let val = ffi::PE_Utils::get_type(path.as_ref().to_str().unwrap_or("").to_string());
232 0 : if val == 0 {
233 0 : return None;
234 0 : }
235 0 : Some(PE_TYPE::from(val))
236 0 : }
237 :
238 : /// Compute the import hash of the given binary
239 0 : pub fn get_imphash(binary: &Binary, mode: ImphashMode) -> String {
240 0 : ffi::PE_Utils::get_imphash(binary.as_ffi(), mode.into()).to_string()
241 0 : }
242 :
243 : /// Convert an OID string to a human-readable string
244 0 : pub fn oid_to_string(oid: &str) -> String {
245 0 : ffi::PE_Utils::oid_to_string(oid.to_string()).to_string()
246 0 : }
247 :
248 : /// Try to resolve import ordinals using the well-known ordinal lookup table
249 0 : pub fn resolve_ordinals<'a>(
250 0 : imp: &'a Import<'a>,
251 0 : strict: bool,
252 0 : use_std: bool,
253 0 : ) -> Option<Import<'a>> {
254 0 : crate::common::into_optional(ffi::PE_Utils::resolve_ordinals(
255 0 : imp.as_ffi(),
256 0 : strict,
257 0 : use_std,
258 0 : ))
259 0 : }
260 :
261 : /// Mode used for computing the import hash
262 : #[allow(non_camel_case_types)]
263 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
264 : pub enum ImphashMode {
265 : /// Default LIEF implementation
266 : DEFAULT,
267 : /// Use pefile algorithm (same as VirusTotal)
268 : PEFILE,
269 : UNKNOWN(u32),
270 : }
271 :
272 : impl From<u32> for ImphashMode {
273 0 : fn from(value: u32) -> Self {
274 0 : match value {
275 0 : 0x00000000 => ImphashMode::DEFAULT,
276 0 : 0x00000001 => ImphashMode::PEFILE,
277 0 : _ => ImphashMode::UNKNOWN(value),
278 : }
279 0 : }
280 : }
281 :
282 : impl From<ImphashMode> for u32 {
283 0 : fn from(value: ImphashMode) -> u32 {
284 0 : match value {
285 0 : ImphashMode::DEFAULT => 0x00000000,
286 0 : ImphashMode::PEFILE => 0x00000001,
287 0 : ImphashMode::UNKNOWN(v) => v,
288 : }
289 0 : }
290 : }
|