Skip to main content

memflow_coredump/native/
x64.rs

1use 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/// A 64bit Microsoft Windows Coredump Header
18#[repr(C)]
19#[derive(Copy, Clone, ByteSwap)]
20pub struct CoreDumpHeader64 {
21    pub signature: u32,                                       // 0x0000
22    pub valid_dump: u32,                                      // 0x0004
23    pub major_version: u32,                                   // 0x0008
24    pub minor_version: u32,                                   // 0x000c
25    pub directory_table_base: u64,                            // 0x0010
26    pub pfn_data_base: u64,                                   // 0x0018
27    pub ps_loaded_module_list: u64,                           // 0x0020
28    pub ps_active_process_head: u64,                          // 0x0028
29    pub machine_image_type: u32,                              // 0x0030
30    pub number_processors: u32,                               // 0x0034
31    pub bug_check_code: u32,                                  // 0x0038
32    pub bug_check_parameter1: u64,                            // 0x0040
33    pub bug_check_parameter2: u64,                            // 0x0048
34    pub bug_check_parameter3: u64,                            // 0x0050
35    pub bug_check_parameter4: u64,                            // 0x0058
36    pub version_user: [u8; 32],                               // 0x0060
37    pub kd_debugger_data_block: u64,                          // 0x0080
38    pub physical_memory_block: PhysicalMemoryDescriptor<u64>, // 0x0088
39    pub pad0: [u8; 176],                                      // 0x0344
40    pub context_record: [u8; 3000],                           // 0x0348
41    pub exception_record: [u8; 152],                          // EXCEPTION_RECORD64 - 0x0F00
42    pub dump_type: u32,                                       // 0x0F98
43    pub required_dump_space: u64,                             // 0x0FA0
44    pub system_time: u64,                                     // 0x0FA8
45    pub comment: [i8; 0x80],                                  // 0x0FB0 May not be present.
46    pub system_up_time: u64,                                  // 0x1030
47    pub mini_dump_fields: u32,                                // 0x1038
48    pub secondary_data_state: u32,                            // 0x103c
49    pub product_type: u32,                                    // 0x1040
50    pub suite_mask: u32,                                      // 0x1044
51    pub writer_status: u32,                                   // 0x1048
52    pub unused0: u8,                                          // 0x104c
53    pub kd_secondary_version: u8,                             // 0x104d only on W2K3 SP1 and up
54    pub unused1: [u8; 2],                                     // 0x104e
55    pub reserved0: [u8; 4016],                                // 0x1050
56}
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
68/// Tries to parse a file handle as a Microsoft Windows 64bit Coredump.
69pub 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}