Struct memprocfs::VmmProcess

source ·
pub struct VmmProcess<'a> {
    pub pid: u32,
    /* private fields */
}
Expand description

Process API Base Struct.

The VmmProcess struct is the base of the per-process related functionality of the MemProcFS API. The VmmProcess struct should be considered a child to the main Vmm struct.

Check out the example project for more detailed API usage and additional examples!

§Created By

§Examples

// Retrieve all processes:
if let Ok(process_all) = vmm.process_list() {
    for process in &*process_all {
        print!("{process} ");
    }
}
// Retrieve a process by its name. If more than one process share the
// same name the first found will be returned.
let systemprocess = vmm.process_from_name("System")?;
println!("{systemprocess}");
// Retrieve a process by its PID.
let systemprocess = vmm.process_from_pid(4)?;
println!("{systemprocess}");
// Process kernel memory and session space:
// Mask the process PID with 0x80000000 to retrieve kernel memory.
// This may be useful for retrieving kernel session data related to win32k.
let mut winlogon = vmm.process_from_name("winlogon.exe")?;
winlogon.pid = winlogon.pid | 0x80000000;
let va = winlogon.get_proc_address("win32kbase.sys", "gSessionId")?;
let sessionid : u32 = winlogon.mem_read_as(va, 0)?;
println!("win32kbase.sys!gSessionId -> {:x} : {}", va, sessionid);

Fields§

§pid: u32

Implementations§

source§

impl VmmProcess<'_>

source

pub fn get_module_base(&self, module_name: &str) -> ResultEx<u64>

Get the base virtual address for a loaded module.

§Arguments
  • module_name
§Examples
if let Ok(module_base_kernel32) = vmmprocess.get_module_base("kernel32.dll") {
    println!("kernel32.dll -> {:x}", module_base_kernel32);
}
source

pub fn get_proc_address( &self, module_name: &str, function_name: &str ) -> ResultEx<u64>

Get the address of an exported function or symbol.

This is similar to the Windows function GetProcAddress.

§Arguments
  • module_name
  • function_name
§Examples
if let Ok(procaddress) = vmmprocess.get_proc_address("kernel32.dll", "GetProcAddress") {
    println!("kernel32.dll!GetProcAddress -> {:x}", procaddress);
}
source

pub fn get_path_kernel(&self) -> ResultEx<String>

Get the process path (retrieved fom kernel mode).

§Examples
if let Ok(path) = vmmprocess.get_path_kernel() {
    println!("-> {path}");
}
source

pub fn get_path_user(&self) -> ResultEx<String>

Get the process path (retrieved from user-mode).

§Examples
if let Ok(path) = vmmprocess.get_path_user() {
    println!("-> {path}");
}
source

pub fn get_cmdline(&self) -> ResultEx<String>

Get the process command line.

§Examples
if let Ok(s_cmdline) = vmmprocess.get_cmdline() {
    println!("-> {s_cmdline}");
}
source

pub fn info(&self) -> ResultEx<VmmProcessInfo>

Get process information - such as name, ppid, state, etc.

If retrieving multiple values from the VmmProcessInfo struct it’s recommended to retrieve the info object once instead of repetedly calling the info() method.

§Examples
if let Ok(procinfo) = vmmprocess.info() {
    println!("struct   -> {procinfo}");
    println!("pid      -> {}", procinfo.pid);
    println!("ppid     -> {}", procinfo.pid);
    println!("peb      -> {:x}", procinfo.va_peb);
    println!("eprocess -> {:x}", procinfo.va_eprocess);
    println!("name     -> {}", procinfo.name);
    println!("longname -> {}", procinfo.name_long);
    println!("SID      -> {}", procinfo.sid);
}
source

pub fn map_handle(&self) -> ResultEx<Vec<VmmProcessMapHandleEntry>>

Retrieve the handles info map.

For additional information see the VmmProcessMapHandleEntry struct.

§Examples
if let Ok(handle_all) = vmmprocess.map_handle() {
    println!("Number of handle entries: {}.", handle_all.len());
    for handle in &*handle_all {
        println!("{handle}");
    }
}
source

pub fn map_heap(&self) -> ResultEx<Vec<VmmProcessMapHeapEntry>>

Retrieve the heaps info map.

For additional information see the VmmProcessMapHeapEntry struct.

§Examples
if let Ok(heap_all) = vmmprocess.map_heap() {
    println!("Number of heap entries: {}.", heap_all.len());
    for heap in &*heap_all {
        println!("{heap}");
    }
}
source

pub fn map_heapalloc( &self, heap_number_or_address: u64 ) -> ResultEx<Vec<VmmProcessMapHeapAllocEntry>>

Retrieve the heap allocations info map.

For additional information see the VmmProcessMapHeapAllocEntry struct.

§Arguments
§Examples
if let Ok(heapalloc_all) = vmmprocess.map_heapalloc(0) {
    println!("Number of allocated heap entries: {}.", heapalloc_all.len());
    for heapalloc in &*heapalloc_all {
        print!("{heapalloc} ");
    }
    println!("");
}
source

pub fn map_module( &self, is_info_debug: bool, is_info_version: bool ) -> ResultEx<Vec<VmmProcessMapModuleEntry>>

Retrieve the loaded modules map.

For additional information see the VmmProcessMapModuleEntry struct.

§Arguments
  • is_info_debug - Also retrieve debug information.
  • is_info_version - Also version information.
§Examples
if let Ok(module_all) = vmmprocess.map_module(true, true) {
    println!("Number of process modules: {}.", module_all.len());
    for module in &*module_all {
        println!("{module}");
    }
}
source

pub fn map_module_data_directory( &self, module_name: &str ) -> ResultEx<Vec<VmmProcessMapDirectoryEntry>>

Retrieve PE data directories associated with a module.

For additional information see the VmmProcessMapDirectoryEntry struct.

§Arguments
  • module_name
§Examples
if let Ok(data_directory_all) = vmmprocess.map_module_data_directory("kernel32.dll") {
    println!("Number of module data directories: {}.", data_directory_all.len());
    for data_directory in &*data_directory_all {
        println!("{data_directory}");
    }
}
source

pub fn map_module_eat( &self, module_name: &str ) -> ResultEx<Vec<VmmProcessMapEatEntry>>

Retrieve exported functions and symbols associated with a module.

For additional information see the VmmProcessMapEatEntry struct.

§Arguments
  • module_name
§Examples
if let Ok(eat_all) = vmmprocess.map_module_eat("kernel32.dll") {
    println!("Number of module exported functions: {}.", eat_all.len());
    for eat in &*eat_all {
        println!("{eat} :: {}", eat.forwarded_function);
    }
}
source

pub fn map_module_iat( &self, module_name: &str ) -> ResultEx<Vec<VmmProcessMapIatEntry>>

Retrieve imported functions associated with a module.

For additional information see the VmmProcessMapIatEntry struct.

§Arguments
  • module_name
§Examples
if let Ok(iat_all) = vmmprocess.map_module_iat("kernel32.dll") {
    println!("Number of module imported functions: {}.", iat_all.len());
    for iat in &*iat_all {
        println!("{iat}");
    }
}
source

pub fn map_module_section( &self, module_name: &str ) -> ResultEx<Vec<VmmProcessSectionEntry>>

Retrieve PE sections associated with a module.

For additional information see the VmmProcessSectionEntry struct.

§Arguments
  • module_name
§Examples
if let Ok(section_all) = vmmprocess.map_module_section("kernel32.dll") {
    println!("Number of module sections: {}.", section_all.len());
    for section in &*section_all {
        println!("{section}");
    }
}
source

pub fn map_pte( &self, is_identify_modules: bool ) -> ResultEx<Vec<VmmProcessMapPteEntry>>

Retrieve the PTE memory info map.

For additional information see the VmmProcessMapPteEntry struct.

§Examples
if let Ok(pte_all) = vmmprocess.map_pte(true) {
    println!("Number of pte entries: {}.", pte_all.len());
    for pte in &*pte_all {
        let s = if pte.is_s { 's' } else { '-' };
        let r = if pte.is_r { 'r' } else { '-' };
        let w = if pte.is_w { 'w' } else { '-' };
        let x = if pte.is_x { 'x' } else { '-' };
        println!("{pte} :: {s}{r}{w}{x} :: {}", pte.info);
    }
}
source

pub fn map_thread(&self) -> ResultEx<Vec<VmmProcessMapThreadEntry>>

Retrieve the thread info map.

For additional information see the VmmProcessMapThreadEntry struct.

§Examples
if let Ok(thread_all) = vmmprocess.map_thread() {
    println!("Number of process threads: {}.", thread_all.len());
    for thread in &*thread_all {
        println!("{thread}");
    }
}
source

pub fn map_unloaded_module( &self ) -> ResultEx<Vec<VmmProcessMapUnloadedModuleEntry>>

Retrieve the unloaded module info map.

For additional information see the VmmProcessMapUnloadedModuleEntry struct.

§Examples
if let Ok(unloaded_all) = vmmprocess.map_unloaded_module() {
    println!("Number of process unloaded modules: {}.", unloaded_all.len());
    for unloaded in &*unloaded_all {
        println!("{unloaded}");
    }
}
source

pub fn map_vad( &self, is_identify_modules: bool ) -> ResultEx<Vec<VmmProcessMapVadEntry>>

Retrieve the VAD (virtual address descriptor) memory info map.

For additional information see the VmmProcessMapVadEntry struct.

§Examples
if let Ok(vad_all) = vmmprocess.map_vad(true) {
    println!("Number of vad entries: {}.", vad_all.len());
    for vad in &*vad_all {
        println!("{vad} :: {}", vad.info);
    }
}
source

pub fn map_vadex( &self, offset_pages: u32, count_pages: u32 ) -> ResultEx<Vec<VmmProcessMapVadExEntry>>

Retrieve the extended VAD info map.

For additional information see the VmmProcessMapVadExEntry struct.

source

pub fn mem_read(&self, va: u64, size: usize) -> ResultEx<Vec<u8>>

Read a contigious virtual memory chunk.

The virtual memory is read without any special flags. The whole chunk must be read successfully for the method to succeed.

If deseriable to provide flags modifying the behavior (such as skipping the built-in data cache or slower paging access) use the method mem_read_ex() instead.

Reading many memory chunks individually may be slow, especially if reading takes place using hardware FPGA devices. In that case it’s better to use the mem_scatter() functionality for better performance.

§Arguments
  • va - Virtual address to start reading from.
  • size - Number of bytes to read.
§Examples
// Read 0x100 bytes of data from the base of kernel32.
// Example assumes: use pretty_hex::*;
if let Ok(data_read) = vmmprocess.mem_read(va_kernel32, 0x100) {
    println!("{:?}", data_read.hex_dump());
}
source

pub fn mem_read_ex(&self, va: u64, size: usize, flags: u64) -> ResultEx<Vec<u8>>

Read a contigious virtual memory chunk with flags.

Flags are constants named FLAG_*

Reading many memory chunks individually may be slow, especially if reading takes place using hardware FPGA devices. In that case it’s better to use the mem_scatter() functionality for better performance.

§Arguments
  • va - Virtual address to start reading from.
  • size - Number of bytes to read.
  • flags - Any combination of FLAG_*.
§Examples
// Read 0x100 bytes of data from the base of kernel32.
// Force reading the underlying memory device (skip data cache) and
// Zero-Pad if parts of the memory read fail instead of failing.
// Example assumes: use pretty_hex::*;
let r = vmmprocess.mem_read_ex(va_kernel32, 0x100, FLAG_NOCACHE | FLAG_ZEROPAD_ON_FAIL);
let Ok(data_read) = r {
    println!("{:?}", data_read.hex_dump());
}
source

pub fn mem_read_as<T>(&self, va: u64, flags: u64) -> ResultEx<T>

Read a contigious virtual memory chunk with flags as a type/struct.

Flags are constants named FLAG_*

Reading many memory chunks individually may be slow, especially if reading takes place using hardware FPGA devices. In that case it’s better to use the mem_scatter() functionality for better performance.

§Arguments
  • va - Virtual address to start reading from.
  • flags - Any combination of FLAG_*.
§Examples
// Read the C-struct IMAGE_DOS_HEADER from memory.
// Force reading the underlying memory device (skip data cache).
#[repr(C)]
struct IMAGE_DOS_HEADER {
    e_magic : u16,
	...
    e_lfanew : u32,
}
if let Ok(doshdr) = vmmprocess.mem_read_as::<IMAGE_DOS_HEADER>(va_kernel32, FLAG_NOCACHE) {
    println!("e_magic:  {:x}", doshdr.e_magic);
    println!("e_lfanew: {:x}", doshdr.e_lfanew);
}
source

pub fn mem_scatter(&self, flags: u64) -> ResultEx<VmmScatterMemory<'_>>

Create a scatter memory object for efficient virtual memory reads.

Check out the VmmScatterMemory struct for more detailed information.

§Arguments
  • flags - Any combination of FLAG_*.
§Examples
let mem_scatter = vmmprocess.mem_scatter(FLAG_NOCACHE | FLAG_ZEROPAD_ON_FAIL)?;
source

pub fn mem_virt2phys(&self, va: u64) -> ResultEx<u64>

Translate a virtual address to a physical address.

It’s not always possible to translate a virtual address to a physical address. This is the case when memory is “paged out”.

§Arguments
  • va - Virtual address to translate.
§Examples
let pa_kernel32 = vmmprocess.mem_virt2phys(va_kernel32)?;
source

pub fn mem_write(&self, va: u64, data: &Vec<u8>) -> ResultEx<()>

Write virtual memory.

The write is a best effort. Even of the write should fail it’s not certain that an error will be returned. To be absolutely certain that a write has taken place follow up with a read.

§Arguments
  • va - Virtual address to start writing from.
  • data - Byte data to write.
§Examples
// Write data starting at the base of kernel32 (in the pe header).
let data_to_write = [0x56u8, 0x4d, 0x4d, 0x52, 0x55, 0x53, 0x54].to_vec();
let _r = vmmprocess.mem_write(va_kernel32, &data_to_write);
source

pub fn mem_write_as<T>(&self, va: u64, data: &T) -> ResultEx<()>

Write a type/struct to virtual memory.

The write is a best effort. Even of the write should fail it’s not certain that an error will be returned. To be absolutely certain that a write has taken place follow up with a read.

§Arguments
  • va - Virtual address to start writing from.
  • data - Data to write. In case of a struct repr(C) is recommended.
§Examples
// Write data starting at the base of kernel32 (in the pe header).
let data_to_write = [0x56, 0x4d, 0x4d, 0x52, 0x55, 0x53, 0x54];
let _r = vmmprocess.mem_write_as(va_kernel32, &data_to_write);
source

pub fn pdb_from_module_address( &self, va_module_base: u64 ) -> ResultEx<VmmPdb<'_>>

Retrieve PDB debugging for the module.

PDB debugging most often only work on modules by Microsoft. See VmmPdb documentation for additional information.

§Arguments
  • va_module_base
§Examples
if let Ok(pdb_kernel32) = vmmprocess.pdb_from_module_address(kernel32.va_base) {
    println!("-> {pdb_kernel32}");
}
source

pub fn search( &self, addr_min: u64, addr_max: u64, num_results_max: u32, flags: u64 ) -> ResultEx<VmmSearch<'_>>

Retrieve a search struct for process virtual memory.

NB! This does not start the actual search yet.

Check out the VmmSearch struct for more detailed information.

§Arguments
  • addr_min - Start search at this virtual address.
  • addr_max - End the search at this virtual address. 0 is interpreted as u64::MAX.
  • num_results_max - Max number of search hits to search for. Max allowed value is 0x10000.
  • flags - Any combination of FLAG_*.
§Examples
// Retrieve a VmmSearch for the entire virtual memory.
let mut search = vmmprocess.search(0, 0, 0x10000, 0)?
// Retrieve a VmmSearch for virtual memory. Stop at first hit.
// Also avoid using cached and paged out memory.
let mut search = vmmprocess.search(0, 0, 1, FLAG_NOCACHE | FLAG_NOPAGING)?
source

pub fn search_yara( &self, rules: Vec<&str>, addr_min: u64, addr_max: u64, num_results_max: u32, flags: u64 ) -> ResultEx<VmmYara<'_>>

Retrieve a yara search struct for process virtual memory.

NB! This does not start the actual search yet.

Check out the VmmYara struct for more detailed information.

§Arguments
  • rules - Yara rules to search for.
  • addr_min - Start yara search at this virtual address.
  • addr_max - End the yara search at this virtual address. 0 is interpreted as u64::MAX.
  • num_results_max - Max number of yara search hits to search for. Max allowed value is 0x10000.
  • flags - Any combination of FLAG_*.
§Examples
§Examples
// Retrieve a VmmYara for the entire physical memory.
let yara_rule = " rule mz_header { strings: $mz = \"MZ\" condition: $mz at 0 } ";
let yara_rules = vec![yara_rule];
let mut yara = vmmprocess.search_yara(yara_rules, 0, 0, 0x10000, 0)?
// Retrieve a VmmYara for physical memory between 4GB and 8GB.
// Also stop at first yara search hit.
let yara_rules = vec!["/tmp/my_yara_rule.yar", "/tmp/my_yara_rule2.yar"];
let mut yara = vmmprocess.search_yara(yara_rules, 0x100000000, 0x200000000, 1, 0)?

Trait Implementations§

source§

impl<'a> Debug for VmmProcess<'a>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for VmmProcess<'_>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for VmmProcess<'_>

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

§

impl<'a> Freeze for VmmProcess<'a>

§

impl<'a> RefUnwindSafe for VmmProcess<'a>

§

impl<'a> Send for VmmProcess<'a>

§

impl<'a> Sync for VmmProcess<'a>

§

impl<'a> Unpin for VmmProcess<'a>

§

impl<'a> UnwindSafe for VmmProcess<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.