From cbc3cb7e15665468e20681eb8af5310436f1c95d Mon Sep 17 00:00:00 2001 From: nganhkhoa Date: Mon, 4 May 2020 11:40:31 +0000 Subject: [PATCH] update new design in code call, no test build --- Cargo.lock | 31 +++++ Cargo.toml | 1 + src/driver_state.rs | 268 +++++++++++++++++------------------------- src/ioctl_protocol.rs | 12 +- src/main.rs | 120 +++++++++++++++---- 5 files changed, 245 insertions(+), 187 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b777d89..51d9981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,6 +48,16 @@ name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "core-foundation" version = "0.6.4" @@ -416,6 +426,23 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num_cpus" version = "1.12.0" @@ -459,6 +486,7 @@ dependencies = [ name = "parse_pdb_for_offsets" version = "0.1.0" dependencies = [ + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "pdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1081,6 +1109,7 @@ dependencies = [ "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" @@ -1125,6 +1154,8 @@ dependencies = [ "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" "checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" diff --git a/Cargo.toml b/Cargo.toml index 16ac852..4fa6068 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] hex = "0.4.2" pdb = "0.5.0" +chrono = "0.4" widestring = "0.4.0" winapi = { version = "0.3.8", features = ["libloaderapi", "processthreadsapi", "winbase", "securitybaseapi", "handleapi", "winnt", "winreg", "fileapi", "ioapiset", "winioctl", "errhandlingapi", "sysinfoapi"] } reqwest = { version = "0.10.1", features = ["blocking"] } diff --git a/src/driver_state.rs b/src/driver_state.rs index 43984d0..d6b38d7 100644 --- a/src/driver_state.rs +++ b/src/driver_state.rs @@ -17,6 +17,15 @@ use crate::ioctl_protocol::{ const SIOCTL_TYPE: DWORD = 40000; +fn to_epoch(filetime: u64) -> u64 { + let windows_epoch_diff: u64 = 11644473600000 * 10000; + if filetime < windows_epoch_diff { + return 0; + } + let process_time_epoch: u64 = (filetime - windows_epoch_diff) / 10000; + process_time_epoch +} + #[allow(dead_code)] #[derive(Debug)] pub enum DriverAction { @@ -47,7 +56,9 @@ impl DriverAction { pub struct EprocessPoolChunk { pub pool_addr: u64, pub eprocess_addr: u64, - pub eprocess_name: String + pub eprocess_name: String, + pub create_time: u64, + pub exit_time: u64 } impl PartialEq for EprocessPoolChunk { @@ -58,12 +69,8 @@ impl PartialEq for EprocessPoolChunk { #[allow(dead_code)] pub struct DriverState { - pdb_store: PdbStore, + pub pdb_store: PdbStore, windows_ffi: WindowsFFI, - ntosbase: u64, - nonpaged_range: [u64; 2], - pub eprocess_traverse_result: Vec, - pub pool_scan_result: Vec } impl DriverState { @@ -82,156 +89,80 @@ impl DriverState { pub fn startup(&mut self) -> NTSTATUS { self.windows_ffi.load_driver() + let mut input = InputData { + offset_value: OffsetData::new(&self.pdb_store, self.windows_ffi.short_version) + }; + self.windows_ffi.device_io(code, &mut input, &mut Nothing); } pub fn shutdown(&self) -> NTSTATUS { self.windows_ffi.unload_driver() } - // TODO: Function output and input data???? - pub fn interact(&mut self, action: DriverAction) { - let code = action.get_code(); - println!("Driver action: {:?}", action); - match action { - DriverAction::SetupOffset => { - let mut input = InputData { - offset_value: OffsetData::new(&self.pdb_store, self.windows_ffi.short_version) - }; - self.windows_ffi.device_io(code, &mut input, &mut Nothing); - }, - DriverAction::GetKernelBase => { - self.windows_ffi.device_io(code, &mut Nothing, &mut self.ntosbase); - println!("ntosbase: 0x{:x}", self.ntosbase); - }, - DriverAction::ScanPsActiveHead => { - self.interact(DriverAction::GetKernelBase); - let ps_active_head = self.ntosbase + self.pdb_store.get_offset("PsActiveProcessHead").unwrap_or(0u64); - let flink_offset = self.pdb_store.get_offset("_LIST_ENTRY.Flink").unwrap_or(0u64); - let eprocess_link_offset = self.pdb_store.get_offset("_EPROCESS.ActiveProcessLinks").unwrap_or(0u64); - let eprocess_name_offset = self.pdb_store.get_offset("_EPROCESS.ImageFileName").unwrap_or(0u64); - - let mut ptr = ps_active_head; - self.deref_addr(ptr + flink_offset, &mut ptr); - - // println!("========================"); - // println!("Scan PsActiveProcessHead"); - 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) => { - // TODO: save to somewhere - // println!("_EPROCESS at 0x{:x} of {}", eprocess, n); - self.eprocess_traverse_result.push(EprocessPoolChunk { - pool_addr: 0, - eprocess_addr: eprocess, - eprocess_name: n.to_string().trim_end_matches(char::from(0)) - .to_string() - - }); - }, - _ => {} - }; - self.deref_addr(ptr + flink_offset, &mut ptr); - } - // println!("========================"); - - // test call to check result - self.windows_ffi.device_io(code, &mut Nothing, &mut Nothing); - }, - DriverAction::ScanPool => { - self.get_nonpaged_range(); - let mut input = InputData { - scan_range: ScanRange::new(&self.nonpaged_range) - }; - self.windows_ffi.device_io(code, &mut input, &mut Nothing); - }, - DriverAction::ScanPoolRemote => { - self.get_nonpaged_range(); - let start_address = self.nonpaged_range[0]; - let end_address = self.nonpaged_range[1]; - - let pool_header_size = self.pdb_store.get_offset("_POOL_HEADER.struct_size").unwrap_or(0u64); - let eprocess_name_offset = self.pdb_store.get_offset("_EPROCESS.ImageFileName").unwrap_or(0u64); - let eprocess_create_time_offset = self.pdb_store.get_offset("_EPROCESS.CreateTime").unwrap_or(0u64); - let eprocess_size = self.pdb_store.get_offset("_EPROCESS.struct_size").unwrap_or(0u64); - - let mut ptr = start_address; - while ptr < end_address { - let mut input = InputData { - scan_range: ScanRange::new(&[ptr, end_address]) - }; - self.windows_ffi.device_io(code, &mut input, &mut ptr); - if ptr >= end_address { - break; - } - let pool_addr = ptr; - ptr += pool_header_size; - - let mut pool = vec![0u8; pool_header_size as usize]; - self.deref_addr_ptr(pool_addr, pool.as_mut_ptr(), pool_header_size); - // TODO: Use pdb to parse, bit mangling and stuff - // println!("========================="); - // println!("Pool at 0x{:x}", pool_addr); - // println!("Previos Size: 0x{:x}", pool[0]); - // println!("Pool index : {:x}", pool[1]); - // println!("Block size : 0x{:x}", (pool[2] as u64) * 16u64); // CHUNK_SIZE = 16 - // println!("Pool type : {}", pool[3]); - // println!("Pool tag : {}", std::str::from_utf8(&pool[4..8]).unwrap()); - - let pool_size = (pool[2] as u64) * 16u64; - let eprocess_valid_start = pool_addr + pool_header_size; - let eprocess_valid_end = pool_addr + pool_size - eprocess_size; - let mut found_valid = false; - let mut try_eprocess_ptr = eprocess_valid_start; - - while !found_valid || try_eprocess_ptr < eprocess_valid_end { - let mut create_time = 0u64; - self.deref_addr(try_eprocess_ptr + eprocess_create_time_offset, &mut create_time); - if self.windows_ffi.valid_process_time(create_time) { - found_valid = true; - let mut image_name = [0u8; 15]; - self.deref_addr(try_eprocess_ptr + eprocess_name_offset, &mut image_name); - // println!("_EPROCESS at 0x{:x} of {}", - // try_eprocess_ptr, std::str::from_utf8(&image_name).unwrap()); - // TODO: save result - self.pool_scan_result.push(EprocessPoolChunk { - pool_addr, - eprocess_addr: try_eprocess_ptr, - eprocess_name: std::str::from_utf8(&image_name).unwrap() - .to_string().trim_end_matches(char::from(0)) - .to_string() - }); - break; - } - try_eprocess_ptr += 0x4; // search exhaustively - } - if !found_valid { - println!("Not an eprocess maybe"); - } - } - }, - DriverAction::HideProcess => { - let s = String::from("notepad.exe"); - let s_bytes = s.as_bytes(); - let mut name = [0u8; 15]; - for i in 0..s.len() { - name[i] = s_bytes[i]; - }; - let mut input = InputData { - hide_process: HideProcess { - name, - size: s.len() as u64 - } - }; - self.windows_ffi.device_io(code, &mut input, &mut Nothing); - } - _ => {} - }; + pub fn get_kernel_base(&self) -> Result { + let mut ntosbase = 0u64; + self.windows_ffi.device_io(DriverAction::GetKernelBase.get_code(), + &mut Nothing, &mut ntosbase); + // println!("ntosbase: 0x{:x}", self.ntosbase); + Ok(ntosbase) } - fn deref_addr(&self, addr: u64, outbuf: &mut T) { + pub fn scan_active_head(&self, ntosbase: u64) -> Result, io::Error> { + let ps_active_head = ntosbase + self.pdb_store.get_offset("PsActiveProcessHead"); + let flink_offset = self.pdb_store.get_offset("_LIST_ENTRY.Flink"); + let eprocess_link_offset = self.pdb_store.get_offset("_EPROCESS.ActiveProcessLinks"); + let eprocess_name_offset = self.pdb_store.get_offset("_EPROCESS.ImageFileName"); + + let mut ptr = ps_active_head; + self.deref_addr(ptr + flink_offset, &mut ptr); + + let mut result: Vec; + 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(&self, ntosbase: u64, tag: [u8; 4], + handler: FnMut(&DriverState, u64) -> Result + ) -> Result { + let range = self.get_nonpaged_range(ntosbase); + let start_address = range[0]; + let end_address = range[1]; + let mut ptr = start_address; + while ptr < end_address { + let mut input = InputData { + scan_range: ScanPoolData::new(&[ptr, end_address], tag) + }; + self.windows_ffi.device_io(code, &mut input, &mut ptr); + if ptr >= end_address { + break; + } + handler(&self, ptr)?; + ptr += pool_header_size; + } + Ok(true) + } + + pub fn deref_addr(&self, addr: u64, outbuf: &mut T) { let code = DriverAction::DereferenceAddress.get_code(); let size: usize = size_of_val(outbuf); let mut input = InputData { @@ -244,7 +175,7 @@ impl DriverState { self.windows_ffi.device_io(code, &mut input, outbuf); } - fn deref_addr_ptr(&self, addr: u64, outptr: *mut T, output_len: u64) { + pub fn deref_addr_ptr(&self, addr: u64, outptr: *mut T, output_len: u64) { let code = DriverAction::DereferenceAddress.get_code(); let mut input = InputData { deref_addr: DerefAddr { @@ -257,15 +188,29 @@ impl DriverState { outptr as *mut c_void, output_len as DWORD); } - #[allow(dead_code)] - fn get_nonpaged_range(&mut self) { + pub fn get_unicode_string(&self, unicode_str_addr: u64) -> Result<&str, io::Error> { + let mut strlen: u16; + let mut bufaddr : u64; + let buffer_ptr = unicode_str_addr + self.pdb_store.get_offset("_UNICODE_STRING.Buffer")?; + + self.defer_addr(unicode_str_addr, &mut strlen); + self.defer_addr(buffer_ptr, &mut bufaddr); + + let mut buf = vec![0u8; strlen as usize]; + dr.deref_addr_ptr(bufaddr, buf.as_mut_ptr(), strlen); + + prinln!("unicode string {?}", buf); + + Ok(str::from_utf8(&buf)?) + } + + pub fn get_nonpaged_range(&self, ntosbase: u64) -> Result<[u64; 2], io::Error> { // TODO: Add support for other Windows version here match self.windows_ffi.short_version { WindowsVersion::Windows10FastRing => { - let mistate = self.ntosbase + self.pdb_store.get_offset("MiState").unwrap_or(0u64); + let mistate = ntosbase + self.pdb_store.get_offset("MiState")?; let system_node_ptr = self.pdb_store.addr_decompose( - mistate, "_MI_SYSTEM_INFORMATION.Hardware.SystemNodeNonPagedPool") - .unwrap_or(0u64); + mistate, "_MI_SYSTEM_INFORMATION.Hardware.SystemNodeNonPagedPool")?; let mut system_node_addr = 0u64; self.deref_addr(system_node_ptr, &mut system_node_addr); @@ -273,19 +218,20 @@ impl DriverState { let mut last_va = 0u64; self.deref_addr( system_node_addr + self.pdb_store.get_offset( - "_MI_SYSTEM_NODE_NONPAGED_POOL.NonPagedPoolFirstVa").unwrap_or(0u64), + "_MI_SYSTEM_NODE_NONPAGED_POOL.NonPagedPoolFirstVa")?, &mut first_va); self.deref_addr( system_node_addr + self.pdb_store.get_offset( - "_MI_SYSTEM_NODE_NONPAGED_POOL.NonPagedPoolLastVa").unwrap_or(0u64), + "_MI_SYSTEM_NODE_NONPAGED_POOL.NonPagedPoolLastVa")?, &mut last_va); - self.nonpaged_range[0] = first_va; - self.nonpaged_range[1] = last_va; + Ok([first_va, last_va]) } - _ => {} - }; - println!("Nonpaged pool range: 0x{:x} - 0x{:x}", self.nonpaged_range[0], self.nonpaged_range[1]); + _ => { + Err("Windows version for nonpaged pool algorithm is not implemented") + } + } } + } diff --git a/src/ioctl_protocol.rs b/src/ioctl_protocol.rs index 22bbf99..8e3c17a 100644 --- a/src/ioctl_protocol.rs +++ b/src/ioctl_protocol.rs @@ -64,16 +64,18 @@ pub struct DerefAddr { #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct ScanRange { +pub struct ScanPoolData { pub start: u64, - pub end: u64 + pub end: u64, + pub tag: [u8; 4] } -impl ScanRange { - pub fn new(arr: &[u64; 2]) -> Self { +impl ScanPoolData{ + pub fn new(arr: &[u64; 2], tag: &[u8; 4]) -> Self { Self { start: arr[0], - end: arr[1] + end: arr[1], + tag: tag } } } diff --git a/src/main.rs b/src/main.rs index 7fbd2e3..a951247 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,121 @@ +extern crate chrono; + mod pdb_store; mod windows; mod ioctl_protocol; mod driver_state; +use chrono::prelude::DateTime; +use chrono::Utc; +use chrono::{Local, DateTime}; +use std::time::{SystemTime, UNIX_EPOCH, Duration}; + use pdb_store::parse_pdb; use windows::WindowsFFI; use driver_state::{DriverState, DriverAction}; -fn main() { +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::::from(d); + let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S.%f").to_string(); + timestamp_str +} + +fn main() -> Result<(), io::Error> { // for windows admin require // https://github.com/nabijaczleweli/rust-embed-resource let mut driver = DriverState::new(parse_pdb(), WindowsFFI::new()); - println!("NtLoadDriver() -> 0x{:x}", driver.startup()); - driver.interact(DriverAction::SetupOffset); - driver.interact(DriverAction::GetKernelBase); + let ntosbase = driver.get_ntosbase()?; + let pool_header_size = driver.pdb_store.get_offset("_POOL_HEADER.struct_size")?; - driver.interact(DriverAction::HideProcess); + let eprocess_tag: [u8; 4] = [80, 114, 111, 99]; // Proc + let eprocess_name_offset = driver.pdb_store.get_offset("_EPROCESS.ImageFileName")?; + let eprocess_create_time_offset = driver.pdb_store.get_offset("_EPROCESS.CreateTime")?; + let eprocess_exit_time_offset = driver.pdb_store.get_offset("_EPROCESS.ExitTime")?; + let eprocess_size = driver.pdb_store.get_offset("_EPROCESS.struct_size")?; - driver.interact(DriverAction::ScanPsActiveHead); - driver.interact(DriverAction::ScanPoolRemote); + let eprocess_scan_head = driver.scan_active_head(ntosbase)?; + let mut eprocess_list: Vec; + driver.scan_pool(ntosbase, eprocess_tag, |dr, pool_addr| { + let mut pool = vec![0u8; pool_header_size as usize]; + dr.deref_addr_ptr(pool_addr, pool.as_mut_ptr(), pool_header_size); - println!("PsActiveProcessHead traversal"); - println!("- [is in scan list?] eprocess_addr eprocess_name"); - for result in &driver.eprocess_traverse_result { - println!("- [{}] 0x{:x} {}", - driver.pool_scan_result.contains(&result), - result.eprocess_addr, result.eprocess_name); - } + let pool_size = (pool[2] as u64) * 16u64; + let eprocess_valid_start = pool_addr + pool_header_size; + let eprocess_valid_end = pool_addr + pool_size - eprocess_size; + let mut try_eprocess_ptr = eprocess_valid_start; - println!("Pool tag (quick) scanning"); - println!("- [is in pslist?] pool_addr eprocess_addr eprocess_name"); - for result in &driver.pool_scan_result { - println!("- [{}] 0x{:x} 0x{:x} {}", - driver.eprocess_traverse_result.contains(&result), - result.pool_addr, result.eprocess_addr, result.eprocess_name); - } + let mut create_time = 0u64; + let mut exit_time = 0u64; + while try_eprocess_ptr <= eprocess_valid_end { + dr.deref_addr(try_eprocess_ptr + eprocess_create_time_offset, &mut create_time); + dr.deref_addr(try_eprocess_ptr + eprocess_exit_time_offset, &mut exit_time); + if dr.windows_ffi.valid_process_time(create_time) { + break; + } + try_eprocess_ptr += 0x4; // search exhaustively + } + let mut image_name = [0u8; 15]; + dr.deref_addr(try_eprocess_ptr + eprocess_name_offset, &mut image_name); + let eprocess_name = std::str::from_utf8(&image_name)? + .to_string() + .trim_end_matches(char::from(0)) + .to_string(); + eprocess_list.push(EprocessPoolChunk { + pool_addr, + eprocess_addr: try_eprocess_ptr, + eprocess_name: eprocess_name, + create_time: to_epoch(create_time), + exit_time: to_epoch(exit_time) + }); + Ok(try_eprocess_ptr <= eprocess_valid_end) + }); + + let ethread_tag: [u8; 4] = [84, 104, 114, 101]; // Thre + let ethread_create_time_offset = driver.pdb_store.get_offset("_ETHREAD.CreateTime")?; + let ethread_exit_time_offset = driver.pdb_store.get_offset("_ETHREAD.ExitTime")?; + let ethread_threadname_offset = driver.pdb_store.get_offset("_ETHREAD.TheadName")?; + let ethread_size = driver.pdb_store.get_offset("_ETHREAD.struct_size")?; + + // let mut ethread_list: Vec; + driver.scan_pool(ntosbase, ethread_tag, |dr, pool_addr| { + let mut pool = vec![0u8; pool_header_size as usize]; + dr.deref_addr_ptr(pool_addr, pool.as_mut_ptr(), pool_header_size); + + let pool_size = (pool[2] as u64) * 16u64; + let ethread_valid_start = pool_addr + pool_header_size; + let ethread_valid_end = pool_addr + pool_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 { + dr.deref_addr(try_ethread_ptr + ethread_create_time_offset, &mut create_time); + dr.deref_addr(try_ethread_ptr + ethread_exit_time_offset, &mut exit_time); + if dr.windows_ffi.valid_process_time(create_time) { + break; + } + try_ethread_ptr += 0x4; // search exhaustively + } + let mut threadname_ptr = 0u64; + dr.deref_addr(try_ethread_ptr + ethread_threadname_offset, &mut threadname_ptr); + let threadname = dr.get_unicode_string(threadname_ptr)? + println!("threadname: {}", threadname); + Ok(try_ethread_ptr <= ethread_valid_end) + }); + + // for result in &driver.eprocess_traverse_result { + // println!("- [{}] 0x{:x} {}", + // driver.pool_scan_result.contains(&result), + // result.eprocess_addr, result.eprocess_name); + // } println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown()); + Ok(()) }