memflow-win32 0.2.0

win32 integration of the memflow physical memory introspection framework
Documentation
use std::prelude::v1::*;

use log::{info, trace};
use std::fmt;

use memflow::mem::{MemoryMap, MemoryView};
use memflow::types::{mem, umem, Address};

use memflow::dataview::Pod;

#[allow(clippy::unnecessary_cast)]
const SIZE_4KB: u64 = mem::kb(4) as u64;

/// The number of PhysicalMemoryRuns contained in the Header
pub const PHYSICAL_MEMORY_MAX_RUNS: usize = 32;

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct PhysicalMemoryRun<T: Pod + fmt::Debug> {
    pub base_page: T,
    pub page_count: T,
}
unsafe impl<T: Pod + fmt::Debug> Pod for PhysicalMemoryRun<T> {}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct PhysicalMemoryDescriptor<T: Pod + fmt::Debug> {
    pub number_of_runs: T,
    pub number_of_pages: T,
    pub runs: [PhysicalMemoryRun<T>; PHYSICAL_MEMORY_MAX_RUNS],
}
unsafe impl<T: Pod + fmt::Debug> Pod for PhysicalMemoryDescriptor<T> {}
const _: [(); std::mem::size_of::<PhysicalMemoryDescriptor<u32>>()] = [(); 0x108];
const _: [(); std::mem::size_of::<PhysicalMemoryDescriptor<u64>>()] = [(); 0x210];

pub fn parse<T: MemoryView, U: Pod + Copy + fmt::Debug + fmt::LowerHex + Into<u64>>(
    virt_mem: &mut T,
    descriptor_ptr_ptr: Address,
) -> Option<MemoryMap<(Address, umem)>> {
    let descriptor_ptr = virt_mem.read_addr64(descriptor_ptr_ptr).ok()?;

    trace!("found phys_mem_block pointer at: {}", descriptor_ptr);
    let descriptor: PhysicalMemoryDescriptor<U> = virt_mem.read(descriptor_ptr).ok()?;

    trace!("found phys_mem_block: {:?}", descriptor);
    if descriptor.number_of_runs.into() <= PHYSICAL_MEMORY_MAX_RUNS as u64 {
        let mut mem_map = MemoryMap::new();

        for i in 0..descriptor.number_of_runs.into() {
            let base = descriptor.runs[i as usize].base_page.into() * SIZE_4KB;
            let size = descriptor.runs[i as usize].page_count.into() * SIZE_4KB;

            trace!("adding memory mapping: base={:x} size={:x}", base, size);
            mem_map.push_remap(base.into(), size as umem, Address::from(base));
        }

        Some(mem_map)
    } else {
        info!(
            "too many memory segments in phys_mem_block: {} found, {} expected",
            descriptor.number_of_runs.into(),
            PHYSICAL_MEMORY_MAX_RUNS
        );
        None
    }
}