diff --git a/src/pe/mod.rs b/src/pe/mod.rs index c3c2693b..0405c61c 100644 --- a/src/pe/mod.rs +++ b/src/pe/mod.rs @@ -33,6 +33,7 @@ use crate::container; use crate::error; use crate::pe::utils::pad; use crate::strtab; +use options::ParseMode; use scroll::{ctx, Pwrite}; @@ -264,11 +265,19 @@ impl<'a> PE<'a> { if let Some(&certificate_table) = optional_header.data_directories.get_certificate_table() { - certificates = certificate_table::enumerate_certificates( + let certificates_result = certificate_table::enumerate_certificates( bytes, certificate_table.virtual_address, certificate_table.size, - )?; + ); + + certificates = match opts.parse_mode { + ParseMode::Strict => certificates_result?, + ParseMode::Permissive => certificates_result.unwrap_or_else(|err| { + warn!("Cannot parse CertificateTable: {:?}", err); + Default::default() + }), + }; certificate_table.size as usize } else { @@ -522,10 +531,7 @@ pub struct TE<'a> { impl<'a> TE<'a> { /// Reads a TE binary from the underlying `bytes` pub fn parse(bytes: &'a [u8]) -> error::Result { - let opts = &options::ParseOptions { - resolve_rva: false, - parse_attribute_certificates: false, - }; + let opts = &options::ParseOptions::te(); let mut offset = 0; diff --git a/src/pe/options.rs b/src/pe/options.rs index 4461a4c7..2330ba00 100644 --- a/src/pe/options.rs +++ b/src/pe/options.rs @@ -1,4 +1,5 @@ /// Parsing Options structure for the PE parser +#[non_exhaustive] #[derive(Debug, Copy, Clone)] pub struct ParseOptions { /// Wether the parser should resolve rvas or not. Default: true @@ -8,14 +9,35 @@ pub struct ParseOptions { /// memory](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#other-contents-of-the-file). /// For on-disk representations, leave as true. Default: true pub parse_attribute_certificates: bool, + /// Whether or not to end with an error in case of incorrect data or continue parsing if able. Default: ParseMode::Strict + pub parse_mode: ParseMode, } -impl ParseOptions { +#[derive(Debug, Copy, Clone)] +pub enum ParseMode { + /// Always end with error on incorrect data + Strict, + /// Incorrect data will not cause to end with error if possible + Permissive, +} + +impl Default for ParseOptions { /// Returns a parse options structure with default values - pub fn default() -> Self { + fn default() -> Self { ParseOptions { resolve_rva: true, parse_attribute_certificates: true, + parse_mode: ParseMode::Strict, + } + } +} + +impl ParseOptions { + pub(crate) fn te() -> Self { + Self { + resolve_rva: false, + parse_attribute_certificates: false, + parse_mode: ParseMode::Strict, } } }