Skip to content

Commit

Permalink
fix: don't abort PE parsing when opt_hdr.magic is incorrect.
Browse files Browse the repository at this point in the history
When a file is corrupt `opt_hdr.magic` may have an incorrect value that doesn't correspond to a 32-bit nor a 64-bit file. In such cases, instead of making the parsing fail, try to continue as it was a 32-bit file even if some values are incorrect. This is what YARA does, and this makes YARA-X closer to how YARA works in these edge cases.
  • Loading branch information
plusvic committed May 4, 2024
1 parent e21872b commit 9d9b01d
Show file tree
Hide file tree
Showing 4 changed files with 835 additions and 39 deletions.
31 changes: 19 additions & 12 deletions lib/src/modules/pe/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,10 +660,7 @@ impl<'a> PE<'a> {
opt_hdr.base_of_code,
),
) = tuple((
verify(le_u16, |magic| {
*magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC
|| *magic == Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC
}),
le_u16, // magic
u8, // major_linker_ver
u8, // minor_linker_ver
le_u32, // size_of_code
Expand All @@ -673,6 +670,14 @@ impl<'a> PE<'a> {
le_u32, // base_of_code
))(input)?;

// opt_hdr.magic should be either IMAGE_NT_OPTIONAL_HDR32_MAGIC
// or IMAGE_NT_OPTIONAL_HDR64_MAGIC, but when the file is corrupt
// and opt_hdr.magic is something else, we assume that the file
// is a 32-bit PE for the purpose of continuing parsing the
// remaining fields, because that's what YARA does. That's the
// case of:
// 3df167b04c52b47ae634b8114671ad3b7bf4e8af62a38a3d4bc0903f474ae2d9

(
remainder,
(
Expand All @@ -682,11 +687,11 @@ impl<'a> PE<'a> {
),
) = tuple((
cond(
opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC,
opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC,
le_u32,
),
cond(
opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC,
opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC,
le_u32,
),
cond(
Expand All @@ -696,8 +701,10 @@ impl<'a> PE<'a> {
))(remainder)?;

opt_hdr.base_of_data = base_of_data;
opt_hdr.image_base =
image_base64.or(image_base32.map(|i| i as u64)).unwrap();
opt_hdr.image_base = image_base32
.map(|i| i as u64)
.or(image_base64)
.unwrap_or_default();

(
remainder,
Expand Down Expand Up @@ -738,10 +745,10 @@ impl<'a> PE<'a> {
le_u32, // checksum
le_u16, // subsystem
le_u16, // dll_characteristics
uint(opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC),
uint(opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC),
uint(opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC),
uint(opt_hdr.magic == Self::IMAGE_NT_OPTIONAL_HDR32_MAGIC),
uint(opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC),
uint(opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC),
uint(opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC),
uint(opt_hdr.magic != Self::IMAGE_NT_OPTIONAL_HDR64_MAGIC),
le_u32, // loader_flags
le_u32, // number_of_rva_and_sizes
))(remainder)?;
Expand Down
Binary file not shown.
Loading

0 comments on commit 9d9b01d

Please sign in to comment.