Update lpus feature
Traverse scan - PsActiveProcessHead - PsLoadedModuleList - KiProcessListHead - HandleTableList pdb_store has dt(struct) to display struct
This commit is contained in:
parent
8cf91aef79
commit
5619048a4a
33
src/bin/eprocess_traverse.rs
Normal file
33
src/bin/eprocess_traverse.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use std::error::Error;
|
||||
|
||||
use lpus::{
|
||||
driver_state::{DriverState},
|
||||
traverse_activehead,
|
||||
traverse_kiprocesslist,
|
||||
traverse_handletable
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let activehead = traverse_activehead(&driver).unwrap_or(Vec::new());
|
||||
let kiprocesslist = traverse_kiprocesslist(&driver).unwrap_or(Vec::new());
|
||||
let handletable = traverse_handletable(&driver).unwrap_or(Vec::new());
|
||||
|
||||
for r in activehead.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
println!("=========================================");
|
||||
for r in kiprocesslist.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
println!("=========================================");
|
||||
for r in handletable.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
|
||||
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
||||
Ok(())
|
||||
}
|
||||
|
20
src/bin/kernel_module_traverse.rs
Normal file
20
src/bin/kernel_module_traverse.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::error::Error;
|
||||
|
||||
use lpus::{
|
||||
driver_state::{DriverState},
|
||||
traverse_loadedmodulelist
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut driver = DriverState::new();
|
||||
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
|
||||
|
||||
let result = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
||||
|
||||
for r in result.iter() {
|
||||
println!("{:#}", r.to_string());
|
||||
}
|
||||
|
||||
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
||||
Ok(())
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
use std::error::Error;
|
||||
// use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
|
||||
use lpus::{
|
||||
driver_state::{DriverState},
|
||||
};
|
||||
@ -22,5 +25,36 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
driver.windows_ffi.print_version();
|
||||
driver.pdb_store.print_default_information();
|
||||
|
||||
let mut rl = Editor::<()>::new();
|
||||
if rl.load_history("history.lpus").is_err() {
|
||||
println!("No previous history.");
|
||||
}
|
||||
loop {
|
||||
let readline = rl.readline(">> ");
|
||||
match readline {
|
||||
Ok(line) => {
|
||||
rl.add_history_entry(line.as_str());
|
||||
println!("Line: {}", line);
|
||||
// TODO: add parser here
|
||||
if let Err(e) = driver.pdb_store.dt(&line) {
|
||||
println!("{}", e);
|
||||
}
|
||||
},
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
break
|
||||
},
|
||||
Err(ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
break
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
rl.save_history("history.lpus").unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
205
src/lib.rs
205
src/lib.rs
@ -323,3 +323,208 @@ pub fn scan_kernel_module(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
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, "_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 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": "_KLDR_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, "_KLDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink")?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// dx Debugger.Utility.Collections.FromListEntry( *(nt!_LIST_ENTRY*)&(nt!PsActiveProcessHead), "nt!_EPROCESS", "ActiveProcessLinks")
|
||||
pub fn traverse_activehead(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
let ntosbase = driver.get_kernel_base();
|
||||
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 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")?;
|
||||
|
||||
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")?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// TODO: where is afd!
|
||||
// dx Debugger.Utility.Collections.FromListEntry( *(nt!_LIST_ENTRY*)&(afd!AfdEndpointListHead), "nt!_EPROCESS", "ActiveProcessLinks")
|
||||
// pub fn traverse_afdendpoint(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
// let mut result: Vec<Value> = Vec::new();
|
||||
//
|
||||
// let ntosbase = driver.get_kernel_base();
|
||||
// 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 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")?;
|
||||
//
|
||||
// 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")?;
|
||||
// }
|
||||
//
|
||||
// Ok(result)
|
||||
// }
|
||||
|
||||
// dx Debugger.Utility.Collections.FromListEntry( *(nt!_LIST_ENTRY*)&(nt!KiProcessListHead), "nt!_KPROCESS", "ProcessListEntry").Select( p => new {Process = (nt!_EPROCESS*)&p )
|
||||
pub fn traverse_kiprocesslist(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
let ntosbase = driver.get_kernel_base();
|
||||
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 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")?;
|
||||
|
||||
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")?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// dx Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY*)&nt!HandleTableListHead, "nt!_HANDLE_TABLE", "HandleTableList").Where(h => h.QuotaProcess != 0).Select( qp => new {Process= qp.QuotaProcess} )
|
||||
pub fn traverse_handletable(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
||||
let mut result: Vec<Value> = Vec::new();
|
||||
|
||||
let ntosbase = driver.get_kernel_base();
|
||||
let process_list_head = ntosbase + driver.pdb_store.get_offset_r("HandleTableListHead")?;
|
||||
let handle_list_offset = driver.pdb_store.get_offset_r("_HANDLE_TABLE.HandleTableList")?;
|
||||
|
||||
let mut ptr: u64 = driver.decompose(&process_list_head, "_LIST_ENTRY.Flink")?;
|
||||
while ptr != process_list_head.address() {
|
||||
let handle_ptr = Address::from_base(ptr - handle_list_offset);
|
||||
let quota_process: u64 = driver.decompose(&handle_ptr, "_HANDLE_TABLE.QuotaProcess")?;
|
||||
|
||||
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")?;
|
||||
|
||||
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")?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -194,6 +194,29 @@ impl PdbStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dt(&self, struct_name: &str) -> BoxResult<()> {
|
||||
let member_info = self.structs.get(struct_name).ok_or(format!("no struct named {}", struct_name))?;
|
||||
let (_, struct_size) = member_info.get("struct_size").ok_or("")?;
|
||||
println!("// 0x{:x} bytes", struct_size);
|
||||
println!("struct {} {{", struct_name);
|
||||
|
||||
// Vec<(offset, type, name)>
|
||||
let mut members: Vec<(u64, String, String)> = Vec::new();
|
||||
for (name, (t, offset)) in member_info.iter() {
|
||||
if name != "struct_size" {
|
||||
members.push((*offset, t.to_string(), name.to_string()));
|
||||
}
|
||||
}
|
||||
members.sort_by(|(o1,_,_), (o2,_,_)| o1.partial_cmp(o2).unwrap());
|
||||
|
||||
for (offset, memtype, member) in members.iter() {
|
||||
println!(" +0x{:x} {} {};", offset, memtype, member);
|
||||
}
|
||||
|
||||
println!("}} // {}", struct_name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_as_str(type_finder: &TypeFinder, typ: &TypeIndex) -> String {
|
||||
|
Loading…
Reference in New Issue
Block a user