Update scan for kernel modules and driver
Scan kernel modules Driver scan major functions' address
This commit is contained in:
parent
1707b301ff
commit
8cf91aef79
22
src/bin/kernel_module_scan.rs
Normal file
22
src/bin/kernel_module_scan.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
55
src/lib.rs
55
src/lib.rs
@ -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(ðread_ptr, "_ETHREAD.ThreadName")?;
|
let unicode_str_ptr: u64 = driver.address_of(ðread_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)
|
||||||
})?;
|
})?;
|
||||||
|
Loading…
Reference in New Issue
Block a user