Update scan for kernel modules and driver

Scan kernel modules
Driver scan major functions' address
This commit is contained in:
nganhkhoa 2020-06-22 14:52:15 +07:00
parent 1707b301ff
commit 8cf91aef79
4 changed files with 89 additions and 19 deletions

View File

@ -0,0 +1,22 @@
use std::error::Error;
use lpus::{
driver_state::{DriverState},
scan_kernel_module
};
fn main() -> Result<(), Box<dyn Error>> {
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(())
}

View File

@ -1,12 +1,26 @@
use std::error::Error; use std::error::Error;
// use std::time::{SystemTime, UNIX_EPOCH};
use lpus::{ use lpus::{
driver_state::{DriverState}, 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<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let driver = DriverState::new(); let driver = DriverState::new();
driver.windows_ffi.print_version(); driver.windows_ffi.print_version();
driver.pdb_store.print_default_information(); driver.pdb_store.print_default_information();
Ok(()) Ok(())
} }

View File

@ -3,7 +3,7 @@ use std::clone::Clone;
use std::error::Error; use std::error::Error;
// use std::io::{Error, ErrorKind}; // use std::io::{Error, ErrorKind};
use std::ffi::c_void; 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::ntdef::{NTSTATUS};
use winapi::shared::minwindef::{DWORD}; use winapi::shared::minwindef::{DWORD};
@ -233,7 +233,8 @@ impl DriverState {
pub fn deref_array<T: Default + Clone>(&self, addr: &Address, len: u64) -> Vec<T> { pub fn deref_array<T: Default + Clone>(&self, addr: &Address, len: u64) -> Vec<T> {
let resolver = |p| { self.deref_addr_new(p) }; let resolver = |p| { self.deref_addr_new(p) };
let mut r: Vec<T> = vec![Default::default(); len as usize]; let mut r: Vec<T> = 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::<T>();
self.deref_addr_ptr(addr.get(&resolver), r.as_mut_ptr(), size_in_byte as u64);
r r
} }
@ -251,20 +252,20 @@ impl DriverState {
} }
// #[deprecated(note="use deref_array<T>")] // #[deprecated(note="use deref_array<T>")]
pub fn deref_addr_ptr<T>(&self, addr: u64, outptr: *mut T, output_len: u64) { pub fn deref_addr_ptr<T>(&self, addr: u64, outptr: *mut T, output_len_as_byte: u64) {
let code = DriverAction::DereferenceAddress.get_code(); let code = DriverAction::DereferenceAddress.get_code();
let mut input = InputData { let mut input = InputData {
deref_addr: DerefAddr { deref_addr: DerefAddr {
addr, addr,
size: output_len size: output_len_as_byte
} }
}; };
self.windows_ffi.device_io_raw(code, self.windows_ffi.device_io_raw(code,
&mut input as *mut _ as *mut c_void, size_of_val(&input) as DWORD, &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<String> { pub fn get_unicode_string(&self, unicode_str_addr: u64) -> BoxResult<String> {
if unicode_str_addr == 0 { if unicode_str_addr == 0 {
return Err("Not a valid address".into()); return Err("Not a valid address".into());
} }
@ -283,10 +284,6 @@ impl DriverState {
return Err("Unicode string is empty".into()); return Err("Unicode string is empty".into());
} }
if !deref {
return Ok("".to_string());
}
let mut buf = vec![0u16; (strlen / 2) as usize]; let mut buf = vec![0u16; (strlen / 2) as usize];
self.deref_addr_ptr(bufaddr, buf.as_mut_ptr(), strlen as u64); self.deref_addr_ptr(bufaddr, buf.as_mut_ptr(), strlen as u64);
// TODO: BUG with deref_array, len is wrong, // TODO: BUG with deref_array, len is wrong,

View File

@ -50,7 +50,7 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
} else { } else {
"".to_string() "".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()); .unwrap_or("".to_string());
result.push(json!({ result.push(json!({
@ -104,15 +104,15 @@ pub fn scan_file(driver: &DriverState) -> BoxResult<Vec<Value>> {
if read_ok == 0 { if read_ok == 0 {
"[NOT READABLE]".to_string() "[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 n
} }
else { else {
"[NOT A VALID _UNICODE_STRING]".to_string() "[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()); .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()); .unwrap_or("".to_string());
result.push(json!({ result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()), "pool": format!("0x{:x}", pool_addr.address()),
@ -165,7 +165,7 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
let unicode_str_ptr: u64 = driver.address_of(ethread_ptr, "_ETHREAD.ThreadName")?; let unicode_str_ptr: u64 = driver.address_of(ethread_ptr, "_ETHREAD.ThreadName")?;
let thread_name = 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 name
} }
else { else {
@ -222,7 +222,7 @@ pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
let unicode_str_ptr: u64 = driver.address_of(&ethread_ptr, "_ETHREAD.ThreadName")?; let unicode_str_ptr: u64 = driver.address_of(&ethread_ptr, "_ETHREAD.ThreadName")?;
let thread_name = 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 name
} }
else { else {
@ -269,17 +269,54 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
let devicename_ptr = driver.address_of(dob_addr, "_DRIVER_OBJECT.DriverName")?; let devicename_ptr = driver.address_of(dob_addr, "_DRIVER_OBJECT.DriverName")?;
let hardware_ptr: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.HardwareDatabase")?; let hardware_ptr: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.HardwareDatabase")?;
let major_function: Vec<u64> = 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()); .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()); .unwrap_or("".to_string());
result.push(json!({ result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()), "pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", dob_addr.address()), "address": format!("0x{:x}", dob_addr.address()),
"type": "_DRIVER_OBJECT", "type": "_DRIVER_OBJECT",
"device": devicename, "device": devicename,
"hardware": hardware "hardware": hardware,
"major_function": major_function.into_iter()
.map(|func| format!("0x{:x}", func))
.collect::<Vec<String>>()
}));
Ok(true)
})?;
Ok(result)
}
pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = 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) Ok(true)
})?; })?;