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
vmm.process_from_pid()
vmm.process_from_name()
vmm.process_list()
vmm.kernel().process()
plugin sub-system
§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<'_>
impl VmmProcess<'_>
sourcepub fn get_module_base(&self, module_name: &str) -> ResultEx<u64>
pub fn get_module_base(&self, module_name: &str) -> ResultEx<u64>
sourcepub fn get_proc_address(
&self,
module_name: &str,
function_name: &str
) -> ResultEx<u64>
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);
}
sourcepub fn get_path_kernel(&self) -> ResultEx<String>
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}");
}
sourcepub fn get_path_user(&self) -> ResultEx<String>
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}");
}
sourcepub fn get_cmdline(&self) -> ResultEx<String>
pub fn get_cmdline(&self) -> ResultEx<String>
Get the process command line.
§Examples
if let Ok(s_cmdline) = vmmprocess.get_cmdline() {
println!("-> {s_cmdline}");
}
sourcepub fn info(&self) -> ResultEx<VmmProcessInfo>
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);
}
sourcepub fn map_handle(&self) -> ResultEx<Vec<VmmProcessMapHandleEntry>>
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}");
}
}
sourcepub fn map_heap(&self) -> ResultEx<Vec<VmmProcessMapHeapEntry>>
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}");
}
}
sourcepub fn map_heapalloc(
&self,
heap_number_or_address: u64
) -> ResultEx<Vec<VmmProcessMapHeapAllocEntry>>
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
heap_number_or_address
- Heap number as given byVmmProcessMapHeapEntry
or the heap base address.
§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!("");
}
sourcepub fn map_module(
&self,
is_info_debug: bool,
is_info_version: bool
) -> ResultEx<Vec<VmmProcessMapModuleEntry>>
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}");
}
}
sourcepub fn map_module_data_directory(
&self,
module_name: &str
) -> ResultEx<Vec<VmmProcessMapDirectoryEntry>>
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}");
}
}
sourcepub fn map_module_eat(
&self,
module_name: &str
) -> ResultEx<Vec<VmmProcessMapEatEntry>>
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);
}
}
sourcepub fn map_module_iat(
&self,
module_name: &str
) -> ResultEx<Vec<VmmProcessMapIatEntry>>
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}");
}
}
sourcepub fn map_module_section(
&self,
module_name: &str
) -> ResultEx<Vec<VmmProcessSectionEntry>>
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}");
}
}
sourcepub fn map_pte(
&self,
is_identify_modules: bool
) -> ResultEx<Vec<VmmProcessMapPteEntry>>
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);
}
}
sourcepub fn map_thread(&self) -> ResultEx<Vec<VmmProcessMapThreadEntry>>
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}");
}
}
sourcepub fn map_unloaded_module(
&self
) -> ResultEx<Vec<VmmProcessMapUnloadedModuleEntry>>
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}");
}
}
sourcepub fn map_vad(
&self,
is_identify_modules: bool
) -> ResultEx<Vec<VmmProcessMapVadEntry>>
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);
}
}
sourcepub fn map_vadex(
&self,
offset_pages: u32,
count_pages: u32
) -> ResultEx<Vec<VmmProcessMapVadExEntry>>
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.
sourcepub fn mem_read(&self, va: u64, size: usize) -> ResultEx<Vec<u8>>
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());
}
sourcepub fn mem_read_ex(&self, va: u64, size: usize, flags: u64) -> ResultEx<Vec<u8>>
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 ofFLAG_*
.
§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());
}
sourcepub fn mem_read_as<T>(&self, va: u64, flags: u64) -> ResultEx<T>
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 ofFLAG_*
.
§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);
}
sourcepub fn mem_scatter(&self, flags: u64) -> ResultEx<VmmScatterMemory<'_>>
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 ofFLAG_*
.
§Examples
let mem_scatter = vmmprocess.mem_scatter(FLAG_NOCACHE | FLAG_ZEROPAD_ON_FAIL)?;
sourcepub fn mem_virt2phys(&self, va: u64) -> ResultEx<u64>
pub fn mem_virt2phys(&self, va: u64) -> ResultEx<u64>
sourcepub fn mem_write(&self, va: u64, data: &Vec<u8>) -> ResultEx<()>
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);
sourcepub fn mem_write_as<T>(&self, va: u64, data: &T) -> ResultEx<()>
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);
sourcepub fn pdb_from_module_address(
&self,
va_module_base: u64
) -> ResultEx<VmmPdb<'_>>
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}");
}
sourcepub fn search(
&self,
addr_min: u64,
addr_max: u64,
num_results_max: u32,
flags: u64
) -> ResultEx<VmmSearch<'_>>
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 ofFLAG_*
.
§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)?
sourcepub fn search_yara(
&self,
rules: Vec<&str>,
addr_min: u64,
addr_max: u64,
num_results_max: u32,
flags: u64
) -> ResultEx<VmmYara<'_>>
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 ofFLAG_*
.
§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)?