authenticode/
pe_object.rs1use crate::pe::{PeOffsetError, PeOffsets, PeTrait};
10use crate::usize_from_u32;
11use core::mem;
12use core::ops::Range;
13use object::pe::{ImageDataDirectory, IMAGE_DIRECTORY_ENTRY_SECURITY};
14use object::read::pe::ImageOptionalHeader;
15use object::read::pe::{ImageNtHeaders, PeFile};
16use object::{pod, LittleEndian, SectionIndex};
17
18impl<'data, I> PeTrait for PeFile<'data, I>
19where
20 I: ImageNtHeaders,
21{
22 fn data(&self) -> &'data [u8] {
23 self.data()
24 }
25
26 fn num_sections(&self) -> usize {
27 self.section_table().len()
28 }
29
30 fn section_data_range(
31 &self,
32 index: usize,
33 ) -> Result<Range<usize>, PeOffsetError> {
34 let section = self
35 .section_table()
36 .section(SectionIndex(index))
37 .expect("invalid index");
38 let start =
39 usize_from_u32(section.pointer_to_raw_data.get(LittleEndian));
40 let size = usize_from_u32(section.size_of_raw_data.get(LittleEndian));
41 let end = start.checked_add(size).ok_or(PeOffsetError)?;
42 Ok(start..end)
43 }
44
45 fn certificate_table_range(
46 &self,
47 ) -> Result<Option<Range<usize>>, PeOffsetError> {
48 if let Some(dir) = self.data_directory(IMAGE_DIRECTORY_ENTRY_SECURITY) {
49 let start = usize_from_u32(dir.virtual_address.get(LittleEndian));
50 let size = usize_from_u32(dir.size.get(LittleEndian));
51 let end = start.checked_add(size).ok_or(PeOffsetError)?;
52 Ok(Some(start..end))
53 } else {
54 Ok(None)
55 }
56 }
57
58 fn offsets(&self) -> Result<PeOffsets, PeOffsetError> {
59 object_offsets_impl(self).ok_or(PeOffsetError)
60 }
61}
62
63fn object_offsets_impl<I>(pe: &PeFile<I>) -> Option<PeOffsets>
64where
65 I: ImageNtHeaders,
66{
67 let get_offset = |bytes: &[u8]| -> Option<usize> {
70 let base = pe.data().as_ptr() as usize;
71 let bytes_start = bytes.as_ptr() as usize;
72 bytes_start.checked_sub(base)
73 };
74
75 let optional_header = pe.nt_headers().optional_header();
77 let optional_header_bytes = pod::bytes_of(optional_header);
78 let optional_header_offset = get_offset(optional_header_bytes)?;
79 let check_sum_offset = optional_header_offset.checked_add(
80 64,
83 )?;
84
85 let data_dirs_offset =
87 optional_header_offset.checked_add(optional_header_bytes.len())?;
88 let sec_dir_offset = data_dirs_offset.checked_add(
89 mem::size_of::<ImageDataDirectory>()
90 .checked_mul(IMAGE_DIRECTORY_ENTRY_SECURITY)?,
91 )?;
92
93 let sec_dir_size = mem::size_of::<ImageDataDirectory>();
95 let size_of_headers =
96 usize_from_u32(pe.nt_headers().optional_header().size_of_headers());
97
98 Some(PeOffsets {
99 check_sum: check_sum_offset,
100 after_check_sum: check_sum_offset.checked_add(mem::size_of::<u32>())?,
101
102 security_data_dir: sec_dir_offset,
103 after_security_data_dir: sec_dir_offset.checked_add(sec_dir_size)?,
104
105 after_header: size_of_headers,
106 })
107}