Update working status for Windows 7

This commit is contained in:
nganhkhoa 2020-07-01 00:01:12 +07:00
parent 8cb553eb11
commit 4e67e10aee
11 changed files with 112 additions and 70 deletions

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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.");

View File

@ -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());

View File

@ -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
}

View File

@ -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,30 +249,41 @@ 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();
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) {
break;
}
try_ethread_ptr += 0x4; // search exhaustively
if chunk_size == header_size + object_header_size + ethread_size {
try_ethread_ptr = ethread_valid_end.clone();
}
if try_ethread_ptr > ethread_valid_end {
return Ok(false);
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) {
break;
}
try_ethread_ptr += 0x4; // search exhaustively
}
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)

View File

@ -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 {