update new design in code call, no test build
This commit is contained in:
parent
862a5c0788
commit
cbc3cb7e15
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -48,6 +48,16 @@ name = "cfg-if"
|
|||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
@ -416,6 +426,23 @@ dependencies = [
|
|||||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
@ -459,6 +486,7 @@ dependencies = [
|
|||||||
name = "parse_pdb_for_offsets"
|
name = "parse_pdb_for_offsets"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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)",
|
"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 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 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 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 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 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"
|
"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 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 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 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 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 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"
|
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||||
|
@ -9,6 +9,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
hex = "0.4.2"
|
hex = "0.4.2"
|
||||||
pdb = "0.5.0"
|
pdb = "0.5.0"
|
||||||
|
chrono = "0.4"
|
||||||
widestring = "0.4.0"
|
widestring = "0.4.0"
|
||||||
winapi = { version = "0.3.8", features = ["libloaderapi", "processthreadsapi", "winbase", "securitybaseapi", "handleapi", "winnt", "winreg", "fileapi", "ioapiset", "winioctl", "errhandlingapi", "sysinfoapi"] }
|
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"] }
|
reqwest = { version = "0.10.1", features = ["blocking"] }
|
||||||
|
@ -17,6 +17,15 @@ use crate::ioctl_protocol::{
|
|||||||
|
|
||||||
const SIOCTL_TYPE: DWORD = 40000;
|
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)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DriverAction {
|
pub enum DriverAction {
|
||||||
@ -47,7 +56,9 @@ impl DriverAction {
|
|||||||
pub struct EprocessPoolChunk {
|
pub struct EprocessPoolChunk {
|
||||||
pub pool_addr: u64,
|
pub pool_addr: u64,
|
||||||
pub eprocess_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 {
|
impl PartialEq for EprocessPoolChunk {
|
||||||
@ -58,12 +69,8 @@ impl PartialEq for EprocessPoolChunk {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct DriverState {
|
pub struct DriverState {
|
||||||
pdb_store: PdbStore,
|
pub pdb_store: PdbStore,
|
||||||
windows_ffi: WindowsFFI,
|
windows_ffi: WindowsFFI,
|
||||||
ntosbase: u64,
|
|
||||||
nonpaged_range: [u64; 2],
|
|
||||||
pub eprocess_traverse_result: Vec<EprocessPoolChunk>,
|
|
||||||
pub pool_scan_result: Vec<EprocessPoolChunk>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DriverState {
|
impl DriverState {
|
||||||
@ -82,156 +89,80 @@ impl DriverState {
|
|||||||
|
|
||||||
pub fn startup(&mut self) -> NTSTATUS {
|
pub fn startup(&mut self) -> NTSTATUS {
|
||||||
self.windows_ffi.load_driver()
|
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 {
|
pub fn shutdown(&self) -> NTSTATUS {
|
||||||
self.windows_ffi.unload_driver()
|
self.windows_ffi.unload_driver()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Function output and input data????
|
pub fn get_kernel_base(&self) -> Result<u64, io::Error> {
|
||||||
pub fn interact(&mut self, action: DriverAction) {
|
let mut ntosbase = 0u64;
|
||||||
let code = action.get_code();
|
self.windows_ffi.device_io(DriverAction::GetKernelBase.get_code(),
|
||||||
println!("Driver action: {:?}", action);
|
&mut Nothing, &mut ntosbase);
|
||||||
match action {
|
// println!("ntosbase: 0x{:x}", self.ntosbase);
|
||||||
DriverAction::SetupOffset => {
|
Ok(ntosbase)
|
||||||
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);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref_addr<T>(&self, addr: u64, outbuf: &mut T) {
|
pub fn scan_active_head(&self, ntosbase: u64) -> Result<Vec<EprocessPoolChunk>, 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<EprocessPoolChunk>;
|
||||||
|
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<bool, io::Error>
|
||||||
|
) -> Result<bool, io::Error> {
|
||||||
|
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<T>(&self, addr: u64, outbuf: &mut T) {
|
||||||
let code = DriverAction::DereferenceAddress.get_code();
|
let code = DriverAction::DereferenceAddress.get_code();
|
||||||
let size: usize = size_of_val(outbuf);
|
let size: usize = size_of_val(outbuf);
|
||||||
let mut input = InputData {
|
let mut input = InputData {
|
||||||
@ -244,7 +175,7 @@ impl DriverState {
|
|||||||
self.windows_ffi.device_io(code, &mut input, outbuf);
|
self.windows_ffi.device_io(code, &mut input, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
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: 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 {
|
||||||
@ -257,15 +188,29 @@ impl DriverState {
|
|||||||
outptr as *mut c_void, output_len as DWORD);
|
outptr as *mut c_void, output_len as DWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
pub fn get_unicode_string(&self, unicode_str_addr: u64) -> Result<&str, io::Error> {
|
||||||
fn get_nonpaged_range(&mut self) {
|
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
|
// TODO: Add support for other Windows version here
|
||||||
match self.windows_ffi.short_version {
|
match self.windows_ffi.short_version {
|
||||||
WindowsVersion::Windows10FastRing => {
|
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(
|
let system_node_ptr = self.pdb_store.addr_decompose(
|
||||||
mistate, "_MI_SYSTEM_INFORMATION.Hardware.SystemNodeNonPagedPool")
|
mistate, "_MI_SYSTEM_INFORMATION.Hardware.SystemNodeNonPagedPool")?;
|
||||||
.unwrap_or(0u64);
|
|
||||||
let mut system_node_addr = 0u64;
|
let mut system_node_addr = 0u64;
|
||||||
self.deref_addr(system_node_ptr, &mut system_node_addr);
|
self.deref_addr(system_node_ptr, &mut system_node_addr);
|
||||||
|
|
||||||
@ -273,19 +218,20 @@ impl DriverState {
|
|||||||
let mut last_va = 0u64;
|
let mut last_va = 0u64;
|
||||||
self.deref_addr(
|
self.deref_addr(
|
||||||
system_node_addr + self.pdb_store.get_offset(
|
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);
|
&mut first_va);
|
||||||
|
|
||||||
self.deref_addr(
|
self.deref_addr(
|
||||||
system_node_addr + self.pdb_store.get_offset(
|
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);
|
&mut last_va);
|
||||||
|
|
||||||
self.nonpaged_range[0] = first_va;
|
Ok([first_va, last_va])
|
||||||
self.nonpaged_range[1] = last_va;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
};
|
Err("Windows version for nonpaged pool algorithm is not implemented")
|
||||||
println!("Nonpaged pool range: 0x{:x} - 0x{:x}", self.nonpaged_range[0], self.nonpaged_range[1]);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,16 +64,18 @@ pub struct DerefAddr {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ScanRange {
|
pub struct ScanPoolData {
|
||||||
pub start: u64,
|
pub start: u64,
|
||||||
pub end: u64
|
pub end: u64,
|
||||||
|
pub tag: [u8; 4]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScanRange {
|
impl ScanPoolData{
|
||||||
pub fn new(arr: &[u64; 2]) -> Self {
|
pub fn new(arr: &[u64; 2], tag: &[u8; 4]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: arr[0],
|
start: arr[0],
|
||||||
end: arr[1]
|
end: arr[1],
|
||||||
|
tag: tag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
120
src/main.rs
120
src/main.rs
@ -1,43 +1,121 @@
|
|||||||
|
extern crate chrono;
|
||||||
|
|
||||||
mod pdb_store;
|
mod pdb_store;
|
||||||
mod windows;
|
mod windows;
|
||||||
mod ioctl_protocol;
|
mod ioctl_protocol;
|
||||||
mod driver_state;
|
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 pdb_store::parse_pdb;
|
||||||
use windows::WindowsFFI;
|
use windows::WindowsFFI;
|
||||||
use driver_state::{DriverState, DriverAction};
|
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::<Utc>::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
|
// for windows admin require
|
||||||
// https://github.com/nabijaczleweli/rust-embed-resource
|
// https://github.com/nabijaczleweli/rust-embed-resource
|
||||||
|
|
||||||
let mut driver = DriverState::new(parse_pdb(), WindowsFFI::new());
|
let mut driver = DriverState::new(parse_pdb(), WindowsFFI::new());
|
||||||
|
|
||||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||||
|
|
||||||
driver.interact(DriverAction::SetupOffset);
|
let ntosbase = driver.get_ntosbase()?;
|
||||||
driver.interact(DriverAction::GetKernelBase);
|
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);
|
let eprocess_scan_head = driver.scan_active_head(ntosbase)?;
|
||||||
driver.interact(DriverAction::ScanPoolRemote);
|
let mut eprocess_list: Vec<EprocessPoolChunk>;
|
||||||
|
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");
|
let pool_size = (pool[2] as u64) * 16u64;
|
||||||
println!("- [is in scan list?] eprocess_addr eprocess_name");
|
let eprocess_valid_start = pool_addr + pool_header_size;
|
||||||
for result in &driver.eprocess_traverse_result {
|
let eprocess_valid_end = pool_addr + pool_size - eprocess_size;
|
||||||
println!("- [{}] 0x{:x} {}",
|
let mut try_eprocess_ptr = eprocess_valid_start;
|
||||||
driver.pool_scan_result.contains(&result),
|
|
||||||
result.eprocess_addr, result.eprocess_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Pool tag (quick) scanning");
|
let mut create_time = 0u64;
|
||||||
println!("- [is in pslist?] pool_addr eprocess_addr eprocess_name");
|
let mut exit_time = 0u64;
|
||||||
for result in &driver.pool_scan_result {
|
while try_eprocess_ptr <= eprocess_valid_end {
|
||||||
println!("- [{}] 0x{:x} 0x{:x} {}",
|
dr.deref_addr(try_eprocess_ptr + eprocess_create_time_offset, &mut create_time);
|
||||||
driver.eprocess_traverse_result.contains(&result),
|
dr.deref_addr(try_eprocess_ptr + eprocess_exit_time_offset, &mut exit_time);
|
||||||
result.pool_addr, result.eprocess_addr, result.eprocess_name);
|
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<EprocessPoolChunk>;
|
||||||
|
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());
|
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user