memflow_coredump/native/
x64.rs1use super::full_memory_dump::*;
2use super::*;
3
4use std::fs::File;
5use std::io::{Read, Seek, SeekFrom};
6use std::mem::size_of;
7use std::mem::MaybeUninit;
8
9use dataview::Pod;
10use log::info;
11use memflow::*;
12use memflow_derive::*;
13
14pub const DUMP_VALID_DUMP64: u32 = 0x34365544;
15pub const IMAGE_FILE_MACHINE_AMD64: u32 = 0x8664;
16
17#[repr(C)]
19#[derive(Copy, Clone, ByteSwap)]
20pub struct CoreDumpHeader64 {
21 pub signature: u32, pub valid_dump: u32, pub major_version: u32, pub minor_version: u32, pub directory_table_base: u64, pub pfn_data_base: u64, pub ps_loaded_module_list: u64, pub ps_active_process_head: u64, pub machine_image_type: u32, pub number_processors: u32, pub bug_check_code: u32, pub bug_check_parameter1: u64, pub bug_check_parameter2: u64, pub bug_check_parameter3: u64, pub bug_check_parameter4: u64, pub version_user: [u8; 32], pub kd_debugger_data_block: u64, pub physical_memory_block: PhysicalMemoryDescriptor<u64>, pub pad0: [u8; 176], pub context_record: [u8; 3000], pub exception_record: [u8; 152], pub dump_type: u32, pub required_dump_space: u64, pub system_time: u64, pub comment: [i8; 0x80], pub system_up_time: u64, pub mini_dump_fields: u32, pub secondary_data_state: u32, pub product_type: u32, pub suite_mask: u32, pub writer_status: u32, pub unused0: u8, pub kd_secondary_version: u8, pub unused1: [u8; 2], pub reserved0: [u8; 4016], }
57const _: [(); std::mem::size_of::<CoreDumpHeader64>()] = [(); 0x2000];
58
59#[allow(clippy::uninit_assumed_init)]
60impl CoreDumpHeader64 {
61 pub fn uninit() -> Self {
62 unsafe { MaybeUninit::uninit().assume_init() }
63 }
64}
65
66unsafe impl Pod for CoreDumpHeader64 {}
67
68pub fn parse_coredump64(file: &mut File) -> Result<MemoryMap<(Address, usize)>> {
70 let mut header = CoreDumpHeader64::uninit();
71
72 file.seek(SeekFrom::Start(0))
73 .map_err(|_| Error::Connector("unable to seek to coredump 64 header"))?;
74
75 file.read_exact(header.as_bytes_mut())
76 .map_err(|_| Error::Connector("unable to read coredump 64 header"))?;
77
78 if cfg!(target_endian = "big") {
79 header.byte_swap();
80 }
81
82 if header.signature != DUMP_SIGNATURE {
83 return Err(Error::Connector("header signature is not valid"));
84 }
85
86 if header.valid_dump != DUMP_VALID_DUMP64 {
87 return Err(Error::Connector("header dump flag is not valid"));
88 }
89
90 if header.machine_image_type != IMAGE_FILE_MACHINE_AMD64 {
91 return Err(Error::Connector("invalid machine image type"));
92 }
93
94 info!("64-bit Microsoft Crash Dump verified");
95
96 match header.dump_type {
97 dump_type::FULL => full_memory_dump::parse_full_dump(
98 header.physical_memory_block,
99 size_of::<CoreDumpHeader64>(),
100 ),
101 dump_type::BIT_MAP => bitmap_dump::parse_bitmap_dump(file),
102 _ => Err(Error::Connector(
103 "invalid dump type, only full and bitmap dumps are supported",
104 )),
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use std::mem::size_of;
112
113 #[test]
114 fn test_struct_sizes_x64() {
115 assert_eq!(size_of::<PhysicalMemoryRun<u64>>(), 0x10);
116 assert_eq!(size_of::<PhysicalMemoryDescriptor<u64>>(), 0x210);
117 assert_eq!(size_of::<CoreDumpHeader64>(), 0x2000);
118 }
119
120 #[test]
121 fn test_struct_members_x64() {
122 let header = CoreDumpHeader64::uninit();
123 assert_eq!(
124 &header.version_user as *const _ as usize - &header as *const _ as usize,
125 0x60
126 );
127 assert_eq!(
128 &header.kd_debugger_data_block as *const _ as usize - &header as *const _ as usize,
129 0x80
130 );
131 assert_eq!(
132 &header.physical_memory_block as *const _ as usize - &header as *const _ as usize,
133 0x88
134 );
135 assert_eq!(
136 &header.context_record as *const _ as usize - &header as *const _ as usize,
137 0x348
138 );
139 assert_eq!(
140 &header.exception_record as *const _ as usize - &header as *const _ as usize,
141 0xf00
142 );
143 assert_eq!(
144 &header.dump_type as *const _ as usize - &header as *const _ as usize,
145 0xf98
146 );
147 }
148}