1use std::slice;
6use std::ops::Range;
7
8use super::Pe;
9use super::image::*;
10
11pub use crate::wrap::sections::*;
12
13#[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 pub fn pe(&self) -> P {
25 self.pe
26 }
27 pub fn image(&self) -> &'a [u8] {
29 unsafe { self.pe.image().get_unchecked(..self.pe.optional_header().SizeOfHeaders as usize) }
30 }
31 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 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 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#[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(|§| 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}