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
use std::prelude::v1::*;
use crate::Result;
use super::pe::validate_headers;
use super::{Align, Pe, PeObject};
#[derive(Copy, Clone)]
pub struct PeFile<'a> {
image: &'a [u8],
}
impl<'a> PeFile<'a> {
pub fn from_bytes<T: AsRef<[u8]> + ?Sized>(image: &'a T) -> Result<PeFile<'a>> {
let image = image.as_ref();
let _ = validate_headers(image)?;
Ok(PeFile { image })
}
pub fn to_view(self) -> Vec<u8> {
let (sizeof_headers, sizeof_image) = {
let optional_header = self.optional_header();
(optional_header.SizeOfHeaders, optional_header.SizeOfImage)
};
let mut vec = vec![0u8; sizeof_image as usize];
let image = self.image();
unsafe {
let dest_headers = vec.get_unchecked_mut(..sizeof_headers as usize);
let src_headers = image.get_unchecked(..sizeof_headers as usize);
dest_headers.copy_from_slice(src_headers);
}
for section in self.section_headers() {
let dest = vec.get_mut(section.VirtualAddress as usize..u32::wrapping_add(section.VirtualAddress, section.VirtualSize) as usize);
let src = image.get(section.PointerToRawData as usize..u32::wrapping_add(section.PointerToRawData, section.SizeOfRawData) as usize);
if let (Some(dest), Some(src)) = (dest, src) {
dest.copy_from_slice(src);
}
}
vec
}
}
unsafe impl<'a> Pe<'a> for PeFile<'a> {}
unsafe impl<'a> PeObject<'a> for PeFile<'a> {
fn image(&self) -> &'a [u8] {
self.image
}
fn align(&self) -> Align {
Align::File
}
#[cfg(feature = "serde")]
fn serde_name(&self) -> &'static str {
"PeFile"
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for PeFile<'a> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
super::pe::serialize_pe(*self, serializer)
}
}
#[test]
fn from_byte_slice() {
assert!(match PeFile::from_bytes(&[]) { Err(crate::Error::Bounds) => true, _ => false });
}