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 driver_state;
pub mod address;
pub mod object;
use std::error::Error;
use std::str::{from_utf8};
use chrono::{DateTime, TimeZone, Local};
use serde_json::{json, Value};
use driver_state::DriverState;
use address::Address;
use object::*;
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 {
let irp_names = vec![
"IRP_MJ_CREATE",
@ -144,31 +157,7 @@ pub fn scan_eprocess(driver: &DriverState) -> BoxResult<Vec<Value>> {
return Ok(false);
}
let eprocess_ptr = &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
}));
result.push(make_eprocess(driver, &try_eprocess_ptr)?);
Ok(true)
})?;
Ok(result)
@ -278,29 +267,7 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
}
}
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")
.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
}));
result.push(make_ethread(driver, &try_ethread_ptr)?);
Ok(true)
})?;
@ -308,64 +275,64 @@ pub fn scan_ethread(driver: &DriverState) -> BoxResult<Vec<Value>> {
}
// Unstable, do not use
pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
let mut result: Vec<Value> = Vec::new();
let ntosbase = driver.get_kernel_base();
let [start, end] = driver.get_nonpaged_range(&ntosbase)?;
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")?;
let kmutant_valid_start = data_addr;
let kmutant_valid_end = (pool_addr.clone() + chunk_size) - kmutant_size;
let mut try_kmutant_ptr = kmutant_valid_start.clone();
while try_kmutant_ptr <= kmutant_valid_end {
// TODO: Stronger constrain
let kthread_ptr = driver.address_of(&try_kmutant_ptr, "_KMUTANT.OwnerThread")?;
if kthread_ptr > start.address() && kthread_ptr < end.address() {
break;
}
try_kmutant_ptr += 0x4; // search exhaustively
}
if try_kmutant_ptr > kmutant_valid_end {
return Ok(false);
}
let kmutant_ptr = try_kmutant_ptr;
let ethread_ptr = Address::from_base(driver.address_of(&kmutant_ptr, "_KMUTANT.OwnerThread")?);
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 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": "_KMUTANT",
"pid": pid,
"tid": tid,
"name": thread_name
}));
Ok(true)
})?;
Ok(result)
}
// pub fn scan_mutant(driver: &DriverState) -> BoxResult<Vec<Value>> {
// let mut result: Vec<Value> = Vec::new();
//
// let ntosbase = driver.get_kernel_base();
// let [start, end] = driver.get_nonpaged_range(&ntosbase)?;
//
// 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")?;
//
// let kmutant_valid_start = data_addr;
// let kmutant_valid_end = (pool_addr.clone() + chunk_size) - kmutant_size;
// let mut try_kmutant_ptr = kmutant_valid_start.clone();
//
// while try_kmutant_ptr <= kmutant_valid_end {
// // TODO: Stronger constrain
// let kthread_ptr = driver.address_of(&try_kmutant_ptr, "_KMUTANT.OwnerThread")?;
// if kthread_ptr > start.address() && kthread_ptr < end.address() {
// break;
// }
// try_kmutant_ptr += 0x4; // search exhaustively
// }
// if try_kmutant_ptr > kmutant_valid_end {
// return Ok(false);
// }
//
// let kmutant_ptr = try_kmutant_ptr;
// let ethread_ptr = Address::from_base(driver.address_of(&kmutant_ptr, "_KMUTANT.OwnerThread")?);
//
// 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 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": "_KMUTANT",
// "pid": pid,
// "tid": tid,
// "name": thread_name
// }));
// Ok(true)
// })?;
//
// Ok(result)
// }
pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
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 {
// 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")?;
if (size as u64) == dob_size /* && ftype == 5u16 */ {
break;
@ -392,72 +358,7 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
if try_ptr > valid_end {
return Ok(false);
}
let dob_addr = &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
}));
result.push(make_driver(driver, &try_ptr)?);
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>> {
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
let mod_addr = &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
}));
result.push(make_ldr(driver, &data_addr)?);
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>> {
let mut result: Vec<Value> = Vec::new();
let ntosbase = driver.get_kernel_base();
let module_list_head = ntosbase + driver.pdb_store.get_offset_r("PsLoadedModuleList")?;
let mut ptr: u64 = driver.decompose(&module_list_head, "_LIST_ENTRY.Flink")?;
while ptr != module_list_head.address() {
let mod_addr = Address::from_base(ptr);
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")?;
}
let result =
make_list_entry(driver, module_list_head.clone(), "_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks")?
.iter().map(|x| make_ldr(driver, &x).unwrap_or(json!({}))).collect();
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 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")?;
while ptr != process_list_head.address() {
let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset);
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
}));
result.push(make_eprocess(driver, &eprocess_ptr)?);
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 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")?;
while ptr != process_list_head.address() {
let eprocess_ptr = Address::from_base(ptr - eprocess_listentry_offset);
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
}));
result.push(make_eprocess(driver, &eprocess_ptr)?);
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 {
let eprocess_ptr = Address::from_base(quota_process);
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
}));
result.push(make_eprocess(driver, &eprocess_ptr)?);
}
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;
}
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 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 {
false