pelite\pe64/
headers.rs

1/*!
2PE headers.
3 */
4
5use std::slice;
6use std::ops::Range;
7
8use super::Pe;
9use super::image::*;
10
11pub use crate::wrap::sections::*;
12
13/// Describes the PE headers.
14#[derive(Copy, Clone)]
15pub struct Headers<P> {
16	pe: P,
17}
18
19impl<'a, P: Pe<'a>> Headers<P> {
20	pub(crate) fn new(pe: P) -> Headers<P> {
21		Headers { pe }
22	}
23	/// Gets the PE instance.
24	pub fn pe(&self) -> P {
25		self.pe
26	}
27	/// Gets the PE headers as a byte slice.
28	pub fn image(&self) -> &'a [u8] {
29		unsafe { self.pe.image().get_unchecked(..self.pe.optional_header().SizeOfHeaders as usize) }
30	}
31	/// Calculates the optional header's CheckSum.
32	pub fn check_sum(&self) -> u32 {
33		let image = self.pe.image();
34		let check_sum_position = (
35			self.pe.dos_header().e_lfanew as usize +
36			dataview::offset_of!(IMAGE_NT_HEADERS.OptionalHeader) +
37			dataview::offset_of!(IMAGE_OPTIONAL_HEADER.CheckSum)) / 4;
38		let dwords = unsafe { slice::from_raw_parts(image.as_ptr() as *const u32, image.len() / 4) };
39		let mut check_sum = 0u64;
40		for i in 0..dwords.len() {
41			if i == check_sum_position {
42				continue;
43			}
44			let dw = dwords[i];
45			check_sum = (check_sum & 0xffffffff) + dw as u64 + (check_sum >> 32);
46			if check_sum > 0xffffffff {
47				check_sum = (check_sum & 0xffffffff) + (check_sum >> 32);
48			}
49		}
50		check_sum = (check_sum & 0xffff) + (check_sum >> 16);
51		check_sum = check_sum + (check_sum >> 16);
52		check_sum = check_sum & 0xffff;
53
54		check_sum += image.len() as u64;
55
56		check_sum as u32
57	}
58	/// Gets the code range from the optional header.
59	pub fn code_range(&self) -> Range<Rva> {
60		let optional_header = self.pe.optional_header();
61		optional_header.BaseOfCode..u32::wrapping_add(optional_header.BaseOfCode, optional_header.SizeOfCode)
62	}
63	/// Gets the full image range excluding the PE headers.
64	pub fn image_range(&self) -> Range<Rva> {
65		let optional_header = self.pe.optional_header();
66		optional_header.SizeOfHeaders..optional_header.SizeOfImage
67	}
68}
69
70/*
71	"headers": {
72		"DosHeader": { .. }
73		"NtHeaders": {
74			"Signature": ..,
75			"FileHeader": { .. }
76			"OptionalHeader": { .. }
77		}
78		"DataDirectory": [ .. ]
79		"SectionHeaders": [ .. ]
80		"details": {
81			"DosHeader.e_magic": "MZ",
82			"NtHeaders.Signature": "PE",
83			"FileHeader.Machine": "AMD",
84			"FileHeader.Characteristics": [],
85			"OptionalHeader.Magic": "PE32+",
86			"DataDirectory.Names": ["Exports", "Imports", ..],
87			"DataDirectory.Sections": [1, 1, ..],
88			"SectionHeaders.Characteristics": [["executable", "read", "write"], ["read"], ["read", "write"]],
89		}
90	}
91*/
92
93#[cfg(feature = "serde")]
94mod serde {
95	use crate::util::serde_helper::*;
96	use crate::stringify;
97	use super::{Pe, Headers};
98
99	impl<'a, P: Pe<'a>> Serialize for Headers<P> {
100		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
101			let mut state = serializer.serialize_struct("Headers", 5)?;
102			state.serialize_field("DosHeader", self.pe.dos_header())?;
103			state.serialize_field("NtHeaders", self.pe.nt_headers())?;
104			state.serialize_field("DataDirectory", self.pe.data_directory())?;
105			state.serialize_field("SectionHeaders", self.pe.section_headers())?;
106			state.serialize_field("details", &Details { pe: self.pe })?;
107			state.end()
108		}
109	}
110
111	struct Details<P> { pe: P }
112	impl<'a, P: Pe<'a>> Serialize for Details<P> {
113		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
114			let mut state = serializer.serialize_struct("Details", 11)?;
115
116			state.serialize_field("DosHeader.e_magic", "MZ")?;
117			state.serialize_field("NtHeaders.Signature", "PE")?;
118
119			let file_header = self.pe.file_header();
120			state.serialize_field("FileHeader.Machine", &stringify::Machine(file_header.Machine).to_str())?;
121			state.serialize_field("FileHeader.Characteristics", &SerdeIter(stringify::FileChars(file_header.Characteristics).to_strs()))?;
122
123			let optional_header = self.pe.optional_header();
124			state.serialize_field("OptionalHeader.Magic", &stringify::OptionalMagic(optional_header.Magic).to_str())?;
125			state.serialize_field("OptionalHeader.CheckSum", &Headers { pe: self.pe }.check_sum())?;
126			state.serialize_field("OptionalHeader.Subsystem", &stringify::Subsystem(optional_header.Subsystem).to_str())?;
127			state.serialize_field("OptionalHeader.DllCharacteristics", &SerdeIter(stringify::DllChars(optional_header.DllCharacteristics).to_strs()))?;
128
129			let data_directory_names = (0..self.pe.data_directory().len()).map(stringify::DirectoryEntry).map(stringify::DirectoryEntry::to_str);
130			state.serialize_field("DataDirectory.Names", &SerdeIter(data_directory_names))?;
131
132			let data_directory_sects = self.pe.data_directory().iter().map(|dd| {
133				self.pe.section_headers().iter().position(|&sect| dd.VirtualAddress >= sect.VirtualAddress && dd.VirtualAddress < sect.VirtualAddress + sect.VirtualSize)
134			});
135			state.serialize_field("DataDirectory.Sections", &SerdeIter(data_directory_sects))?;
136
137			let sections_chars = self.pe.section_headers().iter().map(|sect| {
138				let section_chars = sect.Characteristics;
139				SerdeIter(stringify::SectionChars(section_chars).to_strs())
140			});
141			state.serialize_field("SectionHeaders.Characteristics", &SerdeIter(sections_chars))?;
142
143			state.end()
144		}
145	}
146}