Scan unloaded module/driver
By reversing MmLocateUnloadedDriver, we can know the algorithm to extract name/start/end of unloaded drivers
This commit is contained in:
parent
5619048a4a
commit
0350ec46d9
@ -2,16 +2,22 @@ use std::error::Error;
|
||||
|
||||
use lpus::{
|
||||
driver_state::{DriverState},
|
||||
traverse_loadedmodulelist
|
||||
traverse_loadedmodulelist,
|
||||
traverse_unloadeddrivers
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
||||
let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
||||
let unloaded = traverse_unloadeddrivers(&driver).unwrap_or(Vec::new());
|
||||
|
||||
for r in result.iter() {
|
||||
for r in loaded.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
println!("=============================================");
|
||||
for r in unloaded.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
|
||||
|
37
src/lib.rs
37
src/lib.rs
@ -528,3 +528,40 @@ pub fn traverse_handletable(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn traverse_unloadeddrivers(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
let ntosbase = driver.get_kernel_base();
|
||||
let unload_array_ptr = ntosbase.clone() + driver.pdb_store.get_offset_r("MmUnloadedDrivers")?;
|
||||
let num_unload_ptr = ntosbase.clone() + driver.pdb_store.get_offset_r("MmLastUnloadedDriver")?;
|
||||
|
||||
let unload_array = driver.deref_addr_new::<u64>(unload_array_ptr.address());
|
||||
if unload_array == 0 {
|
||||
return Err("The unload driver list is null".into());
|
||||
}
|
||||
|
||||
// by reversing MmLocateUnloadedDriver
|
||||
let num_unload = driver.deref_addr_new::<u32>(num_unload_ptr.address()) as u64;
|
||||
let bound =
|
||||
if num_unload > 0x32 { 0x32 }
|
||||
else { num_unload };
|
||||
let drivers = (0..bound).map(|i| Address::from_base(unload_array + (i * 0x28)));
|
||||
|
||||
for driver_addr in drivers {
|
||||
let name = driver.get_unicode_string(driver_addr.address()).unwrap_or("".to_string());
|
||||
let start_addr: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.StartAddress")?;
|
||||
let end_addr: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.EndAddress")?;
|
||||
let current_time: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.CurrentTime")?;
|
||||
|
||||
result.push(json!({
|
||||
"address": format!("0x{:x}", driver_addr.address()),
|
||||
"type": "_UNLOADED_DRIVERS",
|
||||
"name": name,
|
||||
"start_addr": format!("0x{:x}", start_addr),
|
||||
"end_addr": format!("0x{:x}", end_addr),
|
||||
"current_time": driver.windows_ffi.to_epoch(current_time)
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ pub fn parse_pdb() -> BoxResult<PdbStore> {
|
||||
match typ.parse() {
|
||||
Ok(TypeData::Class(ClassType {name, fields: Some(fields), size, ..})) => {
|
||||
let mut struct_fields = HashMap::new();
|
||||
struct_fields.insert("struct_size".to_string(), ("u32".to_string(), size as u64));
|
||||
struct_fields.insert("struct_size".to_string(), ("U32".to_string(), size as u64));
|
||||
match type_finder.find(fields).unwrap().parse().unwrap() {
|
||||
TypeData::FieldList(list) => {
|
||||
for field in list.fields {
|
||||
@ -441,6 +441,17 @@ pub fn parse_pdb() -> BoxResult<PdbStore> {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Include/mm.h#L1107
|
||||
let mut unload_driver_member = HashMap::new();
|
||||
unload_driver_member.insert("struct_size".to_string(), ("U32".to_string(), 0x30));
|
||||
unload_driver_member.insert("Name".to_string(), ("_UNICODE_STRING".to_string(), 0));
|
||||
unload_driver_member.insert("StartAddress".to_string(), ("PVOID".to_string(), 0x10));
|
||||
unload_driver_member.insert("EndAddress".to_string(), ("PVOID".to_string(), 0x18));
|
||||
unload_driver_member.insert("CurrentTime".to_string(), ("_LARGE_INTEGER".to_string(), 0x20));
|
||||
struct_extracted.insert("_UNLOADED_DRIVERS".to_string(), unload_driver_member);
|
||||
}
|
||||
|
||||
Ok(PdbStore {
|
||||
symbols: symbol_extracted,
|
||||
structs: struct_extracted
|
||||
|
@ -212,6 +212,15 @@ impl WindowsFFI {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn to_epoch(&self, filetime: u64) -> u64 {
|
||||
let windows_epoch_diff = 11644473600000 * 10000;
|
||||
if filetime < windows_epoch_diff {
|
||||
return 0;
|
||||
}
|
||||
let process_time_epoch = (filetime - windows_epoch_diff) / 10000;
|
||||
process_time_epoch
|
||||
}
|
||||
|
||||
pub fn valid_process_time(&self, filetime: u64) -> bool {
|
||||
// https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/
|
||||
let windows_epoch_diff = 11644473600000 * 10000;
|
||||
|
Loading…
Reference in New Issue
Block a user