-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathpe_object.rs
More file actions
107 lines (94 loc) · 3.59 KB
/
pe_object.rs
File metadata and controls
107 lines (94 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::pe::{PeOffsetError, PeOffsets, PeTrait};
use crate::usize_from_u32;
use core::mem;
use core::ops::Range;
use object::pe::{IMAGE_DIRECTORY_ENTRY_SECURITY, ImageDataDirectory};
use object::read::pe::ImageOptionalHeader;
use object::read::pe::{ImageNtHeaders, PeFile};
use object::{LittleEndian, SectionIndex, pod};
impl<'data, I> PeTrait for PeFile<'data, I>
where
I: ImageNtHeaders,
{
fn data(&self) -> &'data [u8] {
self.data()
}
fn num_sections(&self) -> usize {
self.section_table().len()
}
fn section_data_range(
&self,
index: usize,
) -> Result<Range<usize>, PeOffsetError> {
let section = self
.section_table()
.section(SectionIndex(index))
.expect("invalid index");
let start =
usize_from_u32(section.pointer_to_raw_data.get(LittleEndian));
let size = usize_from_u32(section.size_of_raw_data.get(LittleEndian));
let end = start.checked_add(size).ok_or(PeOffsetError)?;
Ok(start..end)
}
fn certificate_table_range(
&self,
) -> Result<Option<Range<usize>>, PeOffsetError> {
if let Some(dir) = self.data_directory(IMAGE_DIRECTORY_ENTRY_SECURITY) {
let start = usize_from_u32(dir.virtual_address.get(LittleEndian));
let size = usize_from_u32(dir.size.get(LittleEndian));
let end = start.checked_add(size).ok_or(PeOffsetError)?;
Ok(Some(start..end))
} else {
Ok(None)
}
}
fn offsets(&self) -> Result<PeOffsets, PeOffsetError> {
object_offsets_impl(self).ok_or(PeOffsetError)
}
}
fn object_offsets_impl<I>(pe: &PeFile<I>) -> Option<PeOffsets>
where
I: ImageNtHeaders,
{
// Calculate the offset from the start of the pe data to the
// beginning of `bytes`.
let get_offset = |bytes: &[u8]| -> Option<usize> {
let base = pe.data().as_ptr() as usize;
let bytes_start = bytes.as_ptr() as usize;
bytes_start.checked_sub(base)
};
// Get checksum offset.
let optional_header = pe.nt_headers().optional_header();
let optional_header_bytes = pod::bytes_of(optional_header);
let optional_header_offset = get_offset(optional_header_bytes)?;
let check_sum_offset = optional_header_offset.checked_add(
// The offset of the `check_sum` field is the same within both
// the 32-bit and 64-bit headers.
64,
)?;
// Hash from checksum to the security data directory.
let data_dirs_offset =
optional_header_offset.checked_add(optional_header_bytes.len())?;
let sec_dir_offset = data_dirs_offset.checked_add(
mem::size_of::<ImageDataDirectory>()
.checked_mul(IMAGE_DIRECTORY_ENTRY_SECURITY)?,
)?;
// Hash from the security data directory to the end of the header.
let sec_dir_size = mem::size_of::<ImageDataDirectory>();
let size_of_headers =
usize_from_u32(pe.nt_headers().optional_header().size_of_headers());
Some(PeOffsets {
check_sum: check_sum_offset,
after_check_sum: check_sum_offset.checked_add(mem::size_of::<u32>())?,
security_data_dir: sec_dir_offset,
after_security_data_dir: sec_dir_offset.checked_add(sec_dir_size)?,
after_header: size_of_headers,
})
}