From e82b35cee4e2144eaf9991f7667b4233fe876c45 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Fri, 29 Jul 2022 11:37:24 +0200 Subject: [PATCH] fix: Search all ImageDebugDirectory entries for CodeView records There can be more than one ImageDebugDirectory entries, and any of those can be the CodeView record we are looking for. --- src/read/pe/file.rs | 83 +++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/src/read/pe/file.rs b/src/read/pe/file.rs index 15b42074..8dd85131 100644 --- a/src/read/pe/file.rs +++ b/src/read/pe/file.rs @@ -304,49 +304,60 @@ where None => return Ok(None), }; let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?; - let debug_dir = debug_data - .read_at::(0) - .read_error("Invalid PE debug dir size")?; + let debug_data_size = data_dir.size.get(LE) as usize; - if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW { - return Ok(None); + let count = debug_data_size / mem::size_of::(); + let rem = debug_data_size % mem::size_of::(); + if rem != 0 || count < 1 { + return Err(Error("Invalid PE debug dir size")); } - let info = self - .data - .read_slice_at::( - debug_dir.pointer_to_raw_data.get(LE) as u64, - debug_dir.size_of_data.get(LE) as usize, - ) - .read_error("Invalid CodeView Info address")?; - - let mut info = Bytes(info); - - let sig = info - .read_bytes(4) - .read_error("Invalid CodeView signature")?; - if sig.0 != b"RSDS" { - return Ok(None); - } + let debug_dirs = debug_data + .read_slice_at::(0, count) + .read_error("Invalid PE debug dir size")?; + + for debug_dir in debug_dirs { + if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW { + continue; + } + + let info = self + .data + .read_slice_at::( + debug_dir.pointer_to_raw_data.get(LE) as u64, + debug_dir.size_of_data.get(LE) as usize, + ) + .read_error("Invalid CodeView Info address")?; + + let mut info = Bytes(info); + + let sig = info + .read_bytes(4) + .read_error("Invalid CodeView signature")?; + if sig.0 != b"RSDS" { + continue; + } - let guid: [u8; 16] = info - .read_bytes(16) - .read_error("Invalid CodeView GUID")? - .0 - .try_into() - .unwrap(); + let guid: [u8; 16] = info + .read_bytes(16) + .read_error("Invalid CodeView GUID")? + .0 + .try_into() + .unwrap(); - let age = info.read::>().read_error("Invalid CodeView Age")?; + let age = info.read::>().read_error("Invalid CodeView Age")?; - let path = info - .read_string() - .read_error("Invalid CodeView file path")?; + let path = info + .read_string() + .read_error("Invalid CodeView file path")?; - Ok(Some(CodeView { - path: ByteString(path), - guid, - age: age.get(LE), - })) + return Ok(Some(CodeView { + path: ByteString(path), + guid, + age: age.get(LE), + })); + } + Ok(None) } fn has_debug_symbols(&self) -> bool {