use memflow::connector::ConnectorInventory; use memflow::connector::ConnectorArgs; use memflow::mem::*; use memflow_win32::error::{Error, Result}; use memflow_win32::win32::{Kernel, Win32ModuleInfo, Win32Process}; use clap::*; use log::Level; use colored::*; static mut HAD_ERROR: bool = false; fn main() -> Result<()> { let (connector, args_str) = parse_args(); let args = ConnectorArgs::parse(&args_str)?; // create inventory + connector let inventory = unsafe { ConnectorInventory::scan() }; let connector = unsafe { inventory.create_connector(&connector, &args)? }; let mut kernel = build_kernel(connector)?; { println!("Kernel info:"); let info = &kernel.kernel_info; let start_block = &info.start_block; println!( "{:#?} ... {}", start_block, some_str(&start_block.dtb.non_null()) ); println!( "kernel_base: {:x} ... {}", info.kernel_base, some_str(&info.kernel_base.non_null()) ); println!( "kernel_size: {:x} ... {}", info.kernel_size, bool_str(info.kernel_size != 0) ); println!( "kernel_guid: {:?} ... {}", info.kernel_guid, some_str(&info.kernel_guid) ); println!( "kernel_winver: {:?} ... {}", info.kernel_winver.as_tuple(), bool_str(info.kernel_winver != (0, 0).into()) ); println!( "eprocess_base: {:x} ... {}", info.eprocess_base, some_str(&info.eprocess_base.non_null()) ); println!(); } { println!("Kernel Process:"); if let Ok(proc_info) = kernel.kernel_process_info() { let mut kernel_proc = Win32Process::with_kernel_ref(&mut kernel, proc_info); let modules = modules(&mut kernel_proc)?; println!("checking module list:"); println!( "ntoskrnl.exe ... {}", some_str( &modules .iter() .find(|e| e.name.to_lowercase() == "ntoskrnl.exe") ) ); println!( "hal.dll ... {}", some_str(&modules.iter().find(|e| e.name.to_lowercase() == "hal.dll")) ); } else { println!("{}", bool_str(false)); } println!(); } { println!("Process List:"); let proc_list = kernel.process_info_list()?; let lsass = proc_list .iter() .find(|p| p.name.to_lowercase() == "lsass.exe"); println!("lsass.exe ... {}", some_str(&lsass)); println!(); if let Some(proc) = lsass { println!("{} info:", proc.name); println!("pid: {} ... {}", proc.pid, bool_str(proc.pid < 10000)); println!("dtb: {} ... {}", proc.dtb, some_str(&proc.dtb.non_null())); println!( "section_base: {} ... {}", proc.section_base, some_str(&proc.section_base.non_null()) ); println!( "ethread: {} ... {}", proc.ethread, some_str(&proc.ethread.non_null()) ); println!("teb: {:?} ... {}", proc.teb, bool_str(proc.teb.is_none())); println!( "teb_wow64: {:?} ... {}", proc.teb_wow64, bool_str(proc.teb_wow64.is_none()) ); println!( "peb_native: {} ... {}", proc.peb_native, some_str(&proc.peb_native.non_null()) ); println!( "peb_wow64: {:?} ... {}", proc.teb_wow64, bool_str(proc.peb_wow64.is_none()) ); } } unsafe { if HAD_ERROR { Err(Error::Other( "Some errors encountered, not all functionality may be present!", )) } else { Ok(()) } } } fn some_str(r: &Option) -> ColoredString { bool_str(r.is_some()) } fn ok_str(r: &Result) -> ColoredString { bool_str(r.is_ok()) } fn bool_str(b: bool) -> ColoredString { if b { "ok".green() } else { unsafe { HAD_ERROR = true }; "error".red() } } fn modules(process: &mut Win32Process) -> Result> { let modules = process.module_list(); println!("modules ... {}", ok_str(&modules)); modules } fn build_kernel( mem: T, ) -> Result> { let kernel = Kernel::builder(mem).build_default_caches().build(); println!("Kernel::build ... {}", ok_str(&kernel)); println!(); kernel } fn parse_args() -> (String, String) { let matches = App::new("read_keys example") .version(crate_version!()) .author(crate_authors!()) .arg(Arg::with_name("verbose").short("v").multiple(true)) .arg( Arg::with_name("connector") .long("connector") .short("c") .takes_value(true) .required(true), ) .arg( Arg::with_name("args") .long("args") .short("a") .takes_value(true) .default_value(""), ) .get_matches(); // set log level let level = match matches.occurrences_of("verbose") { 0 => Level::Error, 1 => Level::Warn, 2 => Level::Info, 3 => Level::Debug, 4 => Level::Trace, _ => Level::Trace, }; simple_logger::SimpleLogger::new() .with_level(level.to_level_filter()) .init() .unwrap(); ( matches.value_of("connector").unwrap().into(), matches.value_of("args").unwrap().into(), ) }