update
This commit is contained in:
parent
60513ee142
commit
2d7576b1e2
@ -21,12 +21,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let kmods = scan_kernel_module(&driver).unwrap_or(Vec::new());
|
let kmods = scan_kernel_module(&driver).unwrap_or(Vec::new());
|
||||||
|
|
||||||
for d in drivers.iter() {
|
for d in drivers.iter() {
|
||||||
println!("{} {}", d["device"], d["address"]);
|
println!("{} {}", d["address"], d["device"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rl = Editor::<()>::new();
|
let mut rl = Editor::<()>::new();
|
||||||
loop {
|
loop {
|
||||||
let readline = rl.readline(">> ");
|
let readline = rl.readline("irp> ");
|
||||||
match readline {
|
match readline {
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
rl.add_history_entry(line.as_str());
|
rl.add_history_entry(line.as_str());
|
||||||
@ -39,9 +39,11 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
|
let addr: u64 =
|
||||||
|
addr_.as_str().and_then(|x| parse(x).ok()).unwrap_or(0);
|
||||||
|
let mut owner = "(??)";
|
||||||
|
println!("{} {}", addr, get_irp_name(idx));
|
||||||
for kmod in kmods.iter() {
|
for kmod in kmods.iter() {
|
||||||
let addr: u64 =
|
|
||||||
addr_.as_str().and_then(|x| parse(x).ok()).unwrap_or(0);
|
|
||||||
let base: u64 = kmod["dllbase"]
|
let base: u64 = kmod["dllbase"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.and_then(|x| parse(x).ok())
|
.and_then(|x| parse(x).ok())
|
||||||
@ -51,15 +53,11 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
.and_then(|x| parse(x).ok())
|
.and_then(|x| parse(x).ok())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
if addr > base && addr < base + size {
|
if addr > base && addr < base + size {
|
||||||
println!(
|
owner = kmod["BaseName"].as_str().unwrap_or("(??)");
|
||||||
"{} 0x{:x} {}",
|
|
||||||
get_irp_name(idx),
|
|
||||||
addr,
|
|
||||||
kmod["BaseName"]
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("\towned by {}", owner);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ use std::error::Error;
|
|||||||
|
|
||||||
use parse_int::parse;
|
use parse_int::parse;
|
||||||
|
|
||||||
use lpus::{driver_state::DriverState, traverse_loadedmodulelist, traverse_unloadeddrivers};
|
use lpus::{
|
||||||
|
driver_state::DriverState, ssdt_table, traverse_loadedmodulelist, traverse_unloadeddrivers,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let mut driver = DriverState::new();
|
let mut driver = DriverState::new();
|
||||||
@ -17,31 +19,20 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
|
||||||
let unloaded = traverse_unloadeddrivers(&driver).unwrap_or(Vec::new());
|
let unloaded = traverse_unloadeddrivers(&driver).unwrap_or(Vec::new());
|
||||||
|
let ssdt = ssdt_table(&driver)?;
|
||||||
// TODO: move to another place
|
|
||||||
// From Vol3 SSDT scan
|
|
||||||
// https://github.com/volatilityfoundation/volatility3/blob/master/volatility/framework/plugins/windows/ssdt.py
|
|
||||||
let ntosbase = driver.get_kernel_base();
|
let ntosbase = driver.get_kernel_base();
|
||||||
let servicetable = ntosbase.clone() + driver.pdb_store.get_offset_r("KiServiceTable")?;
|
|
||||||
let servicelimit_ptr = ntosbase.clone() + driver.pdb_store.get_offset_r("KiServiceLimit")?;
|
|
||||||
|
|
||||||
let servicelimit = driver.deref_addr_new::<u32>(servicelimit_ptr.address()) as u64;
|
// for r in loaded.iter() {
|
||||||
let ssdt: Vec<u64> = driver
|
// println!("{:#}", r.to_string());
|
||||||
.deref_array::<u32>(&servicetable, servicelimit)
|
// }
|
||||||
.iter()
|
|
||||||
.map(|entry| servicetable.address() + ((entry >> 4) as u64))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for r in loaded.iter() {
|
|
||||||
println!("{:#}", r.to_string());
|
|
||||||
}
|
|
||||||
println!("=============================================");
|
println!("=============================================");
|
||||||
for r in unloaded.iter() {
|
for r in unloaded.iter() {
|
||||||
println!("{:#}", r.to_string());
|
println!("{:#}", r.to_string());
|
||||||
}
|
}
|
||||||
println!("=============================================");
|
println!("=============================================");
|
||||||
for func in ssdt {
|
for (idx, func) in ssdt.iter().enumerate() {
|
||||||
for r in loaded.iter() {
|
println!("SSDT [{}]\t0x{:x}", idx, func);
|
||||||
|
let owner = loaded.iter().find_map(|r| {
|
||||||
let base = r["dllbase"]
|
let base = r["dllbase"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.and_then(|b| parse::<u64>(b).ok())
|
.and_then(|b| parse::<u64>(b).ok())
|
||||||
@ -51,26 +42,34 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
.and_then(|s| parse::<u64>(s).ok())
|
.and_then(|s| parse::<u64>(s).ok())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
if func > base && func < base + size {
|
if *func > base && *func < base + size {
|
||||||
let offset = func - ntosbase.address();
|
let module = r["BaseName"].as_str().unwrap();
|
||||||
let funcname: String = {
|
Some(module)
|
||||||
let mut n = "".to_string();
|
|
||||||
for (name, o) in driver.pdb_store.symbols.iter() {
|
|
||||||
if *o == offset {
|
|
||||||
n = name.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n == "" {
|
|
||||||
"(??)".to_string()
|
|
||||||
} else {
|
|
||||||
n
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("SSDT 0x{:x} {}!{}", func, r["BaseName"], funcname);
|
|
||||||
break; // next func
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if owner == Some("ntoskrnl.exe") {
|
||||||
|
let offset = func - ntosbase.address();
|
||||||
|
let funcname: String = {
|
||||||
|
driver.pdb_store.symbols.iter().find_map(|(name, o)| {
|
||||||
|
if o.clone() == offset {
|
||||||
|
Some(name.clone())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).unwrap_or("(??)".to_string())
|
||||||
|
};
|
||||||
|
println!("\towned by nt!{}", funcname);
|
||||||
|
}
|
||||||
|
else if let Some(owner_) = owner {
|
||||||
|
println!("\towned by {}", owner_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println!("\tmissing owner");
|
||||||
}
|
}
|
||||||
// TODO: If not found, search other list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
||||||
|
52
src/bin/lpus_all.rs
Normal file
52
src/bin/lpus_all.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use serde_json::{json};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
|
||||||
|
use lpus::{
|
||||||
|
driver_state::DriverState, scan_eprocess, scan_ethread, traverse_activehead,
|
||||||
|
traverse_handletable, traverse_kiprocesslist, scan_driver, scan_kernel_module,
|
||||||
|
traverse_loadedmodulelist, traverse_unloadeddrivers,
|
||||||
|
ssdt_table
|
||||||
|
};
|
||||||
|
|
||||||
|
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 eprocess_1 = scan_eprocess(&driver)?;
|
||||||
|
let eprocess_2 = traverse_activehead(&driver)?;
|
||||||
|
let eprocess_3 = traverse_kiprocesslist(&driver)?;
|
||||||
|
let eprocess_4 = traverse_handletable(&driver)?;
|
||||||
|
let ethread = scan_ethread(&driver)?;
|
||||||
|
let drivers = scan_driver(&driver)?;
|
||||||
|
let kernel_module_1 = scan_kernel_module(&driver)?;
|
||||||
|
let kernel_module_2 = traverse_loadedmodulelist(&driver)?;
|
||||||
|
let unloaded_driver = traverse_unloadeddrivers(&driver)?;
|
||||||
|
let ssdt: Vec<String> = ssdt_table(&driver)?.into_iter().map(|x| format!("0x{:x}", x)).collect();
|
||||||
|
|
||||||
|
let result = json!({
|
||||||
|
"scan_eprocess": eprocess_1,
|
||||||
|
"traverse_activehead": eprocess_2,
|
||||||
|
"traverse_kiprocesslist": eprocess_3,
|
||||||
|
"traverse_handletable": eprocess_4,
|
||||||
|
"scan_ethread": ethread,
|
||||||
|
"scan_driver": drivers,
|
||||||
|
"scan_kernel_module": kernel_module_1,
|
||||||
|
"traverse_loadedmodulelist": kernel_module_2,
|
||||||
|
"traverse_unloadeddrivers": unloaded_driver,
|
||||||
|
"ssdt_table": ssdt
|
||||||
|
});
|
||||||
|
|
||||||
|
fs::write("./lpus.json", format!("{:#}", result)).ok();
|
||||||
|
|
||||||
|
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
|
||||||
|
Ok(())
|
||||||
|
}
|
53
src/downloader.rs
Normal file
53
src/downloader.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
use reqwest::{header, Client};
|
||||||
|
use std::path::Path;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
use tokio::{fs, io::AsyncWriteExt};
|
||||||
|
|
||||||
|
type BoxResult<T> = Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
|
async fn download(url: &str, path: &PathBuf) -> BoxResult<()> {
|
||||||
|
let client = Client::new();
|
||||||
|
let total_size = {
|
||||||
|
let resp = client.head(url).send().await?;
|
||||||
|
if resp.status().is_success() {
|
||||||
|
resp.headers()
|
||||||
|
.get(header::CONTENT_LENGTH)
|
||||||
|
.and_then(|ct_len| ct_len.to_str().ok())
|
||||||
|
.and_then(|ct_len| ct_len.parse().ok())
|
||||||
|
.unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
return Err(format!("Couldn'n download URL: {}", url));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut request = client.get(url);
|
||||||
|
let pb = ProgressBar::new(total_size);
|
||||||
|
pb.set_style(
|
||||||
|
ProgressStyle::default_bar()
|
||||||
|
.template("{spinner:.green} [{elapsed_precise}] \
|
||||||
|
[{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})")
|
||||||
|
.progress_chars("#>-"));
|
||||||
|
|
||||||
|
let file = Path::new(path);
|
||||||
|
|
||||||
|
if file.exists() {
|
||||||
|
return Err(format!("File {:?} existed", file));
|
||||||
|
// let size = file.metadata()?.len().saturating_sub(1);
|
||||||
|
// request = request.header(header::RANGE, format!("bytes={}-", size));
|
||||||
|
// pb.inc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut source = request.send().await?;
|
||||||
|
let mut dest = fs::OpenOptions::new().create(true).append(true).open(&file).await?;
|
||||||
|
while let Some(chunk) = source.chunk().await? {
|
||||||
|
dest.write_all(&chunk).await?;
|
||||||
|
pb.inc(chunk.len() as u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Download of '{}' has been completed.", file.to_str().unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
16
src/lib.rs
16
src/lib.rs
@ -566,3 +566,19 @@ pub fn traverse_unloadeddrivers(driver: &DriverState) -> BoxResult<Vec<Value>> {
|
|||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ssdt_table(driver: &DriverState) -> BoxResult<Vec<u64>> {
|
||||||
|
// https://github.com/volatilityfoundation/volatility3/blob/master/volatility/framework/plugins/windows/ssdt.py
|
||||||
|
let ntosbase = driver.get_kernel_base();
|
||||||
|
let servicetable = ntosbase.clone() + driver.pdb_store.get_offset_r("KiServiceTable")?;
|
||||||
|
let servicelimit_ptr = ntosbase.clone() + driver.pdb_store.get_offset_r("KiServiceLimit")?;
|
||||||
|
|
||||||
|
// TODO: Shifting is wrong, Rust seems to do arithmetic shift
|
||||||
|
let servicelimit = driver.deref_addr_new::<u32>(servicelimit_ptr.address()) as u64;
|
||||||
|
let ssdt: Vec<u64> = driver
|
||||||
|
.deref_array::<u32>(&servicetable, servicelimit)
|
||||||
|
.iter()
|
||||||
|
.map(|entry| servicetable.address() + ((*entry as u64) >> 4))
|
||||||
|
.collect();
|
||||||
|
Ok(ssdt)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user