Create object in object.rs

This commit is contained in:
nganhkhoa 2020-07-02 02:44:01 +07:00
parent 4e67e10aee
commit b1c3107c74
4 changed files with 302 additions and 298 deletions

7
other/to_epoch.py Normal file
View File

@ -0,0 +1,7 @@
windows_epoch_diff = 11644473600000 * 10000
filetime = 132380977838542980
process_time_epoch = (filetime - windows_epoch_diff) // 10000
print(process_time_epoch)

View File

@ -6,15 +6,28 @@ pub mod windows;
pub mod ioctl_protocol; pub mod ioctl_protocol;
pub mod driver_state; pub mod driver_state;
pub mod address; pub mod address;
pub mod object;
use std::error::Error; use std::error::Error;
use std::str::{from_utf8}; use chrono::{DateTime, TimeZone, Local};
use serde_json::{json, Value}; use serde_json::{json, Value};
use driver_state::DriverState; use driver_state::DriverState;
use address::Address; use address::Address;
use object::*;
type BoxResult<T> = Result<T, Box<dyn Error>>; type BoxResult<T> = Result<T, Box<dyn Error>>;
pub fn to_epoch(filetime: u64) -> DateTime<Local> {
// return seconds from epoch
let windows_epoch_diff = 11_644_473_600_000 * 10_000;
if filetime < windows_epoch_diff {
return Local.timestamp(0, 0);
}
let filetime_epoch = (filetime - windows_epoch_diff) / 10_000_000;
Local.timestamp(filetime_epoch as i64, 0)
}
pub fn get_irp_name(idx: usize) -> String { pub fn get_irp_name(idx: usize) -> String {
let irp_names = vec![ let irp_names = vec![
"IRP_MJ_CREATE", "IRP_MJ_CREATE",
@ -144,31 +157,7 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
return Ok(false); return Ok(false);
} }
let eprocess_ptr = &try_eprocess_ptr; result.push(make_eprocess(driver, &try_eprocess_ptr)?);
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 after Windows 10 Anniversary
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()
};
let binary_path = driver.get_unicode_string(unicode_str_ptr)
.unwrap_or("".to_string());
result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", eprocess_ptr.address()),
"type": "_EPROCESS",
"pid": pid,
"ppid": ppid,
"name": eprocess_name,
"path": binary_path
}));
Ok(true) Ok(true)
})?; })?;
Ok(result) Ok(result)
@ -278,29 +267,7 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
} }
} }
let ethread_ptr = &try_ethread_ptr; result.push(make_ethread(driver, &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")
.unwrap_or(0); // ThreadName is after Windows 10 Anniversary
let thread_name =
if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) {
name
}
else {
"".to_string()
};
result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", ethread_ptr.address()),
"type": "_ETHREAD",
"pid": pid,
"tid": tid,
"name": thread_name
}));
Ok(true) Ok(true)
})?; })?;
@ -308,64 +275,64 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
} }
// Unstable, do not use // Unstable, do not use
pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> { // pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = Vec::new(); // let mut result: Vec<Value> = Vec::new();
//
let ntosbase = driver.get_kernel_base(); // let ntosbase = driver.get_kernel_base();
let [start, end] = driver.get_nonpaged_range(&ntosbase)?; // let [start, end] = driver.get_nonpaged_range(&ntosbase)?;
//
let tag = // let tag =
if driver.use_old_tag() { b"Mut\xe1" } // if driver.use_old_tag() { b"Mut\xe1" }
else { b"Muta" }; // else { b"Muta" };
driver.scan_pool(tag, "_KMUTANT", |pool_addr, header, data_addr| { // driver.scan_pool(tag, "_KMUTANT", |pool_addr, header, data_addr| {
let chunk_size = (header[2] as u64) * 16u64; // let chunk_size = (header[2] as u64) * 16u64;
//
let kmutant_size = driver.pdb_store.get_offset_r("_KMUTANT.struct_size")?; // let kmutant_size = driver.pdb_store.get_offset_r("_KMUTANT.struct_size")?;
//
let kmutant_valid_start = data_addr; // let kmutant_valid_start = data_addr;
let kmutant_valid_end = (pool_addr.clone() + chunk_size) - kmutant_size; // let kmutant_valid_end = (pool_addr.clone() + chunk_size) - kmutant_size;
let mut try_kmutant_ptr = kmutant_valid_start.clone(); // let mut try_kmutant_ptr = kmutant_valid_start.clone();
//
while try_kmutant_ptr <= kmutant_valid_end { // while try_kmutant_ptr <= kmutant_valid_end {
// TODO: Stronger constrain // // TODO: Stronger constrain
let kthread_ptr = driver.address_of(&try_kmutant_ptr, "_KMUTANT.OwnerThread")?; // let kthread_ptr = driver.address_of(&try_kmutant_ptr, "_KMUTANT.OwnerThread")?;
if kthread_ptr > start.address() && kthread_ptr < end.address() { // if kthread_ptr > start.address() && kthread_ptr < end.address() {
break; // break;
} // }
try_kmutant_ptr += 0x4; // search exhaustively // try_kmutant_ptr += 0x4; // search exhaustively
} // }
if try_kmutant_ptr > kmutant_valid_end { // if try_kmutant_ptr > kmutant_valid_end {
return Ok(false); // return Ok(false);
} // }
//
let kmutant_ptr = try_kmutant_ptr; // let kmutant_ptr = try_kmutant_ptr;
let ethread_ptr = Address::from_base(driver.address_of(&kmutant_ptr, "_KMUTANT.OwnerThread")?); // let ethread_ptr = Address::from_base(driver.address_of(&kmutant_ptr, "_KMUTANT.OwnerThread")?);
//
let pid: u64 = driver.decompose(&ethread_ptr, "_ETHREAD.Cid.UniqueProcess")?; // let pid: u64 = driver.decompose(&ethread_ptr, "_ETHREAD.Cid.UniqueProcess")?;
let tid: u64 = driver.decompose(&ethread_ptr, "_ETHREAD.Cid.UniqueThread")?; // 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")?;
//
let thread_name = // let thread_name =
if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) { // if let Ok(name) = driver.get_unicode_string(unicode_str_ptr) {
name // name
} // }
else { // else {
"".to_string() // "".to_string()
}; // };
//
result.push(json!({ // result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()), // "pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", ethread_ptr.address()), // "address": format!("0x{:x}", ethread_ptr.address()),
"type": "_KMUTANT", // "type": "_KMUTANT",
"pid": pid, // "pid": pid,
"tid": tid, // "tid": tid,
"name": thread_name // "name": thread_name
})); // }));
Ok(true) // Ok(true)
})?; // })?;
//
Ok(result) // Ok(result)
} // }
pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> { pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = Vec::new(); let mut result: Vec<Value> = Vec::new();
@ -382,7 +349,6 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
while try_ptr <= valid_end { while try_ptr <= valid_end {
// No documentation on type constrain // No documentation on type constrain
// let ftype: u16 = driver.decompose(&try_ptr, "_DRIVER_OBJECT.Type")?;
let size: u16 = driver.decompose(&try_ptr, "_DRIVER_OBJECT.Size")?; let size: u16 = driver.decompose(&try_ptr, "_DRIVER_OBJECT.Size")?;
if (size as u64) == dob_size /* && ftype == 5u16 */ { if (size as u64) == dob_size /* && ftype == 5u16 */ {
break; break;
@ -392,72 +358,7 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
if try_ptr > valid_end { if try_ptr > valid_end {
return Ok(false); return Ok(false);
} }
let dob_addr = &try_ptr; result.push(make_driver(driver, &try_ptr)?);
let devicename_ptr = driver.address_of(dob_addr, "_DRIVER_OBJECT.DriverName")?;
let servicekey_ptr = driver.address_of(dob_addr, "_DRIVER_OBJECT.DriverExtension.ServiceKeyName")?;
let hardware_ptr: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.HardwareDatabase")?;
let major_function: Vec<u64> = driver.decompose_array(dob_addr, "_DRIVER_OBJECT.MajorFunction", 28)?;
let start: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.DriverStart")?;
let init: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.DriverInit")?;
let unload: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.DriverUnload")?;
let size: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.DriverSize")?;
let devicename = driver.get_unicode_string(devicename_ptr)
.unwrap_or("".to_string());
let hardware = driver.get_unicode_string(hardware_ptr)
.unwrap_or("".to_string());
let servicekey = driver.get_unicode_string(servicekey_ptr)
.unwrap_or("".to_string());
// device tree walk
let devices = {
let mut driver_devices: Vec<Value> = Vec::new();
let mut device_ptr: u64 = driver.decompose(dob_addr, "_DRIVER_OBJECT.DeviceObject")?;
while device_ptr != 0 {
let addr = Address::from_base(device_ptr);
let device_type: u32 = driver.decompose(&addr, "_DEVICE_OBJECT.DeviceType")?;
// get attached devices
let mut attached_ptr: u64 = driver.decompose(&addr, "_DEVICE_OBJECT.AttachedDevice")?;
let mut attached_devices: Vec<Value> = Vec::new();
while attached_ptr != 0 {
let attached = Address::from_base(attached_ptr);
let attached_device_type: u32 = driver.decompose(&attached, "_DEVICE_OBJECT.DeviceType")?;
attached_devices.push(json!({
"address": format!("0x{:x}", attached_ptr),
"type": "_DEVICE_OBJECT",
"devicetype": get_device_type(attached_device_type)
}));
attached_ptr = driver.decompose(&attached, "_DEVICE_OBJECT.AttachedDevice")?;
}
driver_devices.push(json!({
"address": format!("0x{:x}", device_ptr),
"type": "_DEVICE_OBJECT",
"devicetype": get_device_type(device_type),
"attached": attached_devices
}));
device_ptr = driver.decompose(&addr, "_DEVICE_OBJECT.NextDevice")?;
}
driver_devices
};
result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", dob_addr.address()),
"type": "_DRIVER_OBJECT",
"device": devicename,
"hardware": hardware,
"major_function": major_function.into_iter()
.map(|func| format!("0x{:x}", func))
.collect::<Vec<String>>(),
"servicekey": servicekey,
"start": format!("0x{:x}", start),
"init": format!("0x{:x}", init),
"unload": format!("0x{:x}", unload),
"size": format!("0x{:x}", size),
"devicetree": devices
}));
Ok(true) Ok(true)
})?; })?;
@ -467,30 +368,9 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> { pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = Vec::new(); let mut result: Vec<Value> = Vec::new();
driver.scan_pool(b"MmLd", "_LDR_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 // By reversing, this structure does not have any header
let mod_addr = &data_addr; result.push(make_ldr(driver, &data_addr)?);
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());
let basename = driver.get_unicode_string(basename_ptr)
.unwrap_or("".to_string());
result.push(json!({
"pool": format!("0x{:x}", pool_addr.address()),
"address": format!("0x{:x}", mod_addr.address()),
"type": "_LDR_DATA_TABLE_ENTRY",
"dllbase": format!("0x{:x}", dllbase),
"entry": format!("0x{:x}", entry),
"size": format!("0x{:x}", size),
"FullName": fullname,
"BaseName": basename
}));
Ok(true) Ok(true)
})?; })?;
@ -498,37 +378,13 @@ pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> {
} }
pub fn traverse_loadedmodulelist(driver: &DriverState) -> BoxResult<Vec<Value>> { pub fn traverse_loadedmodulelist(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = Vec::new();
let ntosbase = driver.get_kernel_base(); let ntosbase = driver.get_kernel_base();
let module_list_head = ntosbase + driver.pdb_store.get_offset_r("PsLoadedModuleList")?; let module_list_head = ntosbase + driver.pdb_store.get_offset_r("PsLoadedModuleList")?;
let mut ptr: u64 = driver.decompose(&module_list_head, "_LIST_ENTRY.Flink")?; let result =
while ptr != module_list_head.address() { make_list_entry(driver, module_list_head.clone(), "_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks")?
let mod_addr = Address::from_base(ptr); .iter().map(|x| make_ldr(driver, &x).unwrap_or(json!({}))).collect();
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());
let basename = driver.get_unicode_string(basename_ptr)
.unwrap_or("".to_string());
result.push(json!({
"address": format!("0x{:x}", mod_addr.address()),
"type": "_LDR_DATA_TABLE_ENTRY",
"dllbase": format!("0x{:x}", dllbase),
"entry": format!("0x{:x}", entry),
"size": format!("0x{:x}", size),
"FullName": fullname,
"BaseName": basename
}));
ptr = driver.decompose(&mod_addr, "_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink")?;
}
Ok(result) Ok(result)
} }
@ -541,34 +397,11 @@ pub fn traverse_activehead(driver: &DriverState) -> BoxResult<Vec<Value>> {
let process_list_head = ntosbase + driver.pdb_store.get_offset_r("PsActiveProcessHead")?; let process_list_head = ntosbase + driver.pdb_store.get_offset_r("PsActiveProcessHead")?;
let eprocess_listentry_offset = driver.pdb_store.get_offset_r("_EPROCESS.ActiveProcessLinks")?; let eprocess_listentry_offset = driver.pdb_store.get_offset_r("_EPROCESS.ActiveProcessLinks")?;
// TODO: make_list_entry
let mut ptr: u64 = driver.decompose(&process_list_head, "_LIST_ENTRY.Flink")?; let mut ptr: u64 = driver.decompose(&process_list_head, "_LIST_ENTRY.Flink")?;
while ptr != process_list_head.address() { while ptr != process_list_head.address() {
let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset); let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset);
result.push(make_eprocess(driver, &eprocess_ptr)?);
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);
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()
};
let binary_path = driver.get_unicode_string(unicode_str_ptr)
.unwrap_or("".to_string());
result.push(json!({
"address": format!("0x{:x}", &eprocess_ptr.address()),
"type": "_EPROCESS",
"pid": pid,
"ppid": ppid,
"name": eprocess_name,
"path": binary_path
}));
ptr = driver.decompose(&eprocess_ptr, "_EPROCESS.ActiveProcessLinks.Flink")?; ptr = driver.decompose(&eprocess_ptr, "_EPROCESS.ActiveProcessLinks.Flink")?;
} }
@ -625,33 +458,11 @@ pub fn traverse_kiprocesslist(driver: &DriverState) -> BoxResult<Vec<Value>> {
let process_list_head = ntosbase + driver.pdb_store.get_offset_r("KiProcessListHead")?; let process_list_head = ntosbase + driver.pdb_store.get_offset_r("KiProcessListHead")?;
let eprocess_listentry_offset = driver.pdb_store.get_offset_r("_KPROCESS.ProcessListEntry")?; let eprocess_listentry_offset = driver.pdb_store.get_offset_r("_KPROCESS.ProcessListEntry")?;
// TODO: make_list_entry
let mut ptr: u64 = driver.decompose(&process_list_head, "_LIST_ENTRY.Flink")?; let mut ptr: u64 = driver.decompose(&process_list_head, "_LIST_ENTRY.Flink")?;
while ptr != process_list_head.address() { while ptr != process_list_head.address() {
let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset); let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset);
result.push(make_eprocess(driver, &eprocess_ptr)?);
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);
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()
};
let binary_path = driver.get_unicode_string(unicode_str_ptr)
.unwrap_or("".to_string());
result.push(json!({
"address": format!("0x{:x}", &eprocess_ptr.address()),
"type": "_EPROCESS",
"pid": pid,
"ppid": ppid,
"name": eprocess_name,
"path": binary_path
}));
ptr = driver.decompose(&eprocess_ptr, "_KPROCESS.ProcessListEntry.Flink")?; ptr = driver.decompose(&eprocess_ptr, "_KPROCESS.ProcessListEntry.Flink")?;
} }
@ -674,29 +485,7 @@ pub fn traverse_handletable(driver: &DriverState) -> BoxResult<Vec<Value>> {
if quota_process != 0 { if quota_process != 0 {
let eprocess_ptr = Address::from_base(quota_process); let eprocess_ptr = Address::from_base(quota_process);
let pid: u64 = driver.decompose(&eprocess_ptr, "_EPROCESS.UniqueProcessId")?; result.push(make_eprocess(driver, &eprocess_ptr)?);
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);
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()
};
let binary_path = driver.get_unicode_string(unicode_str_ptr)
.unwrap_or("".to_string());
result.push(json!({
"address": format!("0x{:x}", &eprocess_ptr.address()),
"type": "_EPROCESS",
"pid": pid,
"ppid": ppid,
"name": eprocess_name,
"path": binary_path
}));
} }
ptr = driver.decompose(&handle_ptr, "_HANDLE_TABLE.HandleTableList.Flink")?; ptr = driver.decompose(&handle_ptr, "_HANDLE_TABLE.HandleTableList.Flink")?;

207
src/object.rs Normal file
View File

@ -0,0 +1,207 @@
use std::error::Error;
use std::str::{from_utf8};
use serde_json::{json, Value};
use crate::driver_state::DriverState;
use crate::address::Address;
use crate::{get_device_type, to_epoch};
type BoxResult<T> = Result<T, Box<dyn Error>>;
pub fn make_list_entry(d: &DriverState, a: Address, next: &str) -> BoxResult<Vec<Address>> {
// `a` is the address to the _LIST_ENTRY
// `next` is the _LIST_ENTRY field in the object
// return a list of address for object
let mut result: Vec<Address> = Vec::new();
let list_offset = d.pdb_store.get_offset_r(next)?;
let mut ptr: u64 = d.deref_addr_new(a.address());
while ptr != a.address() {
let obj_ptr = Address::from_base(ptr - list_offset);
ptr = d.decompose(&obj_ptr, &format!("{}.Flink", next))?;
result.push(obj_ptr);
}
Ok(result)
}
pub fn make_eprocess(d: &DriverState, a: &Address) -> BoxResult<Value> {
let createtime: u64 = d.decompose(a, "_EPROCESS.CreateTime")?;
let exittime: u64 = d.decompose(a, "_EPROCESS.ExitTime")?;
let pid: u64 = d.decompose(a, "_EPROCESS.UniqueProcessId")?;
let ppid: u64 = d.decompose(a, "_EPROCESS.InheritedFromUniqueProcessId")?;
let image_name: Vec<u8> = d.decompose_array(a, "_EPROCESS.ImageFileName", 15)?;
let filename_ptr = d.address_of(a, "_EPROCESS.ImageFilePointer.FileName")
.unwrap_or(0); // ImageFilePointer is after Windows 10 Anniversary
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()
};
let binary_path = d.get_unicode_string(filename_ptr)
.unwrap_or("".to_string());
let thread_head = d.address_of(a, "_EPROCESS.ThreadListHead")?;
let threads: Vec<Value> =
make_list_entry(d, Address::from_base(thread_head), "_ETHREAD.ThreadListEntry")
.unwrap_or(Vec::new()).iter()
.map(|thread_addr| {
make_ethread(d, thread_addr)
.unwrap_or(json!({})) // unlikely
}).collect();
let c_t = to_epoch(createtime);
let e_t = to_epoch(exittime);
Ok(json!({
"address": format!("0x{:x}", a.address()),
"type": "_EPROCESS",
"pid": pid,
"ppid": ppid,
"name": eprocess_name,
"path": binary_path,
"threads": threads,
"createtime": {
"unix": c_t.timestamp(),
"rfc2822": c_t.to_rfc2822()
},
"exittime": {
"unix": e_t.timestamp(),
"rfc2822": e_t.to_rfc2822(),
}
}))
}
pub fn make_ethread(d: &DriverState, a: &Address) -> BoxResult<Value> {
// let createtime: u64 = d.decompose(a, "_ETHREAD.CreateTime")?;
// let exittime: u64 = d.decompose(a, "_ETHREAD.ExitTime")?;
let pid: u64 = d.decompose(a, "_ETHREAD.Cid.UniqueProcess")?;
let tid: u64 = d.decompose(a, "_ETHREAD.Cid.UniqueThread")?;
let name_ptr: u64 = d.address_of(a, "_ETHREAD.ThreadName")
.unwrap_or(0); // ThreadName is after Windows 10 Anniversary
let thread_name =
if let Ok(name) = d.get_unicode_string(name_ptr) { name }
else { "".to_string() };
// let c_t = to_epoch(createtime);
// let e_t = to_epoch(exittime);
Ok(json!({
"address": format!("0x{:x}", a.address()),
"type": "_ETHREAD",
"tid": tid,
"pid": pid,
"name": thread_name,
// "createtime": {
// "unix": c_t.timestamp(),
// "rfc2822": c_t.to_rfc2822()
// },
// "exittime": {
// "unix": e_t.timestamp(),
// "rfc2822": e_t.to_rfc2822(),
// }
}))
}
pub fn make_driver(d: &DriverState, a: &Address) -> BoxResult<Value> {
let devicename_ptr = d.address_of(a, "_DRIVER_OBJECT.DriverName")?;
let servicekey_ptr = d.address_of(a, "_DRIVER_OBJECT.DriverExtension.ServiceKeyName")?;
let hardware_ptr: u64 = d.decompose(a, "_DRIVER_OBJECT.HardwareDatabase")?;
let major_function: Vec<u64> = d.decompose_array(a, "_DRIVER_OBJECT.MajorFunction", 28)?;
let start: u64 = d.decompose(a, "_DRIVER_OBJECT.DriverStart")?;
let init: u64 = d.decompose(a, "_DRIVER_OBJECT.DriverInit")?;
let unload: u64 = d.decompose(a, "_DRIVER_OBJECT.DriverUnload")?;
let size: u64 = d.decompose(a, "_DRIVER_OBJECT.DriverSize")?;
let devicename = d.get_unicode_string(devicename_ptr)
.unwrap_or("".to_string());
let hardware = d.get_unicode_string(hardware_ptr)
.unwrap_or("".to_string());
let servicekey = d.get_unicode_string(servicekey_ptr)
.unwrap_or("".to_string());
// device tree walk
let devices = {
let mut driver_devices: Vec<Value> = Vec::new();
let mut device_ptr: u64 = d.decompose(a, "_DRIVER_OBJECT.DeviceObject")?;
while device_ptr != 0 {
let addr = Address::from_base(device_ptr);
let device_type: u32 = d.decompose(&addr, "_DEVICE_OBJECT.DeviceType")?;
// get attached devices
let mut attached_ptr: u64 = d.decompose(&addr, "_DEVICE_OBJECT.AttachedDevice")?;
let mut attached_devices: Vec<Value> = Vec::new();
while attached_ptr != 0 {
let attached = Address::from_base(attached_ptr);
let attached_device_type: u32 = d.decompose(&attached, "_DEVICE_OBJECT.DeviceType")?;
attached_devices.push(json!({
"address": format!("0x{:x}", attached_ptr),
"type": "_DEVICE_OBJECT",
"devicetype": get_device_type(attached_device_type)
}));
attached_ptr = d.decompose(&attached, "_DEVICE_OBJECT.AttachedDevice")?;
}
driver_devices.push(json!({
"address": format!("0x{:x}", device_ptr),
"type": "_DEVICE_OBJECT",
"devicetype": get_device_type(device_type),
"attached": attached_devices
}));
device_ptr = d.decompose(&addr, "_DEVICE_OBJECT.NextDevice")?;
}
driver_devices
};
Ok(json!({
"address": format!("0x{:x}", a.address()),
"type": "_DRIVER_OBJECT",
"device": devicename,
"hardware": hardware,
"major_function": major_function.into_iter()
.map(|func| format!("0x{:x}", func))
.collect::<Vec<String>>(),
"servicekey": servicekey,
"start": format!("0x{:x}", start),
"init": format!("0x{:x}", init),
"unload": format!("0x{:x}", unload),
"size": format!("0x{:x}", size),
"devicetree": devices
}))
}
pub fn make_ldr(d: &DriverState, a: &Address) -> BoxResult<Value> {
let dllbase: u64 = d.decompose(a, "_LDR_DATA_TABLE_ENTRY.DllBase")?;
let entry: u64 = d.decompose(a, "_LDR_DATA_TABLE_ENTRY.EntryPoint")?;
let size: u64 = d.decompose(a, "_LDR_DATA_TABLE_ENTRY.SizeOfImage")?;
let fullname_ptr = d.address_of(a, "_LDR_DATA_TABLE_ENTRY.FullDllName")?;
let basename_ptr = d.address_of(a, "_LDR_DATA_TABLE_ENTRY.BaseDllName")?;
let fullname = d.get_unicode_string(fullname_ptr)
.unwrap_or("".to_string());
let basename = d.get_unicode_string(basename_ptr)
.unwrap_or("".to_string());
let ldr_load: Vec<String> =
make_list_entry(d, a.clone(), "_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks")?
.iter().map(|x| format!("0x{:x}", x.address())).collect();
let ldr_mem: Vec<String> =
make_list_entry(d, a.clone(), "_LDR_DATA_TABLE_ENTRY.InMemoryOrderLinks")?
.iter().map(|x| format!("0x{:x}", x.address())).collect();
let ldr_init: Vec<String> =
make_list_entry(d, a.clone(), "_LDR_DATA_TABLE_ENTRY.InInitializationOrderLinks")?
.iter().map(|x| format!("0x{:x}", x.address())).collect();
Ok(json!({
"address": format!("0x{:x}", a.address()),
"type": "_LDR_DATA_TABLE_ENTRY",
"dllbase": format!("0x{:x}", dllbase),
"entry": format!("0x{:x}", entry),
"size": format!("0x{:x}", size),
"FullName": fullname,
"BaseName": basename,
"ldr_load": ldr_load,
"ldr_mem": ldr_mem,
"ldr_init": ldr_init
}))
}

View File

@ -256,9 +256,10 @@ impl WindowsFFI {
return false; return false;
} }
let system_up_time_ms = unsafe { GetTickCount64() }; let system_up_time_ms = unsafe { GetTickCount64() };
let process_time_epoch = (filetime - windows_epoch_diff) / 10000; let process_time_epoch = (filetime - windows_epoch_diff) / 10000; // in milisecond
let now_ms = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis() as u64; let now_ms = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis() as u64;
let system_start_up_time_ms = now_ms - system_up_time_ms; let system_start_up_time_ms =
now_ms - system_up_time_ms - (10 * 3600 * 1000/* 10 minutes penalty */);
if process_time_epoch < system_start_up_time_ms { if process_time_epoch < system_start_up_time_ms {
false false