1use std::{cmp, mem, ptr, slice};
6
7use crate::{Error, Result};
8use crate::{util::CStr, util::FromBytes, util::AlignTo, Pod};
9
10use super::{Ptr, image::*};
11
12pub use crate::wrap::Align;
15
16pub unsafe trait PeObject<'a> {
17 fn image(&self) -> &'a [u8];
19
20 fn align(&self) -> Align;
22
23 #[cfg(feature = "serde")]
25 #[doc(hidden)]
26 fn serde_name(&self) -> &'static str;
27}
28
29pub unsafe trait Pe<'a>: PeObject<'a> + Copy {
30 fn dos_header(self) -> &'a IMAGE_DOS_HEADER {
32 unsafe { dos_header(self.image()) }
33 }
34 fn dos_image(self) -> &'a [u8] {
38 unsafe { dos_image(self.image()) }
39 }
40 fn nt_headers(self) -> &'a IMAGE_NT_HEADERS {
42 unsafe { nt_headers(self.image()) }
43 }
44 fn file_header(self) -> &'a IMAGE_FILE_HEADER {
46 unsafe { file_header(self.image()) }
47 }
48 fn optional_header(self) -> &'a IMAGE_OPTIONAL_HEADER {
50 unsafe { optional_header(self.image()) }
51 }
52 fn data_directory(self) -> &'a [IMAGE_DATA_DIRECTORY] {
54 unsafe { data_directory(self.image()) }
55 }
56 fn section_headers(self) -> &'a super::headers::SectionHeaders {
58 unsafe { section_headers(self.image()) }
59 }
60
61 fn headers(self) -> super::headers::Headers<Self> {
63 super::headers::Headers::new(self)
64 }
65
66 fn rva_to_file_offset(self, rva: Rva) -> Result<usize> {
81 if rva < self.optional_header().SizeOfHeaders {
83 return Ok(rva as usize);
84 }
85 for it in self.section_headers() {
87 #[allow(non_snake_case)]
90 let VirtualEnd = it.VirtualAddress.wrapping_add(cmp::max(it.VirtualSize, it.SizeOfRawData));
91 if it.VirtualAddress <= rva && rva < VirtualEnd { if let None = it.PointerToRawData.checked_add(it.SizeOfRawData) { return Err(Error::Overflow);
95 }
96 let section_offset = rva - it.VirtualAddress;
98 return if section_offset < it.SizeOfRawData { Ok((section_offset + it.PointerToRawData) as usize)
101 }
102 else if section_offset < it.VirtualSize {
104 Err(Error::ZeroFill)
105 }
106 else {
107 Err(Error::Bounds)
108 };
109 }
110 }
111 Err(Error::Bounds)
112 }
113 fn file_offset_to_rva(self, file_offset: usize) -> Result<Rva> {
126 if file_offset < self.optional_header().SizeOfHeaders as usize {
128 return Ok(file_offset as Rva);
129 }
130 for it in self.section_headers() {
132 #[allow(non_snake_case)]
135 let EndOfRawData = it.PointerToRawData.wrapping_add(it.SizeOfRawData);
136 if it.PointerToRawData as usize <= file_offset && file_offset < EndOfRawData as usize { if let None = it.VirtualAddress.checked_add(it.VirtualSize) { return Err(Error::Overflow);
140 }
141 let section_offset = file_offset as Rva - it.PointerToRawData;
143 return if section_offset < it.VirtualSize { Ok(section_offset + it.VirtualAddress)
146 }
147 else if section_offset < it.SizeOfRawData {
149 Err(Error::Unmapped)
150 }
151 else {
152 Err(Error::Bounds)
153 };
154 }
155 }
156 Err(Error::Bounds)
157 }
158
159 fn rva_to_va(self, rva: Rva) -> Result<Va> {
169 if rva == 0 {
170 Err(Error::Null)
171 }
172 else {
173 let (image_base, size_of_image) = {
174 let optional_header = self.optional_header();
175 (optional_header.ImageBase, optional_header.SizeOfImage)
176 };
177 if rva < size_of_image {
178 Ok(image_base + rva as Va)
179 }
180 else {
181 Err(Error::Bounds)
182 }
183 }
184 }
185 fn va_to_rva(self, va: Va) -> Result<Rva> {
195 if va == 0 {
196 Err(Error::Null)
197 }
198 else {
199 let (image_base, size_of_image) = {
200 let optional_header = self.optional_header();
201 (optional_header.ImageBase, optional_header.SizeOfImage)
202 };
203 if va < image_base || va - image_base > size_of_image as Va {
205 Err(Error::Bounds)
206 }
207 else {
208 Ok((va - image_base) as Rva)
209 }
210 }
211 }
212
213 fn slice(&self, rva: Rva, min_size_of: usize, align: usize) -> Result<&'a [u8]> {
228 unsafe {
229 match (self.align(), self.image()) {
230 (Align::File, image) => slice_file(image, rva, min_size_of, align),
231 (Align::Section, image) => slice_section(image, rva, min_size_of, align),
232 }
233 }
234 }
235
236 fn slice_bytes(self, rva: Rva) -> Result<&'a [u8]> where Self: Sized {
240 self.slice(rva, 0, 1)
241 }
242
243 fn get_section_bytes(self, section_header: &IMAGE_SECTION_HEADER) -> Result<&'a [u8]> {
253 crate::wrap::get_section_bytes(self.image(), section_header, self.align())
254 }
255
256 fn read(&self, va: Va, min_size_of: usize, align: usize) -> Result<&'a [u8]> {
269 unsafe {
270 match (self.align(), self.image()) {
271 (Align::File, image) => read_file(image, va, min_size_of, align),
272 (Align::Section, image) => read_section(image, va, min_size_of, align),
273 }
274 }
275 }
276
277 fn read_bytes(self, va: Va) -> Result<&'a [u8]> where Self: Sized {
281 self.read(va, 0, 1)
282 }
283
284 fn derva<T>(self, rva: Rva) -> Result<&'a T> where T: Pod {
288 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
289 let bytes = self.slice(rva, mem::size_of::<T>(), align)?;
290 unsafe {
292 let p = &*(bytes.as_ptr() as *const T);
293 Ok(p)
294 }
295 }
296 fn derva_copy<T>(self, rva: Rva) -> Result<T> where T: Copy + Pod {
298 let bytes = self.slice(rva, mem::size_of::<T>(), 1)?;
299 unsafe {
301 let p = bytes.as_ptr() as *const T;
302 Ok(ptr::read_unaligned(p))
303 }
304 }
305 fn derva_into<T>(self, rva: Rva, dest: &mut T) -> Result<()> where T: ?Sized + Pod {
309 let len = mem::size_of_val(dest);
310 let bytes = self.slice(rva, len, 1)?;
311 dataview::bytes_mut(dest).copy_from_slice(&bytes[..len]);
312 Ok(())
313 }
314 fn derva_slice<T>(self, rva: Rva, len: usize) -> Result<&'a [T]> where T: Pod {
316 let min_size_of = mem::size_of::<T>().checked_mul(len).ok_or(Error::Overflow)?;
317 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
318 let bytes = self.slice(rva, min_size_of, align)?;
319 unsafe {
321 Ok(slice::from_raw_parts(bytes.as_ptr() as *const T, len))
322 }
323 }
324 fn derva_slice_f<T, F>(self, rva: Rva, mut f: F) -> Result<&'a [T]> where T: Pod, F: FnMut(&'a T) -> bool {
331 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
332 let bytes = self.slice(rva, 0, align)?;
333 let mut len = 0;
334 loop {
335 let offset = len * mem::size_of::<T>();
338 if offset + mem::size_of::<T>() > bytes.len() {
339 return Err(Error::Bounds);
340 }
341 unsafe {
343 let s = bytes.as_ptr().offset(offset as isize) as *const T;
344 if f(&*s) {
345 let p = slice::from_raw_parts(bytes.as_ptr() as *const T, len);
346 return Ok(p);
347 }
348 len += 1;
349 }
350 }
351 }
352 fn derva_slice_s<T>(self, rva: Rva, sentinel: T) -> Result<&'a [T]> where T: PartialEq + Pod {
358 self.derva_slice_f(rva, |tee| *tee == sentinel)
359 }
360 fn derva_c_str(self, rva: Rva) -> Result<&'a CStr> {
362 self.derva_string(rva)
363 }
364 fn derva_string<T>(self, rva: Rva) -> Result<&'a T> where T: FromBytes + ?Sized {
366 let bytes = self.slice(rva, T::MIN_SIZE_OF, T::ALIGN_OF)?;
367 unsafe { T::from_bytes(bytes).ok_or(Error::Encoding) }
368 }
369
370 fn deref<T>(self, ptr: Ptr<T>) -> Result<&'a T> where T: Pod {
375 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
376 let bytes = self.read(ptr.into(), mem::size_of::<T>(), align)?;
377 unsafe {
379 let p = &*(bytes.as_ptr() as *const T);
380 Ok(p)
381 }
382 }
383 fn deref_copy<T>(self, ptr: Ptr<T>) -> Result<T> where T: Copy + Pod {
385 let bytes = self.read(ptr.into(), mem::size_of::<T>(), 1)?;
386 unsafe {
388 let p = bytes.as_ptr() as *const T;
389 Ok(ptr::read_unaligned(p))
390 }
391 }
392 fn deref_into<T>(self, ptr: Ptr<T>, dest: &mut T) -> Result<()> where T: ?Sized + Pod {
396 let len = mem::size_of_val(dest);
397 let bytes = self.read(ptr.into(), len, 1)?;
398 dataview::bytes_mut(dest).copy_from_slice(&bytes[..len]);
399 Ok(())
400 }
401 fn deref_slice<T>(self, ptr: Ptr<[T]>, len: usize) -> Result<&'a [T]> where T: Pod {
403 let min_size_of = mem::size_of::<T>().checked_mul(len).ok_or(Error::Overflow)?;
404 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
405 let bytes = self.read(ptr.into(), min_size_of, align)?;
406 unsafe {
408 Ok(slice::from_raw_parts(bytes.as_ptr() as *const T, len))
409 }
410 }
411 fn deref_slice_f<T, F>(self, ptr: Ptr<[T]>, mut f: F) -> Result<&'a [T]> where T: Pod, F: FnMut(&'a T) -> bool {
418 let align = if cfg!(feature = "unsafe_alignment") { 1 } else { mem::align_of::<T>() };
419 let bytes = self.read(ptr.into(), 0, align)?;
420 let mut len = 0;
421 loop {
422 let offset = len * mem::size_of::<T>();
425 if offset + mem::size_of::<T>() > bytes.len() {
426 return Err(Error::Bounds);
427 }
428 unsafe {
430 let s = bytes.as_ptr().offset(offset as isize) as *const T;
431 if f(&*s) {
432 let p = slice::from_raw_parts(bytes.as_ptr() as *const T, len);
433 return Ok(p);
434 }
435 len += 1;
436 }
437 }
438 }
439 fn deref_slice_s<T>(self, ptr: Ptr<[T]>, sentinel: T) -> Result<&'a [T]> where T: PartialEq + Pod {
445 self.deref_slice_f(ptr, |tee| *tee == sentinel)
446 }
447 fn deref_c_str(self, ptr: Ptr<CStr>) -> Result<&'a CStr> {
449 self.deref_string(ptr)
450 }
451 fn deref_string<T>(self, ptr: Ptr<T>) -> Result<&'a T> where T: FromBytes + ?Sized {
453 let bytes = self.read(ptr.into(), T::MIN_SIZE_OF, T::ALIGN_OF)?;
454 unsafe { T::from_bytes(bytes).ok_or(Error::Encoding) }
455 }
456
457 fn rich_structure(self) -> Result<crate::rich_structure::RichStructure<'a>> {
461 let image = self.image();
462 let image = unsafe { slice::from_raw_parts(image.as_ptr() as *const u32, image.len() / 4) };
463 crate::rich_structure::RichStructure::try_from(image)
464 }
465
466 fn exports(self) -> Result<super::exports::Exports<'a, Self>> {
472 super::exports::Exports::try_from(self)
473 }
474
475 fn imports(self) -> Result<super::imports::Imports<'a, Self>> {
481 super::imports::Imports::try_from(self)
482 }
483
484 fn iat(self) -> Result<super::imports::IAT<'a, Self>> {
490 super::imports::IAT::try_from(self)
491 }
492
493 fn base_relocs(self) -> Result<crate::base_relocs::BaseRelocs<'a>> {
499 super::base_relocs::try_from(self)
500 }
501
502 fn load_config(self) -> Result<super::load_config::LoadConfig<'a, Self>> {
508 super::load_config::LoadConfig::try_from(self)
509 }
510
511 fn tls(self) -> Result<super::tls::Tls<'a, Self>> {
517 super::tls::Tls::try_from(self)
518 }
519
520 fn security(self) -> Result<crate::security::Security<'a>> {
526 super::security::try_from(self)
527 }
528
529 fn exception(self) -> Result<super::exception::Exception<'a, Self>> {
535 super::exception::Exception::try_from(self)
536 }
537
538 fn debug(self) -> Result<super::debug::Debug<'a, Self>> {
544 super::debug::Debug::try_from(self)
545 }
546
547 #[cfg(any(feature = "std", feature = "resources_nostd"))]
553 fn resources(self) -> Result<crate::resources::Resources<'a>> where Self: Copy {
554 let datadir = self.data_directory().get(IMAGE_DIRECTORY_ENTRY_RESOURCE).ok_or(Error::Bounds)?;
555 let bytes = self.slice_bytes(datadir.VirtualAddress)?;
556 let size = cmp::min(datadir.Size as usize, bytes.len());
557 Ok(crate::resources::Resources::new(&bytes[..size], datadir))
558 }
559
560 fn scanner(self) -> super::scanner::Scanner<Self> {
564 super::scanner::Scanner::new(self)
565 }
566}
567
568unsafe impl<'s, 'a> PeObject<'a> for &'s dyn PeObject<'a> {
572 fn image(&self) -> &'a [u8] {
573 PeObject::image(*self)
574 }
575 fn align(&self) -> Align {
576 PeObject::align(*self)
577 }
578 #[cfg(feature = "serde")]
579 fn serde_name(&self) -> &'static str {
580 PeObject::serde_name(*self)
581 }
582}
583
584unsafe impl<'s, 'a> Pe<'a> for &'s dyn PeObject<'a> {}
585
586#[cfg(feature = "serde")]
589pub(crate) fn serialize_pe<'a, P: Pe<'a>, S: serde::Serializer>(pe: P, serializer: S) -> std::result::Result<S::Ok, S::Error> {
590 use crate::util::serde_helper::*;
591
592 let mut state = serializer.serialize_struct(pe.serde_name(), 10)?;
593 state.serialize_field("headers", &pe.headers())?;
594 state.serialize_field("rich_structure", &pe.rich_structure().ok())?;
595 state.serialize_field("exports", &pe.exports().ok())?;
596 state.serialize_field("imports", &pe.imports().ok())?;
597 state.serialize_field("base_relocs", &pe.base_relocs().ok())?;
598 state.serialize_field("debug", &pe.debug().ok())?;
599 state.serialize_field("tls", &pe.tls().ok())?;
600 state.serialize_field("load_config", &pe.load_config().ok())?;
601 state.serialize_field("security", &pe.security().ok())?;
602 state.serialize_field("resources", &pe.resources().ok())?;
603 state.end()
604}
605
606unsafe fn dos_header(image: &[u8]) -> &IMAGE_DOS_HEADER {
610 &*(image.as_ptr() as *const IMAGE_DOS_HEADER)
611}
612unsafe fn dos_image(image: &[u8]) -> &[u8] {
613 image.get_unchecked(..dos_header(image).e_lfanew as usize)
614}
615unsafe fn nt_headers(image: &[u8]) -> &IMAGE_NT_HEADERS {
616 &*(image.as_ptr().offset(dos_header(image).e_lfanew as isize) as *const IMAGE_NT_HEADERS)
617}
618unsafe fn file_header(image: &[u8]) -> &IMAGE_FILE_HEADER {
619 &nt_headers(image).FileHeader
620}
621unsafe fn optional_header(image: &[u8]) -> &IMAGE_OPTIONAL_HEADER {
622 &nt_headers(image).OptionalHeader
623}
624unsafe fn data_directory(image: &[u8]) -> &[IMAGE_DATA_DIRECTORY] {
625 let opt = optional_header(image);
626 let len = cmp::min(opt.NumberOfRvaAndSizes as usize, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
627 slice::from_raw_parts(opt.DataDirectory.as_ptr(), len)
628}
629unsafe fn section_headers(image: &[u8]) -> &super::headers::SectionHeaders {
630 let nt = nt_headers(image);
631 let data = (&nt.OptionalHeader as *const _ as *const u8).offset(nt.FileHeader.SizeOfOptionalHeader as isize) as *const IMAGE_SECTION_HEADER;
632 let raw = slice::from_raw_parts(data, nt.FileHeader.NumberOfSections as usize);
633 super::headers::SectionHeaders::new(raw)
634}
635
636unsafe fn slice_section(image: &[u8], rva: Rva, min_size_of: usize, align_of: usize) -> Result<&[u8]> {
637 let start = rva as usize;
638 if rva == 0 {
639 Err(Error::Null)
640 }
641 else if !usize::wrapping_add(image.as_ptr() as usize, start).aligned_to(align_of) {
642 Err(Error::Misaligned)
643 }
644 else {
645 match image.get(start..) {
646 Some(bytes) if bytes.len() >= min_size_of => Ok(bytes),
647 _ => Err(Error::Bounds),
648 }
649 }
650}
651unsafe fn read_section(image: &[u8], va: Va, min_size_of: usize, align_of: usize) -> Result<&[u8]> {
652 let (image_base, image_size) = {
653 let optional_header = optional_header(image);
654 (optional_header.ImageBase, optional_header.SizeOfImage)
655 };
656 if va == 0 {
657 Err(Error::Null)
658 }
659 else if va < image_base || va - image_base > image_size as Va {
660 Err(Error::Bounds)
661 }
662 else {
663 let start = (va - image_base) as usize;
664 if !usize::wrapping_add(image.as_ptr() as usize, start).aligned_to(align_of) {
665 Err(Error::Misaligned)
666 }
667 else {
668 match image.get(start..) {
669 Some(bytes) if bytes.len() >= min_size_of => Ok(bytes),
670 _ => Err(Error::Bounds),
671 }
672 }
673 }
674}
675
676unsafe fn range_file(image: &[u8], rva: Rva, min_size_of: usize) -> Result<&[u8]> {
677 for it in section_headers(image) {
679 #[allow(non_snake_case)]
682 let VirtualEnd = it.VirtualAddress.wrapping_add(cmp::max(it.VirtualSize, it.SizeOfRawData));
683 if it.VirtualAddress <= rva && rva < VirtualEnd { let section_range = it.PointerToRawData as usize..it.PointerToRawData.wrapping_add(it.SizeOfRawData) as usize;
687 let section_bytes = image.get(section_range).ok_or(Error::Invalid)?;
688 let section_offset = (rva - it.VirtualAddress) as usize;
690 return match section_bytes.get(section_offset..) {
691 Some(bytes) if bytes.len() >= min_size_of => Ok(bytes),
692 _ => Err(if min_size_of > (VirtualEnd - rva) as usize { Error::Bounds } else { Error::ZeroFill }),
694 };
695 }
696 }
697 Err(Error::Bounds)
698}
699#[inline(never)]
700unsafe fn slice_file(image: &[u8], rva: Rva, min_size_of: usize, align_of: usize) -> Result<&[u8]> {
701 if rva == 0 {
702 Err(Error::Null)
703 }
704 else if !usize::wrapping_add(image.as_ptr() as usize, rva as usize).aligned_to(align_of) {
705 Err(Error::Misaligned)
706 }
707 else {
708 range_file(image, rva, min_size_of)
709 }
710}
711#[inline(never)]
712unsafe fn read_file(image: &[u8], va: Va, min_size_of: usize, align_of: usize) -> Result<&[u8]> {
713 let (image_base, size_of_image) = {
714 let optional_header = optional_header(image);
715 (optional_header.ImageBase, optional_header.SizeOfImage)
716 };
717 if va == 0 {
718 Err(Error::Null)
719 }
720 else if va < image_base || va - image_base > size_of_image as Va {
721 Err(Error::Bounds)
722 }
723 else {
724 let rva = (va - image_base) as Rva;
725 if !usize::wrapping_add(image.as_ptr() as usize, rva as usize).aligned_to(align_of) {
726 Err(Error::Misaligned)
727 }
728 else {
729 range_file(image, rva, min_size_of)
730 }
731 }
732}
733
734pub(crate) fn validate_headers(image: &[u8]) -> Result<u32> {
739 if mem::size_of::<IMAGE_DOS_HEADER>() > image.len() {
741 return Err(Error::Bounds);
742 }
743 if !image.as_ptr().aligned_to(4) {
745 return Err(Error::Misaligned);
746 }
747 let dos = unsafe { &*(image.as_ptr() as *const IMAGE_DOS_HEADER) };
748 if dos.e_magic != IMAGE_DOS_SIGNATURE {
750 return Err(Error::BadMagic);
751 }
752 if !dos.e_lfanew.aligned_to(4) {
754 return Err(Error::Misaligned);
755 }
756 if dos.e_lfanew > 0x01000000 {
759 return Err(Error::Insanity);
760 }
761
762 let nt_end = dos.e_lfanew as usize + mem::size_of::<IMAGE_NT_HEADERS>();
764 if nt_end > image.len() {
765 return Err(Error::Bounds);
766 }
767 let nt = unsafe { &*(image.as_ptr().offset(dos.e_lfanew as isize) as *const IMAGE_NT_HEADERS) };
768 if nt.Signature != IMAGE_NT_HEADERS_SIGNATURE ||
770 !(nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC || nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
771 {
772 return Err(Error::BadMagic);
773 }
774 if nt.OptionalHeader.SizeOfHeaders as usize > image.len() {
775 return Err(Error::Bounds);
776 }
777 if nt.OptionalHeader.SizeOfHeaders > nt.OptionalHeader.SizeOfImage {
778 return Err(Error::Insanity);
779 }
780 if nt.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC {
782 return Err(Error::PeMagic);
783 }
784
785 let num_rva_sizes = cmp::min(
787 nt.OptionalHeader.NumberOfRvaAndSizes as usize,
788 IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
789 let size_of_data_dir = num_rva_sizes * mem::size_of::<IMAGE_DATA_DIRECTORY>();
790 if nt_end + size_of_data_dir > image.len() {
791 return Err(Error::Bounds);
792 }
793
794 if nt.FileHeader.NumberOfSections > 96 {
796 return Err(Error::Insanity);
797 }
798 let size_of_sections = nt.FileHeader.NumberOfSections as usize * mem::size_of::<IMAGE_SECTION_HEADER>();
800 let start_of_sections = dos.e_lfanew as usize
802 + (mem::size_of::<IMAGE_NT_HEADERS>() - mem::size_of::<IMAGE_OPTIONAL_HEADER>())
803 + nt.FileHeader.SizeOfOptionalHeader as usize;
804 if size_of_sections + start_of_sections > image.len() {
806 return Err(Error::Bounds);
807 }
808 Ok(nt.OptionalHeader.SizeOfImage)
809}
810
811#[cfg(feature = "unstable")]
817pub unsafe fn headers_mut(image: &mut [u8]) -> (&mut IMAGE_DOS_HEADER, &mut IMAGE_NT_HEADERS, &mut [IMAGE_DATA_DIRECTORY], &mut [IMAGE_SECTION_HEADER]) {
818 let dos = &mut *(image.as_mut_ptr() as *mut IMAGE_DOS_HEADER);
819 let nt = &mut *(image.as_mut_ptr().offset(dos.e_lfanew as isize) as *mut IMAGE_NT_HEADERS);
820 let dd_ptr = nt.OptionalHeader.DataDirectory.as_mut_ptr();
821 let dd_len = cmp::min(nt.OptionalHeader.NumberOfRvaAndSizes as usize, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
822 let dd = slice::from_raw_parts_mut(dd_ptr, dd_len);
823 let sections_ptr = (&mut nt.OptionalHeader as *mut _ as *mut u8).offset(nt.FileHeader.SizeOfOptionalHeader as isize) as *mut IMAGE_SECTION_HEADER;
824 let sections_len = nt.FileHeader.NumberOfSections as usize;
825 let sections = slice::from_raw_parts_mut(sections_ptr, sections_len);
826 (dos, nt, dd, sections)
827}