Update working status for Windows 7
This commit is contained in:
parent
8cb553eb11
commit
4e67e10aee
@ -7,6 +7,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = scan_driver(&driver).unwrap_or(Vec::new());
|
||||
|
@ -7,6 +7,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = scan_eprocess(&driver).unwrap_or(Vec::new());
|
||||
|
@ -9,6 +9,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let activehead = traverse_activehead(&driver).unwrap_or(Vec::new());
|
||||
|
@ -7,6 +7,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = scan_file(&driver).unwrap_or(Vec::new());
|
||||
|
@ -7,6 +7,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = scan_kernel_module(&driver).unwrap_or(Vec::new());
|
||||
|
@ -10,6 +10,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
||||
|
@ -25,6 +25,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
driver.windows_ffi.print_version();
|
||||
driver.pdb_store.print_default_information();
|
||||
|
||||
println!("{}", to_epoch(0xfffffa80018cb688));
|
||||
println!("{}", to_epoch(0x01d64ecd8b295318));
|
||||
|
||||
let mut rl = Editor::<()>::new();
|
||||
if rl.load_history("history.lpus").is_err() {
|
||||
println!("No previous history.");
|
||||
|
@ -7,6 +7,9 @@ use lpus::{
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
if !driver.is_supported() {
|
||||
return Err(format!("Windows version {:?} is not supported", driver.windows_ffi.short_version).into());
|
||||
}
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let threads = scan_ethread(&driver).unwrap_or(Vec::new());
|
||||
|
@ -103,6 +103,20 @@ impl DriverState {
|
||||
self.windows_ffi.unload_driver()
|
||||
}
|
||||
|
||||
pub fn is_supported(&self) -> bool {
|
||||
self.windows_ffi.short_version.is_supported()
|
||||
}
|
||||
|
||||
pub fn use_old_tag(&self) -> bool {
|
||||
// use old tag to scan, for Window < 8
|
||||
if self.windows_ffi.short_version < WindowsVersion::Windows8 {
|
||||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_kernel_base(&self) -> Address {
|
||||
let mut ntosbase = 0u64;
|
||||
self.windows_ffi.device_io(DriverAction::GetKernelBase.get_code(),
|
||||
@ -110,46 +124,12 @@ impl DriverState {
|
||||
Address::from_base(ntosbase)
|
||||
}
|
||||
|
||||
// pub fn scan_active_head(&self) -> BoxResult<Vec<EprocessPoolChunk>> {
|
||||
// let ntosbase = self.get_kernel_base();
|
||||
// let ps_active_head = ntosbase + self.pdb_store.get_offset_r("PsActiveProcessHead")?;
|
||||
// let flink_offset = self.pdb_store.get_offset_r("_LIST_ENTRY.Flink")?;
|
||||
// let eprocess_link_offset = self.pdb_store.get_offset_r("_EPROCESS.ActiveProcessLinks")?;
|
||||
// let eprocess_name_offset = self.pdb_store.get_offset_r("_EPROCESS.ImageFileName")?;
|
||||
//
|
||||
// let mut ptr = ps_active_head;
|
||||
// self.deref_addr((ptr + flink_offset).get(), &mut ptr);
|
||||
//
|
||||
// let mut result: Vec<EprocessPoolChunk> = Vec::new();
|
||||
// while ptr != ps_active_head {
|
||||
// let mut image_name = [0u8; 15];
|
||||
// let eprocess = ptr - eprocess_link_offset;
|
||||
// self.deref_addr(eprocess + eprocess_name_offset, &mut image_name);
|
||||
// match std::str::from_utf8(&image_name) {
|
||||
// Ok(n) => {
|
||||
// result.push(EprocessPoolChunk {
|
||||
// pool_addr: 0,
|
||||
// eprocess_addr: eprocess,
|
||||
// eprocess_name: n.to_string()
|
||||
// .trim_end_matches(char::from(0))
|
||||
// .to_string(),
|
||||
// create_time: 0,
|
||||
// exit_time: 0
|
||||
//
|
||||
// });
|
||||
// },
|
||||
// _ => {}
|
||||
// };
|
||||
// self.deref_addr(ptr + flink_offset, &mut ptr);
|
||||
// }
|
||||
// Ok(result)
|
||||
// }
|
||||
|
||||
pub fn scan_pool<F>(&self, tag: &[u8; 4], expected_struct: &str, mut handler: F) -> BoxResult<bool>
|
||||
where F: FnMut(Address, &[u8], Address) -> BoxResult<bool>
|
||||
// F(Pool Address, Pool Header Data, Pool Data Address)
|
||||
// TODO: Pool Header as a real struct
|
||||
{
|
||||
// TODO: scan large pool
|
||||
// TODO: make generator, in hold: https://github.com/rust-lang/rust/issues/43122
|
||||
// Making this function a generator will turn the call to a for loop
|
||||
// https://docs.rs/gen-iter/0.2.0/gen_iter/
|
||||
@ -161,7 +141,8 @@ impl DriverState {
|
||||
let ntosbase = self.get_kernel_base();
|
||||
let [start_address, end_address] = self.get_nonpaged_range(&ntosbase)?;
|
||||
|
||||
println!("kernel base: {}; non-paged pool (start, end): ({}, {})", ntosbase, start_address, end_address);
|
||||
println!("kernel base: {}; non-paged pool (start, end): ({}, {}); tag: {:?} {}",
|
||||
ntosbase, start_address, end_address, tag, expected_struct);
|
||||
|
||||
let mut ptr = start_address;
|
||||
while ptr < end_address {
|
||||
@ -191,7 +172,7 @@ impl DriverState {
|
||||
}
|
||||
|
||||
let data_addr = Address::from_base(pool_addr.address() + pool_header_size);
|
||||
let success = handler(pool_addr, &header, data_addr)?;
|
||||
let success = handler(pool_addr, &header, data_addr).unwrap_or(false);
|
||||
if success {
|
||||
ptr += chunk_size; // skip this chunk
|
||||
}
|
||||
|
68
src/lib.rs
68
src/lib.rs
@ -121,7 +121,10 @@ fn get_device_type(typ: u32) -> String {
|
||||
|
||||
pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
driver.scan_pool(b"Proc", "_EPROCESS", |pool_addr, header, data_addr| {
|
||||
let tag =
|
||||
if driver.use_old_tag() { b"Pro\xe3" }
|
||||
else { b"Proc" };
|
||||
driver.scan_pool(tag, "_EPROCESS", |pool_addr, header, data_addr| {
|
||||
let chunk_size = (header[2] as u64) * 16u64;
|
||||
|
||||
let eprocess_size = driver.pdb_store.get_offset_r("_EPROCESS.struct_size")?;
|
||||
@ -142,14 +145,11 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
}
|
||||
|
||||
let eprocess_ptr = &try_eprocess_ptr;
|
||||
|
||||
println!("EPROCESS: 0x{:x}", eprocess_ptr.address());
|
||||
|
||||
let pid: u64 = driver.decompose(eprocess_ptr, "_EPROCESS.UniqueProcessId")?;
|
||||
let ppid: u64 = driver.decompose(eprocess_ptr, "_EPROCESS.InheritedFromUniqueProcessId")?;
|
||||
let image_name: Vec<u8> = driver.decompose_array(eprocess_ptr, "_EPROCESS.ImageFileName", 15)?;
|
||||
let unicode_str_ptr = driver.address_of(eprocess_ptr, "_EPROCESS.ImageFilePointer.FileName")
|
||||
.unwrap_or(0); // ImageFilePointer is Windows 10+
|
||||
.unwrap_or(0); // ImageFilePointer is after Windows 10 Anniversary
|
||||
|
||||
let eprocess_name =
|
||||
if let Ok(name) = from_utf8(&image_name) {
|
||||
@ -177,7 +177,10 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
pub fn scan_file(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
driver.scan_pool(b"File", "_FILE_OBJECT", |pool_addr, header, data_addr| {
|
||||
let tag =
|
||||
if driver.use_old_tag() { b"Fil\xe5" }
|
||||
else { b"File" };
|
||||
driver.scan_pool(tag, "_FILE_OBJECT", |pool_addr, header, data_addr| {
|
||||
let chunk_size = (header[2] as u64) * 16u64;
|
||||
|
||||
let fob_size = driver.pdb_store.get_offset_r("_FILE_OBJECT.struct_size")?;
|
||||
@ -246,14 +249,23 @@ pub fn scan_file(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
driver.scan_pool(b"Thre", "_ETHREAD", |pool_addr, header, data_addr| {
|
||||
let tag =
|
||||
if driver.use_old_tag() { b"Thr\xe5" }
|
||||
else { b"Thre" };
|
||||
driver.scan_pool(tag, "_ETHREAD", |pool_addr, header, data_addr| {
|
||||
let chunk_size = (header[2] as u64) * 16u64;
|
||||
|
||||
let object_header_size = driver.pdb_store.get_offset_r("_OBJECT_HEADER.struct_size")?;
|
||||
let header_size = driver.pdb_store.get_offset_r("_POOL_HEADER.struct_size")?;
|
||||
let ethread_size = driver.pdb_store.get_offset_r("_ETHREAD.struct_size")?;
|
||||
let ethread_valid_start = &data_addr;
|
||||
let ethread_valid_end = (pool_addr.clone() + chunk_size) - ethread_size;
|
||||
let mut try_ethread_ptr = ethread_valid_start.clone();
|
||||
|
||||
if chunk_size == header_size + object_header_size + ethread_size {
|
||||
try_ethread_ptr = ethread_valid_end.clone();
|
||||
}
|
||||
else {
|
||||
while try_ethread_ptr <= ethread_valid_end {
|
||||
let create_time: u64 = driver.decompose(&try_ethread_ptr, "_ETHREAD.CreateTime")?;
|
||||
if driver.windows_ffi.valid_process_time(create_time) {
|
||||
@ -264,12 +276,14 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
if try_ethread_ptr > ethread_valid_end {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
let ethread_ptr = &try_ethread_ptr;
|
||||
|
||||
let pid: u64 = driver.decompose(ethread_ptr, "_ETHREAD.Cid.UniqueProcess")?;
|
||||
let tid: u64 = driver.decompose(ethread_ptr, "_ETHREAD.Cid.UniqueThread")?;
|
||||
let unicode_str_ptr: u64 = driver.address_of(ethread_ptr, "_ETHREAD.ThreadName")?;
|
||||
let unicode_str_ptr: u64 = driver.address_of(ethread_ptr, "_ETHREAD.ThreadName")
|
||||
.unwrap_or(0); // ThreadName is after Windows 10 Anniversary
|
||||
|
||||
let thread_name =
|
||||
if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) {
|
||||
@ -300,7 +314,10 @@ pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let ntosbase = driver.get_kernel_base();
|
||||
let [start, end] = driver.get_nonpaged_range(&ntosbase)?;
|
||||
|
||||
driver.scan_pool(b"Muta", "_KMUTANT", |pool_addr, header, data_addr| {
|
||||
let tag =
|
||||
if driver.use_old_tag() { b"Mut\xe1" }
|
||||
else { b"Muta" };
|
||||
driver.scan_pool(tag, "_KMUTANT", |pool_addr, header, data_addr| {
|
||||
let chunk_size = (header[2] as u64) * 16u64;
|
||||
|
||||
let kmutant_size = driver.pdb_store.get_offset_r("_KMUTANT.struct_size")?;
|
||||
@ -353,7 +370,10 @@ pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
driver.scan_pool(b"Driv", "_DRIVER_OBJECT", |pool_addr, header, data_addr| {
|
||||
let tag =
|
||||
if driver.use_old_tag() { b"Dri\xf6" }
|
||||
else { b"Driv" };
|
||||
driver.scan_pool(tag, "_DRIVER_OBJECT", |pool_addr, header, data_addr| {
|
||||
let chunk_size = (header[2] as u64) * 16u64;
|
||||
|
||||
let dob_size = driver.pdb_store.get_offset_r("_DRIVER_OBJECT.struct_size")?;
|
||||
@ -447,15 +467,15 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
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| {
|
||||
driver.scan_pool(b"MmLd", "_LDR_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 dllbase: u64 = driver.decompose(mod_addr, "_LDR_DATA_TABLE_ENTRY.DllBase")?;
|
||||
let entry: u64 = driver.decompose(mod_addr, "_LDR_DATA_TABLE_ENTRY.EntryPoint")?;
|
||||
let size: u64 = driver.decompose(mod_addr, "_LDR_DATA_TABLE_ENTRY.SizeOfImage")?;
|
||||
let fullname_ptr = driver.address_of(mod_addr, "_LDR_DATA_TABLE_ENTRY.FullDllName")?;
|
||||
let basename_ptr = driver.address_of(mod_addr, "_LDR_DATA_TABLE_ENTRY.BaseDllName")?;
|
||||
|
||||
let fullname = driver.get_unicode_string(fullname_ptr)
|
||||
.unwrap_or("".to_string());
|
||||
@ -464,7 +484,7 @@ pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
result.push(json!({
|
||||
"pool": format!("0x{:x}", pool_addr.address()),
|
||||
"address": format!("0x{:x}", mod_addr.address()),
|
||||
"type": "_KLDR_DATA_TABLE_ENTRY",
|
||||
"type": "_LDR_DATA_TABLE_ENTRY",
|
||||
"dllbase": format!("0x{:x}", dllbase),
|
||||
"entry": format!("0x{:x}", entry),
|
||||
"size": format!("0x{:x}", size),
|
||||
@ -487,11 +507,11 @@ pub fn traverse_loadedmodulelist(driver: &DriverState) -> BoxResult<Vec<Value>>
|
||||
while ptr != module_list_head.address() {
|
||||
let mod_addr = Address::from_base(ptr);
|
||||
|
||||
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 dllbase: u64 = driver.decompose(&mod_addr, "_LDR_DATA_TABLE_ENTRY.DllBase")?;
|
||||
let entry: u64 = driver.decompose(&mod_addr, "_LDR_DATA_TABLE_ENTRY.EntryPoint")?;
|
||||
let size: u64 = driver.decompose(&mod_addr, "_LDR_DATA_TABLE_ENTRY.SizeOfImage")?;
|
||||
let fullname_ptr = driver.address_of(&mod_addr, "_LDR_DATA_TABLE_ENTRY.FullDllName")?;
|
||||
let basename_ptr = driver.address_of(&mod_addr, "_LDR_DATA_TABLE_ENTRY.BaseDllName")?;
|
||||
|
||||
let fullname = driver.get_unicode_string(fullname_ptr)
|
||||
.unwrap_or("".to_string());
|
||||
@ -499,7 +519,7 @@ pub fn traverse_loadedmodulelist(driver: &DriverState) -> BoxResult<Vec<Value>>
|
||||
.unwrap_or("".to_string());
|
||||
result.push(json!({
|
||||
"address": format!("0x{:x}", mod_addr.address()),
|
||||
"type": "_KLDR_DATA_TABLE_ENTRY",
|
||||
"type": "_LDR_DATA_TABLE_ENTRY",
|
||||
"dllbase": format!("0x{:x}", dllbase),
|
||||
"entry": format!("0x{:x}", entry),
|
||||
"size": format!("0x{:x}", size),
|
||||
@ -507,7 +527,7 @@ pub fn traverse_loadedmodulelist(driver: &DriverState) -> BoxResult<Vec<Value>>
|
||||
"BaseName": basename
|
||||
}));
|
||||
|
||||
ptr = driver.decompose(&mod_addr, "_KLDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink")?;
|
||||
ptr = driver.decompose(&mod_addr, "_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink")?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
@ -27,7 +27,7 @@ use winapi::um::winreg::{RegCreateKeyExA, RegSetValueExA, RegCloseKey, HKEY_LOCA
|
||||
const STR_DRIVER_REGISTRY_PATH: &str = "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\lpus";
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||
pub enum WindowsVersion {
|
||||
Windows7,
|
||||
Windows8,
|
||||
@ -42,6 +42,23 @@ pub enum WindowsVersion {
|
||||
WindowsUnknown
|
||||
}
|
||||
|
||||
impl WindowsVersion {
|
||||
pub fn not_supported(self) -> bool {
|
||||
match self {
|
||||
WindowsVersion::Windows10Legacy |
|
||||
WindowsVersion::Windows10_2015 |
|
||||
WindowsVersion::Windows10_2016 |
|
||||
WindowsVersion::Windows10_2017 |
|
||||
WindowsVersion::Windows8 |
|
||||
WindowsVersion::WindowsUnknown => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
pub fn is_supported(self) -> bool {
|
||||
!self.not_supported()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct WindowsFFI {
|
||||
|
Loading…
Reference in New Issue
Block a user