From 8cf91aef79986b25736181b55133bcb89dda4b12 Mon Sep 17 00:00:00 2001 From: nganhkhoa Date: Mon, 22 Jun 2020 14:52:15 +0700 Subject: [PATCH] Update scan for kernel modules and driver Scan kernel modules Driver scan major functions' address --- src/bin/kernel_module_scan.rs | 22 ++++++++++++++ src/bin/print_pdb.rs | 14 +++++++++ src/driver_state.rs | 17 +++++------ src/lib.rs | 55 +++++++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 19 deletions(-) create mode 100644 src/bin/kernel_module_scan.rs diff --git a/src/bin/kernel_module_scan.rs b/src/bin/kernel_module_scan.rs new file mode 100644 index 0000000..980b763 --- /dev/null +++ b/src/bin/kernel_module_scan.rs @@ -0,0 +1,22 @@ +use std::error::Error; + +use lpus::{ + driver_state::{DriverState}, + scan_kernel_module +}; + +fn main() -> Result<(), Box> { + let mut driver = DriverState::new(); + println!("NtLoadDriver() -> 0x{:x}", driver.startup()); + + let result = scan_kernel_module(&driver).unwrap_or(Vec::new()); + + for r in result.iter() { + println!("{:#}", r.to_string()); + } + + println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown()); + Ok(()) +} + + diff --git a/src/bin/print_pdb.rs b/src/bin/print_pdb.rs index dc15394..2009034 100644 --- a/src/bin/print_pdb.rs +++ b/src/bin/print_pdb.rs @@ -1,12 +1,26 @@ use std::error::Error; +// use std::time::{SystemTime, UNIX_EPOCH}; use lpus::{ driver_state::{DriverState}, }; +pub fn to_epoch(filetime: u64) -> u64 { + // https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ + let windows_epoch_diff = 11644473600000 * 10000; + if filetime < windows_epoch_diff { + return 0; + } + let process_time_epoch = (filetime - windows_epoch_diff) / 10000; + // let now_ms = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis() as u64; + + process_time_epoch +} + fn main() -> Result<(), Box> { let driver = DriverState::new(); driver.windows_ffi.print_version(); driver.pdb_store.print_default_information(); + Ok(()) } diff --git a/src/driver_state.rs b/src/driver_state.rs index 9dd52da..aa453e5 100644 --- a/src/driver_state.rs +++ b/src/driver_state.rs @@ -3,7 +3,7 @@ use std::clone::Clone; use std::error::Error; // use std::io::{Error, ErrorKind}; use std::ffi::c_void; -use std::mem::{size_of_val}; +use std::mem::{size_of_val, size_of}; use winapi::shared::ntdef::{NTSTATUS}; use winapi::shared::minwindef::{DWORD}; @@ -233,7 +233,8 @@ impl DriverState { pub fn deref_array(&self, addr: &Address, len: u64) -> Vec { let resolver = |p| { self.deref_addr_new(p) }; let mut r: Vec = vec![Default::default(); len as usize]; - self.deref_addr_ptr(addr.get(&resolver), r.as_mut_ptr(), len); + let size_in_byte = (len as usize) * size_of::(); + self.deref_addr_ptr(addr.get(&resolver), r.as_mut_ptr(), size_in_byte as u64); r } @@ -251,20 +252,20 @@ impl DriverState { } // #[deprecated(note="use deref_array")] - pub fn deref_addr_ptr(&self, addr: u64, outptr: *mut T, output_len: u64) { + pub fn deref_addr_ptr(&self, addr: u64, outptr: *mut T, output_len_as_byte: u64) { let code = DriverAction::DereferenceAddress.get_code(); let mut input = InputData { deref_addr: DerefAddr { addr, - size: output_len + size: output_len_as_byte } }; self.windows_ffi.device_io_raw(code, &mut input as *mut _ as *mut c_void, size_of_val(&input) as DWORD, - outptr as *mut c_void, output_len as DWORD); + outptr as *mut c_void, output_len_as_byte as DWORD); } - pub fn get_unicode_string(&self, unicode_str_addr: u64, deref: bool) -> BoxResult { + pub fn get_unicode_string(&self, unicode_str_addr: u64) -> BoxResult { if unicode_str_addr == 0 { return Err("Not a valid address".into()); } @@ -283,10 +284,6 @@ impl DriverState { return Err("Unicode string is empty".into()); } - if !deref { - return Ok("".to_string()); - } - let mut buf = vec![0u16; (strlen / 2) as usize]; self.deref_addr_ptr(bufaddr, buf.as_mut_ptr(), strlen as u64); // TODO: BUG with deref_array, len is wrong, diff --git a/src/lib.rs b/src/lib.rs index 266b55a..6cb7d96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,7 +50,7 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult> { } else { "".to_string() }; - let binary_path = driver.get_unicode_string(unicode_str_ptr, true) + let binary_path = driver.get_unicode_string(unicode_str_ptr) .unwrap_or("".to_string()); result.push(json!({ @@ -104,15 +104,15 @@ pub fn scan_file(driver: &DriverState) -> BoxResult> { if read_ok == 0 { "[NOT READABLE]".to_string() } - else if let Ok(n) = driver.get_unicode_string(filename_ptr, true) { + else if let Ok(n) = driver.get_unicode_string(filename_ptr) { n } else { "[NOT A VALID _UNICODE_STRING]".to_string() }; - let devicename = driver.get_unicode_string(devicename_ptr, true) + let devicename = driver.get_unicode_string(devicename_ptr) .unwrap_or("".to_string()); - let hardware = driver.get_unicode_string(hardware_ptr, true) + let hardware = driver.get_unicode_string(hardware_ptr) .unwrap_or("".to_string()); result.push(json!({ "pool": format!("0x{:x}", pool_addr.address()), @@ -165,7 +165,7 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult> { let unicode_str_ptr: u64 = driver.address_of(ethread_ptr, "_ETHREAD.ThreadName")?; let thread_name = - if let Ok(name) = driver.get_unicode_string(unicode_str_ptr, true) { + if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) { name } else { @@ -222,7 +222,7 @@ pub fn scan_mutant(driver: &DriverState) -> BoxResult> { let unicode_str_ptr: u64 = driver.address_of(ðread_ptr, "_ETHREAD.ThreadName")?; let thread_name = - if let Ok(name) = driver.get_unicode_string(unicode_str_ptr, true) { + if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) { name } else { @@ -269,17 +269,54 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult> { let devicename_ptr = driver.address_of(dob_addr, "_DRIVER_OBJECT.DriverName")?; let hardware_ptr: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.HardwareDatabase")?; + let major_function: Vec = driver.decompose_array(dob_addr, "_DRIVER_OBJECT.MajorFunction", 28)?; - let devicename = driver.get_unicode_string(devicename_ptr, true) + let devicename = driver.get_unicode_string(devicename_ptr) .unwrap_or("".to_string()); - let hardware = driver.get_unicode_string(hardware_ptr, true) + let hardware = driver.get_unicode_string(hardware_ptr) .unwrap_or("".to_string()); result.push(json!({ "pool": format!("0x{:x}", pool_addr.address()), "address": format!("0x{:x}", dob_addr.address()), "type": "_DRIVER_OBJECT", "device": devicename, - "hardware": hardware + "hardware": hardware, + "major_function": major_function.into_iter() + .map(|func| format!("0x{:x}", func)) + .collect::>() + })); + Ok(true) + })?; + + Ok(result) +} + +pub fn scan_kernel_module(driver: &DriverState) -> BoxResult> { + let mut result: Vec = Vec::new(); + + driver.scan_pool(b"MmLd", "_KLDR_DATA_TABLE_ENTRY", |pool_addr, _, data_addr| { + // By reversing, this structure does not have any header + let mod_addr = &data_addr; + + let dllbase: u64 = driver.decompose(mod_addr, "_KLDR_DATA_TABLE_ENTRY.DllBase")?; + let entry: u64 = driver.decompose(mod_addr, "_KLDR_DATA_TABLE_ENTRY.EntryPoint")?; + let size: u64 = driver.decompose(mod_addr, "_KLDR_DATA_TABLE_ENTRY.SizeOfImage")?; + let fullname_ptr = driver.address_of(mod_addr, "_KLDR_DATA_TABLE_ENTRY.FullDllName")?; + let basename_ptr = driver.address_of(mod_addr, "_KLDR_DATA_TABLE_ENTRY.BaseDllName")?; + + let fullname = driver.get_unicode_string(fullname_ptr) + .unwrap_or("".to_string()); + let basename = driver.get_unicode_string(basename_ptr) + .unwrap_or("".to_string()); + result.push(json!({ + "pool": format!("0x{:x}", pool_addr.address()), + "address": format!("0x{:x}", mod_addr.address()), + "type": "_KLDR_DATA_TABLE_ENTRY", + "dllbase": format!("0x{:x}", dllbase), + "entry": format!("0x{:x}", entry), + "size": format!("0x{:x}", size), + "FullName": fullname, + "BaseName": basename })); Ok(true) })?;