diff --git a/Cargo.lock b/Cargo.lock index e2bbfa5..94f58b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -453,6 +453,7 @@ version = "0.1.0" dependencies = [ "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parse_int 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -639,6 +640,14 @@ dependencies = [ "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parse_int" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pdb" version = "0.5.0" @@ -1456,6 +1465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +"checksum parse_int 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82db48cac18f0963b10ddad303fa88447b95bbe0e6dbe3385f98402b63d0cc48" "checksum pdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6b57b7067dc9dbd04b1305bb51a8ae7d0fc645956a73b6cb2807dd956ab6929" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" diff --git a/Cargo.toml b/Cargo.toml index 9ce06c7..d97640b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ widestring = "0.4.0" winapi = { version = "0.3.8", features = ["libloaderapi", "processthreadsapi", "winbase", "securitybaseapi", "handleapi", "winnt", "winreg", "fileapi", "ioapiset", "winioctl", "errhandlingapi", "sysinfoapi"] } reqwest = { version = "0.10.1", features = ["blocking"] } serde_json = "1.0.55" +parse_int = "0.4.0" # repl dependencies rustyline = "6.2.0" pest = "2.1.3" diff --git a/src/bin/kernel_module_traverse.rs b/src/bin/kernel_module_traverse.rs index 9f566f5..096ec89 100644 --- a/src/bin/kernel_module_traverse.rs +++ b/src/bin/kernel_module_traverse.rs @@ -1,5 +1,7 @@ use std::error::Error; +use parse_int::parse; + use lpus::{ driver_state::{DriverState}, traverse_loadedmodulelist, @@ -13,6 +15,19 @@ fn main() -> Result<(), Box> { let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new()); let unloaded = traverse_unloadeddrivers(&driver).unwrap_or(Vec::new()); + // 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 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::(servicelimit_ptr.address()) as u64; + let ssdt: Vec = driver.deref_array::(&servicetable, servicelimit) + .iter().map(|entry| { + servicetable.address() + ((entry >> 4) as u64) + }).collect(); + for r in loaded.iter() { println!("{:#}", r.to_string()); } @@ -20,6 +35,34 @@ fn main() -> Result<(), Box> { for r in unloaded.iter() { println!("{:#}", r.to_string()); } + println!("============================================="); + for func in ssdt { + for r in loaded.iter() { + let base = r["dllbase"].as_str().and_then(|b| parse::(b).ok()).unwrap_or(0); + let size = r["size"].as_str().and_then(|s| parse::(s).ok()).unwrap_or(0); + + if func > base && func < base + size { + let offset = func - ntosbase.address(); + let funcname: String = { + 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 + } + } + // TODO: If not found, search other list + } println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown()); Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 8198126..4683358 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,110 @@ use address::Address; type BoxResult = Result>; +pub fn get_irp_name(idx: usize) -> String { + let irp_names = vec![ + "IRP_MJ_CREATE", + "IRP_MJ_CREATE_NAMED_PIPE", + "IRP_MJ_CLOSE", + "IRP_MJ_READ", + "IRP_MJ_WRITE", + "IRP_MJ_QUERY_INFORMATION", + "IRP_MJ_SET_INFORMATION", + "IRP_MJ_QUERY_EA", + "IRP_MJ_SET_EA", + "IRP_MJ_FLUSH_BUFFERS", + "IRP_MJ_QUERY_VOLUME_INFORMATION", + "IRP_MJ_SET_VOLUME_INFORMATION", + "IRP_MJ_DIRECTORY_CONTROL", + "IRP_MJ_FILE_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CONTROL", + "IRP_MJ_INTERNAL_DEVICE_CONTROL", + "IRP_MJ_SHUTDOWN", + "IRP_MJ_LOCK_CONTROL", + "IRP_MJ_CLEANUP", + "IRP_MJ_CREATE_MAILSLOT", + "IRP_MJ_QUERY_SECURITY", + "IRP_MJ_SET_SECURITY", + "IRP_MJ_POWER", + "IRP_MJ_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CHANGE", + "IRP_MJ_QUERY_QUOTA", + "IRP_MJ_SET_QUOTA", + "IRP_MJ_PNP" + ].iter().map(|x| x.to_string()).collect::>(); + + if let Some(name) = irp_names.get(idx) { + name.clone() + } + else { + "UNKNOWN".to_string() + } +} + +fn get_device_type(typ: u32) -> String { + match typ { + 0x00000027 => "FILE_DEVICE_8042_PORT", + 0x00000032 => "FILE_DEVICE_ACPI", + 0x00000029 => "FILE_DEVICE_BATTERY", + 0x00000001 => "FILE_DEVICE_BEEP", + 0x0000002a => "FILE_DEVICE_BUS_EXTENDER", + 0x00000002 => "FILE_DEVICE_CD_ROM", + 0x00000003 => "FILE_DEVICE_CD_ROM_FILE_SYSTEM", + 0x00000030 => "FILE_DEVICE_CHANGER", + 0x00000004 => "FILE_DEVICE_CONTROLLER", + 0x00000005 => "FILE_DEVICE_DATALINK", + 0x00000006 => "FILE_DEVICE_DFS", + 0x00000035 => "FILE_DEVICE_DFS_FILE_SYSTEM", + 0x00000036 => "FILE_DEVICE_DFS_VOLUME", + 0x00000007 => "FILE_DEVICE_DISK", + 0x00000008 => "FILE_DEVICE_DISK_FILE_SYSTEM", + 0x00000033 => "FILE_DEVICE_DVD", + 0x00000009 => "FILE_DEVICE_FILE_SYSTEM", + 0x0000003a => "FILE_DEVICE_FIPS", + 0x00000034 => "FILE_DEVICE_FULLSCREEN_VIDEO", + 0x0000000a => "FILE_DEVICE_INPORT_PORT", + 0x0000000b => "FILE_DEVICE_KEYBOARD", + 0x0000002f => "FILE_DEVICE_KS", + 0x00000039 => "FILE_DEVICE_KSEC", + 0x0000000c => "FILE_DEVICE_MAILSLOT", + 0x0000002d => "FILE_DEVICE_MASS_STORAGE", + 0x0000000d => "FILE_DEVICE_MIDI_IN", + 0x0000000e => "FILE_DEVICE_MIDI_OUT", + 0x0000002b => "FILE_DEVICE_MODEM", + 0x0000000f => "FILE_DEVICE_MOUSE", + 0x00000010 => "FILE_DEVICE_MULTI_UNC_PROVIDER", + 0x00000011 => "FILE_DEVICE_NAMED_PIPE", + 0x00000012 => "FILE_DEVICE_NETWORK", + 0x00000013 => "FILE_DEVICE_NETWORK_BROWSER", + 0x00000014 => "FILE_DEVICE_NETWORK_FILE_SYSTEM", + 0x00000028 => "FILE_DEVICE_NETWORK_REDIRECTOR", + 0x00000015 => "FILE_DEVICE_NULL", + 0x00000016 => "FILE_DEVICE_PARALLEL_PORT", + 0x00000017 => "FILE_DEVICE_PHYSICAL_NETCARD", + 0x00000018 => "FILE_DEVICE_PRINTER", + 0x00000019 => "FILE_DEVICE_SCANNER", + 0x0000001c => "FILE_DEVICE_SCREEN", + 0x00000037 => "FILE_DEVICE_SERENUM", + 0x0000001a => "FILE_DEVICE_SERIAL_MOUSE_PORT", + 0x0000001b => "FILE_DEVICE_SERIAL_PORT", + 0x00000031 => "FILE_DEVICE_SMARTCARD", + 0x0000002e => "FILE_DEVICE_SMB", + 0x0000001d => "FILE_DEVICE_SOUND", + 0x0000001e => "FILE_DEVICE_STREAMS", + 0x0000001f => "FILE_DEVICE_TAPE", + 0x00000020 => "FILE_DEVICE_TAPE_FILE_SYSTEM", + 0x00000038 => "FILE_DEVICE_TERMSRV", + 0x00000021 => "FILE_DEVICE_TRANSPORT", + 0x00000022 => "FILE_DEVICE_UNKNOWN", + 0x0000002c => "FILE_DEVICE_VDM", + 0x00000023 => "FILE_DEVICE_VIDEO", + 0x00000024 => "FILE_DEVICE_VIRTUAL_DISK", + 0x00000025 => "FILE_DEVICE_WAVE_IN", + 0x00000026 => "FILE_DEVICE_WAVE_OUT", + _ => "UNKNOWN" + }.to_string() +} + pub fn scan_eprocess(driver: &DriverState) -> BoxResult> { let mut result: Vec = Vec::new(); driver.scan_pool(b"Proc", "_EPROCESS", |pool_addr, header, data_addr| { @@ -268,13 +372,53 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult> { 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 = 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 = 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 = 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()), @@ -283,7 +427,13 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult> { "hardware": hardware, "major_function": major_function.into_iter() .map(|func| format!("0x{:x}", func)) - .collect::>() + .collect::>(), + "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) })?;