Update scan algorithm

- Scan _ETHREAD with PoolTag='Thre'
- Parse pid/ppid from _EPROCESS
- Build process tree from output log
- Static link for machine missing Windows C++ dev environment
This commit is contained in:
2020-06-09 04:13:15 +07:00
parent 8c642f6ba0
commit 72a947ccd7
6 changed files with 329 additions and 19 deletions

View File

@ -34,9 +34,11 @@ fn main() -> Result<(), Box<dyn Error>> {
let eprocess_size = driver.pdb_store.get_offset_r("_EPROCESS.struct_size")?;
let eprocess_name_offset = driver.pdb_store.get_offset_r("_EPROCESS.ImageFileName")?;
let eprocess_create_time_offset = driver.pdb_store.get_offset_r("_EPROCESS.CreateTime")?;
let fob_filename_offset = driver.pdb_store.get_offset_r("_FILE_OBJECT.FileName")?;
let eprocess_image_file_ptr_offset = driver.pdb_store.get_offset_r("_EPROCESS.ImageFilePointer")?;
let eprocess_image_file_offset = driver.pdb_store.get_offset_r("_EPROCESS.ImageFilePointer")?;
let eprocess_pid_offset = driver.pdb_store.get_offset_r("_EPROCESS.UniqueProcessId")?;
let eprocess_ppid_offset = driver.pdb_store.get_offset_r("_EPROCESS.InheritedFromUniqueProcessId")?;
// let eprocess_exit_time_offset = driver.pdb_store.get_offset_r("_EPROCESS.ExitTime")?;
let fob_filename_offset = driver.pdb_store.get_offset_r("_FILE_OBJECT.FileName")?;
let eprocess_valid_start = data_addr;
let eprocess_valid_end = (pool_addr + chunk_size) - eprocess_size;
@ -57,25 +59,34 @@ fn main() -> Result<(), Box<dyn Error>> {
return Ok(false);
}
let eprocess_ptr = try_eprocess_ptr;
let mut image_name = [0u8; 15];
let mut file_object_ptr = 0u64;
let mut image_file_ptr = 0u64;
let mut ppid = 0u64;
let mut pid = 0u64;
driver.deref_addr(try_eprocess_ptr + eprocess_name_offset, &mut image_name);
driver.deref_addr(try_eprocess_ptr + eprocess_image_file_ptr_offset, &mut file_object_ptr);
let filename = if file_object_ptr != 0 { driver.get_unicode_string(file_object_ptr + fob_filename_offset, true)? }
else { "".to_string() };
driver.deref_addr(eprocess_ptr + eprocess_ppid_offset, &mut ppid);
driver.deref_addr(eprocess_ptr + eprocess_pid_offset, &mut pid);
if let Ok(name) = from_utf8(&image_name) {
let eprocess_name = name
.to_string()
.trim_end_matches(char::from(0))
.to_string();
println!("pool: 0x{:x} | eprocess: 0x{:x} | {} | {}", pool_addr, try_eprocess_ptr, filename, eprocess_name);
}
else {
println!("pool: 0x{:x} | eprocess: 0x{:x} | {} | {:?}", pool_addr, try_eprocess_ptr, filename, image_name);
}
Ok(true)
driver.deref_addr(eprocess_ptr + eprocess_name_offset, &mut image_name);
driver.deref_addr(eprocess_ptr + eprocess_image_file_offset, &mut image_file_ptr);
let binary_path =
if image_file_ptr != 0 {
driver.get_unicode_string(image_file_ptr + fob_filename_offset, true)?
} else {
"".to_string()
};
let eprocess_name =
if let Ok(name) = from_utf8(&image_name) {
name.to_string().trim_end_matches(char::from(0)).to_string()
} else {
"".to_string()
};
println!("pool: 0x{:x} | eprocess: 0x{:x} | pid: {} | ppid: {} | name: {} | path: {}",
pool_addr, eprocess_ptr, pid, ppid, eprocess_name, binary_path);
// eprocess_list.push(EprocessPoolChunk {
// pool_addr,
// eprocess_addr: try_eprocess_ptr,
@ -83,6 +94,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// create_time: to_epoch(create_time),
// exit_time: to_epoch(exit_time)
// });
Ok(true)
})?;
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());

78
src/bin/ethread_scan.rs Normal file
View File

@ -0,0 +1,78 @@
use std::error::Error;
use std::str::{from_utf8};
use chrono::Utc;
use chrono::{DateTime};
use std::time::{UNIX_EPOCH, Duration};
use lpus::{
driver_state::{DriverState /* , EprocessPoolChunk */}
};
#[allow(dead_code)]
fn to_str_time(time_ms: u64) -> String {
if time_ms == 0 {
return "".to_string();
}
let d = UNIX_EPOCH + Duration::from_millis(time_ms);
let datetime = DateTime::<Utc>::from(d);
let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S.%f").to_string();
timestamp_str
}
fn main() -> Result<(), Box<dyn Error>> {
// for windows admin require
// https://github.com/nabijaczleweli/rust-embed-resource
let mut driver = DriverState::new();
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
// let ethread_scan_head = driver.scan_active_head(ntosbase)?;
// let mut ethread_list: Vec<EprocessPoolChunk> = Vec::new();
driver.scan_pool(b"Thre", |pool_addr, header, data_addr| {
let chunk_size = (header[2] as u64) * 16u64;
let ethread_size = driver.pdb_store.get_offset_r("_ETHREAD.struct_size")?;
let ethread_create_time_offset = driver.pdb_store.get_offset_r("_ETHREAD.CreateTime")?;
let ethread_name_offset = driver.pdb_store.get_offset_r("_ETHREAD.ThreadName")?;
// let ethread_exit_time_offset = driver.pdb_store.get_offset_r("_ETHREAD.ExitTime")?;
let ethread_valid_start = data_addr;
let ethread_valid_end = (pool_addr + chunk_size) - ethread_size;
let mut try_ethread_ptr = ethread_valid_start;
let mut create_time = 0u64;
// let mut exit_time = 0u64;
while try_ethread_ptr <= ethread_valid_end {
driver.deref_addr(try_ethread_ptr + ethread_create_time_offset, &mut create_time);
// driver.deref_addr(try_ethread_ptr + ethread_exit_time_offset, &mut exit_time);
// using heuristics to eliminate false positive
if driver.windows_ffi.valid_process_time(create_time) {
break;
}
try_ethread_ptr += 0x4; // search exhaustively
}
if try_ethread_ptr > ethread_valid_end {
return Ok(false);
}
let mut thread_name_ptr = 0u64;
driver.deref_addr(try_ethread_ptr + ethread_name_offset, &mut thread_name_ptr);
let thread_name = if thread_name_ptr != 0 { driver.get_unicode_string(thread_name_ptr, true)? }
else { "".to_string() };
println!("pool: 0x{:x} | ethread: 0x{:x} | {}", pool_addr, try_ethread_ptr, thread_name);
Ok(true)
// ethread_list.push(EprocessPoolChunk {
// pool_addr,
// ethread_addr: try_ethread_ptr,
// ethread_name: ethread_name,
// create_time: to_epoch(create_time),
// exit_time: to_epoch(exit_time)
// });
})?;
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
Ok(())
}

View File

@ -203,6 +203,11 @@ impl DriverState {
let minimum_data_size = eprocess_size + pool_header_size;
Ok(minimum_data_size)
}
else if tag == b"Thre" {
let ethread_size = self.pdb_store.get_offset_r("_EPROCESS.struct_size")?;
let minimum_data_size = ethread_size + pool_header_size;
Ok(minimum_data_size)
}
else if tag == b"File" {
let file_object_size = self.pdb_store.get_offset_r("_FILE_OBJECT.struct_size")?;
let minimum_data_size = file_object_size + pool_header_size;
@ -290,7 +295,8 @@ impl DriverState {
Ok([first_va, last_va])
},
WindowsVersion::Windows10_2019 => {
WindowsVersion::Windows10_2019 |
WindowsVersion::Windows10_2018 => {
let mistate = ntosbase + self.pdb_store.get_offset_r("MiState")?;
let system_node_ptr = self.pdb_store.addr_decompose(
mistate, "_MI_SYSTEM_INFORMATION.Hardware.SystemNodeInformation")?;