From d8b7e49048f69060d42240eea768ce7902e47de5 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 12 Jan 2025 22:21:36 +0100 Subject: [PATCH 01/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Display=20some=20meta?= =?UTF-8?q?data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index d70130c..2439afb 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -5,7 +5,12 @@ use crate::commands::{traces::Traces, Runnable}; use clap::Parser; use serde::Deserialize; -use std::{error::Error, fs::read_to_string, path::PathBuf}; +use std::{ + error::Error, + fmt::{Display, Formatter, Result as FormatResult}, + fs::read_to_string, + path::PathBuf, +}; use toml::from_str; #[derive(Deserialize)] @@ -22,6 +27,19 @@ struct Metadata { authors: Option>, } +impl Display for Metadata { + fn fmt(&self, formatter: &mut Formatter) -> FormatResult { + write!( + formatter, + "Generation file metadata\n\ + Name: {}\n\ + Version: {}\n\ + References: {:?}", + self.name, self.version, self.references + ) + } +} + #[derive(Deserialize)] struct Author { name: String, @@ -42,6 +60,8 @@ impl Runnable for Generate { let configuration: Configuration = from_str(read_to_string(self.path.clone())?.as_str())?; + println!("{}", configuration.metadata); + for trace in configuration.traces { trace.run()?; } From 913b5c531011e91ed9fac482a1ad28550ac43c54 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 12 Jan 2025 22:22:40 +0100 Subject: [PATCH 02/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Change=20clap=20help?= =?UTF-8?q?=20for=20the=20path=20argument=20in=20the=20generate=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 2439afb..cb35251 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -48,7 +48,7 @@ struct Author { #[derive(Parser)] pub struct Generate { - #[clap(required = true, help = "Path to the configuration file")] + #[clap(required = true, help = "Path to the generation file")] path: PathBuf, } From e5a08de6cabdb3a0bdd5b2576c44544f42465b56 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 12 Jan 2025 22:31:15 +0100 Subject: [PATCH 03/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Return=20an=20Error?= =?UTF-8?q?=20when=20the=20provided=20path=20is=20not=20valid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index cb35251..05eccfe 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -9,6 +9,7 @@ use std::{ error::Error, fmt::{Display, Formatter, Result as FormatResult}, fs::read_to_string, + io::{Error as IoError, ErrorKind::InvalidInput}, path::PathBuf, }; use toml::from_str; @@ -55,7 +56,10 @@ pub struct Generate { impl Runnable for Generate { fn run(&self) -> Result<(), Box> { if !self.path.try_exists()? || !self.path.is_file() { - return Ok(()); + return Err(Box::new(IoError::new( + InvalidInput, + "Provided path does not exists or isn't a file.", + ))); } let configuration: Configuration = from_str(read_to_string(self.path.clone())?.as_str())?; From 670f3164348ddf8cabb99fe6addaacb2463bb396 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 00:52:59 +0100 Subject: [PATCH 04/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20Display=20trait?= =?UTF-8?q?=20for=20Author=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 05eccfe..50d80b2 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -47,6 +47,23 @@ struct Author { email: Option, } +impl Display for Author { + fn fmt(&self, formatter: &mut Formatter) -> FormatResult { + let mut email_line: String = String::default(); + + if let Some(email) = &self.email { + email_line = format!("\nEmail: {}", email); + } + + write!( + formatter, + "Name: {}\ + {}", + self.name, email_line + ) + } +} + #[derive(Parser)] pub struct Generate { #[clap(required = true, help = "Path to the generation file")] From 919998f38d9cf2a6fc2cb9d073cefb99c04dcc8e Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 01:03:27 +0100 Subject: [PATCH 05/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20Display=20trait?= =?UTF-8?q?=20for=20Metadata=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 50d80b2..baea79b 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -30,13 +30,34 @@ struct Metadata { impl Display for Metadata { fn fmt(&self, formatter: &mut Formatter) -> FormatResult { + let mut authors_lines: String = String::default(); + + if let Some(authors) = &self.authors { + for (index, author) in authors.iter().enumerate() { + authors_lines.push_str( + format!( + "Author n°{}\n\ + {}", + index + 1, + author + ) + .as_str(), + ); + + if index != authors.len() - 1 { + authors_lines.push_str("\n\n"); + } + } + } + write!( formatter, - "Generation file metadata\n\ + "Metadata\n\ Name: {}\n\ Version: {}\n\ - References: {:?}", - self.name, self.version, self.references + References: {:#?}\n\n\ + {}", + self.name, self.version, self.references, authors_lines ) } } From c822a2dac400e83e1312e67c1a10d1a4f02b4653 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 01:06:22 +0100 Subject: [PATCH 06/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Change=20Confi?= =?UTF-8?q?guration=20structuture=20to=20"Generation"=20because=20it=20mak?= =?UTF-8?q?es=20more=20sens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index baea79b..cae8137 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -15,7 +15,7 @@ use std::{ use toml::from_str; #[derive(Deserialize)] -struct Configuration { +struct Generation { metadata: Metadata, traces: Vec, } @@ -100,11 +100,11 @@ impl Runnable for Generate { ))); } - let configuration: Configuration = from_str(read_to_string(self.path.clone())?.as_str())?; + let generation: Generation = from_str(read_to_string(self.path.clone())?.as_str())?; - println!("{}", configuration.metadata); + println!("{}", generation.metadata); - for trace in configuration.traces { + for trace in generation.traces { trace.run()?; } From 783298224e9e2fba675422177ff41c2e6d26f5c3 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 16:18:17 +0100 Subject: [PATCH 07/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20the=20R?= =?UTF-8?q?unnable=20trait=20return=20ExitCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/traces/processes.rs b/src/commands/traces/processes.rs index 2238f5f..744855b 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -5,7 +5,7 @@ use crate::commands::{traces::processes::spoofing::Spoofing, Runnable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::error::Error; +use std::{error::Error, process::ExitCode}; pub mod spoofing; @@ -23,7 +23,7 @@ pub enum Command { } impl Runnable for Processes { - fn run(&self) -> Result<(), Box> { + fn run(&self) -> ExitCode { match &self.command { Command::Spoofing(spoofing) => spoofing as &dyn Runnable, } From 0f615a11c3804423fce879ad780a051992357881 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 16:20:15 +0100 Subject: [PATCH 08/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Ok,=20the=20la?= =?UTF-8?q?st=20one=20was=20not=20the=20right=20file,=20but=20this=20time?= =?UTF-8?q?=20it's=20realy=20the=20Runnable=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 00450e7..9b174dd 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -8,7 +8,7 @@ use crate::commands::{ }; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::error::Error; +use std::{error::Error, process::ExitCode}; pub mod drivers; pub mod processes; @@ -28,7 +28,7 @@ pub enum Command { } impl Runnable for Traces { - fn run(&self) -> Result<(), Box> { + fn run(&self) -> ExitCode { match &self.command { Command::Drivers(drivers) => drivers as &dyn Runnable, Command::Processes(processes) => processes, From b4576d12af989e367f6126d258e16e2c57878225 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 16:21:53 +0100 Subject: [PATCH 09/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20the=20D?= =?UTF-8?q?rivers=20structure=20return=20the=20right=20type=20for=20the=20?= =?UTF-8?q?run=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/traces/drivers.rs b/src/commands/traces/drivers.rs index b0b3582..77da41f 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -5,7 +5,7 @@ use crate::commands::{traces::drivers::byovd::Byovd, Runnable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::error::Error; +use std::{error::Error, process::ExitCode}; pub mod byovd; @@ -23,7 +23,7 @@ pub enum Command { } impl Runnable for Drivers { - fn run(&self) -> Result<(), Box> { + fn run(&self) -> ExitCode { match &self.command { Command::Byovd(byovd) => byovd as &dyn Runnable, } From 79f0664d072ba4125b5ea0c74f14e8bd42c28411 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 16:33:25 +0100 Subject: [PATCH 10/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20the=20R?= =?UTF-8?q?unnable=20trait=20return=20ExitCode=20(for=20real=20this=20time?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 8835879..3920563 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -7,7 +7,7 @@ pub mod traces; use crate::commands::{generate::Generate, traces::Traces}; use clap::{Parser, Subcommand}; -use std::error::Error; +use std::{error::Error, process::ExitCode}; #[derive(Parser)] #[clap(author, version)] @@ -24,11 +24,11 @@ pub enum Command { } pub trait Runnable { - fn run(&self) -> Result<(), Box>; + fn run(&self) -> ExitCode; } impl Runnable for Arguments { - fn run(&self) -> Result<(), Box> { + fn run(&self) -> ExitCode { match &self.command { Command::Traces(traces) => traces as &dyn Runnable, Command::Generate(generate) => generate, From 65bd4c4a794476ecde563e584c9cb229715698e7 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 16:34:43 +0100 Subject: [PATCH 11/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20entry?= =?UTF-8?q?=20point=20return=20ExitCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8b41b3b..f852dd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,8 +7,8 @@ mod windows; use clap::Parser; use commands::{Arguments, Runnable}; -use std::error::Error; +use std::{error::Error, process::ExitCode}; -fn main() -> Result<(), Box> { +fn main() -> ExitCode { Arguments::parse().run() } From ac2a406d98dbe1ac20ad32262e810d5448df391c Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 17:55:05 +0100 Subject: [PATCH 12/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20byovd?= =?UTF-8?q?=20return=20ExitCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove OpenServiceW because we can handle "service already exists" via error codes of CreateServiceW. --- src/commands/traces/drivers/byovd.rs | 53 +++++++++++++++------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9c8552e..0ec4bab 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -5,7 +5,7 @@ use crate::{commands::Runnable, windows::users::is_administrator}; use clap::Parser; use serde::Deserialize; -use std::{error::Error, path::PathBuf}; +use std::{error::Error, path::PathBuf, process::ExitCode}; use windows::{ core::{Owned, HSTRING, PCWSTR}, Win32::{ @@ -29,33 +29,31 @@ pub struct Byovd { } impl Runnable for Byovd { - fn run(&self) -> Result<(), Box> { - if !is_administrator()? { - return Ok(()); + fn run(&self) -> ExitCode { + let Ok(is_administrator) = is_administrator() else { + return ExitCode::FAILURE; + }; + + if !is_administrator { + return ExitCode::FAILURE; } - if !self.path.try_exists()? || !self.path.is_file() { - return Ok(()); + let Ok(path_exists) = self.path.try_exists() else { + return ExitCode::FAILURE; + }; + + if !path_exists || !self.path.is_file() { + return ExitCode::FAILURE; } unsafe { - let service_manager: Owned = Owned::new(OpenSCManagerW( - PCWSTR::null(), - PCWSTR::null(), - SC_MANAGER_CREATE_SERVICE, - )?); - - if OpenServiceW( - *service_manager, - &HSTRING::from(self.service_name.as_str()), - GENERIC_READ.0, - ) - .is_ok() - { - return Ok(()); - } + let service_manager: Owned = + match OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) { + Ok(handle) => Owned::new(handle), + Err(_) => return ExitCode::FAILURE, + }; - let service: Owned = Owned::new(CreateServiceW( + let service: Owned = match CreateServiceW( *service_manager, &HSTRING::from(self.service_name.as_str()), &HSTRING::from(self.displayed_name.as_str()), @@ -69,9 +67,16 @@ impl Runnable for Byovd { PCWSTR::null(), PCWSTR::null(), PCWSTR::null(), - )?); + ) { + Ok(handle) => Owned::new(handle), + Err(_) => return ExitCode::FAILURE, + }; - Ok(StartServiceW(*service, None)?) + if let Err(_) = StartServiceW(*service, None) { + return ExitCode::FAILURE; + } } + + ExitCode::SUCCESS } } From 271d68abd25d3b7a2f95ec01175589b30aefb5c6 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 18:37:48 +0100 Subject: [PATCH 13/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20spoofin?= =?UTF-8?q?g=20return=20ExitCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 51 +++++++++++++++-------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 5ce0a1f..86a22a6 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -7,10 +7,10 @@ use clap::Parser; use serde::Deserialize; use std::{ error::Error, ffi::OsString, iter::once, mem::size_of, os::windows::ffi::OsStrExt, - path::PathBuf, + path::PathBuf, process::ExitCode, }; use windows::{ - core::{Owned, PWSTR}, + core::{Owned, Result as WindowsResult, PWSTR}, Win32::{ Foundation::HANDLE, System::Threading::{ @@ -31,15 +31,19 @@ pub struct Spoofing { } impl Runnable for Spoofing { - fn run(&self) -> Result<(), Box> { - if !self.executable.try_exists()? || !self.executable.is_file() { - return Ok(()); + fn run(&self) -> ExitCode { + let Ok(path_exists) = self.executable.try_exists() else { + return ExitCode::FAILURE; + }; + + if !path_exists || !self.executable.is_file() { + return ExitCode::FAILURE; } let mut required_size: usize = 0; unsafe { - let _ = InitializeProcThreadAttributeList( + let _: WindowsResult<()> = InitializeProcThreadAttributeList( LPPROC_THREAD_ATTRIBUTE_LIST::default(), 1, 0, @@ -62,19 +66,26 @@ impl Runnable for Spoofing { }; unsafe { - InitializeProcThreadAttributeList( + if let Err(_) = InitializeProcThreadAttributeList( startup_informations.lpAttributeList, 1, 0, &mut required_size, - )?; + ) { + return ExitCode::FAILURE; + } - let mut parent_process: Owned = Owned::new(OpenProcess( - PROCESS_CREATE_PROCESS, - false, - get_pid(self.parent_executable.as_str())?, - )?); - UpdateProcThreadAttribute( + let Ok(parent_process_identifier) = get_pid(self.parent_executable.as_str()) else { + return ExitCode::FAILURE; + }; + + let mut parent_process: Owned = + match OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) { + Ok(handle) => Owned::new(handle), + Err(_) => return ExitCode::FAILURE, + }; + + if let Err(_) = UpdateProcThreadAttribute( startup_informations.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS as usize, @@ -82,9 +93,11 @@ impl Runnable for Spoofing { size_of::(), None, None, - )?; + ) { + return ExitCode::FAILURE; + } - CreateProcessW( + if let Err(_) = CreateProcessW( None, PWSTR( OsString::from(self.executable.as_os_str()) @@ -101,9 +114,11 @@ impl Runnable for Spoofing { None, &startup_informations.StartupInfo, &mut PROCESS_INFORMATION::default(), - )?; + ) { + return ExitCode::FAILURE; + } }; - Ok(()) + ExitCode::SUCCESS } } From c1639c38b904e56d32382d06c0d8738fa44307bb Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 18:40:41 +0100 Subject: [PATCH 14/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20unuse?= =?UTF-8?q?d=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 2 +- src/commands/traces.rs | 2 +- src/commands/traces/drivers.rs | 2 +- src/commands/traces/drivers/byovd.rs | 12 ++++-------- src/commands/traces/processes.rs | 2 +- src/commands/traces/processes/spoofing.rs | 4 ++-- src/main.rs | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 3920563..95c01b3 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -7,7 +7,7 @@ pub mod traces; use crate::commands::{generate::Generate, traces::Traces}; use clap::{Parser, Subcommand}; -use std::{error::Error, process::ExitCode}; +use std::process::ExitCode; #[derive(Parser)] #[clap(author, version)] diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 9b174dd..97d0578 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -8,7 +8,7 @@ use crate::commands::{ }; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::{error::Error, process::ExitCode}; +use std::process::ExitCode; pub mod drivers; pub mod processes; diff --git a/src/commands/traces/drivers.rs b/src/commands/traces/drivers.rs index 77da41f..bff8d89 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -5,7 +5,7 @@ use crate::commands::{traces::drivers::byovd::Byovd, Runnable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::{error::Error, process::ExitCode}; +use std::process::ExitCode; pub mod byovd; diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 0ec4bab..9e8dfb2 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -5,16 +5,12 @@ use crate::{commands::Runnable, windows::users::is_administrator}; use clap::Parser; use serde::Deserialize; -use std::{error::Error, path::PathBuf, process::ExitCode}; +use std::{path::PathBuf, process::ExitCode}; use windows::{ core::{Owned, HSTRING, PCWSTR}, - Win32::{ - Foundation::GENERIC_READ, - System::Services::{ - CreateServiceW, OpenSCManagerW, OpenServiceW, StartServiceW, SC_HANDLE, - SC_MANAGER_ALL_ACCESS, SC_MANAGER_CREATE_SERVICE, SERVICE_AUTO_START, - SERVICE_ERROR_IGNORE, SERVICE_KERNEL_DRIVER, - }, + Win32::System::Services::{ + CreateServiceW, OpenSCManagerW, StartServiceW, SC_HANDLE, SC_MANAGER_ALL_ACCESS, + SC_MANAGER_CREATE_SERVICE, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, SERVICE_KERNEL_DRIVER, }, }; diff --git a/src/commands/traces/processes.rs b/src/commands/traces/processes.rs index 744855b..af85f00 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -5,7 +5,7 @@ use crate::commands::{traces::processes::spoofing::Spoofing, Runnable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::{error::Error, process::ExitCode}; +use std::process::ExitCode; pub mod spoofing; diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 86a22a6..d1eedf1 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -6,8 +6,8 @@ use crate::{commands::Runnable, windows::processes::get_pid}; use clap::Parser; use serde::Deserialize; use std::{ - error::Error, ffi::OsString, iter::once, mem::size_of, os::windows::ffi::OsStrExt, - path::PathBuf, process::ExitCode, + ffi::OsString, iter::once, mem::size_of, os::windows::ffi::OsStrExt, path::PathBuf, + process::ExitCode, }; use windows::{ core::{Owned, Result as WindowsResult, PWSTR}, diff --git a/src/main.rs b/src/main.rs index f852dd4..51364c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ mod windows; use clap::Parser; use commands::{Arguments, Runnable}; -use std::{error::Error, process::ExitCode}; +use std::process::ExitCode; fn main() -> ExitCode { Arguments::parse().run() From 8799fb81cd7ea8c0473ae1e97ef47b8c6d17775e Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 18:49:35 +0100 Subject: [PATCH 15/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Make=20Generat?= =?UTF-8?q?e=20return=20ExitCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index cae8137..01578be 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -6,13 +6,12 @@ use crate::commands::{traces::Traces, Runnable}; use clap::Parser; use serde::Deserialize; use std::{ - error::Error, fmt::{Display, Formatter, Result as FormatResult}, fs::read_to_string, - io::{Error as IoError, ErrorKind::InvalidInput}, path::PathBuf, + process::ExitCode, }; -use toml::from_str; +use toml::{de::Error as TomlError, from_str}; #[derive(Deserialize)] struct Generation { @@ -92,22 +91,31 @@ pub struct Generate { } impl Runnable for Generate { - fn run(&self) -> Result<(), Box> { - if !self.path.try_exists()? || !self.path.is_file() { - return Err(Box::new(IoError::new( - InvalidInput, - "Provided path does not exists or isn't a file.", - ))); + fn run(&self) -> ExitCode { + let Ok(path_exists) = self.path.try_exists() else { + return ExitCode::FAILURE; + }; + + if !path_exists || !self.path.is_file() { + return ExitCode::FAILURE; } - let generation: Generation = from_str(read_to_string(self.path.clone())?.as_str())?; + let Ok(file_content) = read_to_string(self.path.clone()) else { + return ExitCode::FAILURE; + }; + + let Ok(generation): Result = from_str(file_content.as_str()) else { + return ExitCode::FAILURE; + }; println!("{}", generation.metadata); for trace in generation.traces { - trace.run()?; + if trace.run() == ExitCode::FAILURE { + return ExitCode::FAILURE; + } } - Ok(()) + ExitCode::SUCCESS } } From 203639e8fdbfc136b4b9937d7729c561030339b0 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 20:44:31 +0100 Subject: [PATCH 16/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Respect=20impo?= =?UTF-8?q?rts/modules=20declaration's=20ordering=20from=20Rust=20style=20?= =?UTF-8?q?guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 6 +++--- src/main.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 95c01b3..d756c84 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -2,13 +2,13 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -pub mod generate; -pub mod traces; - use crate::commands::{generate::Generate, traces::Traces}; use clap::{Parser, Subcommand}; use std::process::ExitCode; +pub mod generate; +pub mod traces; + #[derive(Parser)] #[clap(author, version)] #[clap(arg_required_else_help = true)] diff --git a/src/main.rs b/src/main.rs index 51364c4..169734e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,13 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -mod commands; -mod windows; - use clap::Parser; use commands::{Arguments, Runnable}; use std::process::ExitCode; +mod commands; +mod windows; + fn main() -> ExitCode { Arguments::parse().run() } From aba56cbcb0a3e2cc0db63ba9306d720c4bf6ebe3 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 20:49:43 +0100 Subject: [PATCH 17/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Respect=20decl?= =?UTF-8?q?aration=20ordering=20as=20the=20Rust=20style=20guide=20says?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 01578be..720baf7 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -27,6 +27,18 @@ struct Metadata { authors: Option>, } +#[derive(Deserialize)] +struct Author { + name: String, + email: Option, +} + +#[derive(Parser)] +pub struct Generate { + #[clap(required = true, help = "Path to the generation file")] + path: PathBuf, +} + impl Display for Metadata { fn fmt(&self, formatter: &mut Formatter) -> FormatResult { let mut authors_lines: String = String::default(); @@ -61,12 +73,6 @@ impl Display for Metadata { } } -#[derive(Deserialize)] -struct Author { - name: String, - email: Option, -} - impl Display for Author { fn fmt(&self, formatter: &mut Formatter) -> FormatResult { let mut email_line: String = String::default(); @@ -84,12 +90,6 @@ impl Display for Author { } } -#[derive(Parser)] -pub struct Generate { - #[clap(required = true, help = "Path to the generation file")] - path: PathBuf, -} - impl Runnable for Generate { fn run(&self) -> ExitCode { let Ok(path_exists) = self.path.try_exists() else { From 795911fda3d65c62e979f0ae79eb52b6579b1871 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 17 Jan 2025 20:53:26 +0100 Subject: [PATCH 18/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Put=20modules?= =?UTF-8?q?=20visibility=20in=20private=20as=20much=20as=20possible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 4 ++-- src/commands/traces.rs | 4 ++-- src/commands/traces/drivers.rs | 2 +- src/commands/traces/processes.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index d756c84..e60c292 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -6,8 +6,8 @@ use crate::commands::{generate::Generate, traces::Traces}; use clap::{Parser, Subcommand}; use std::process::ExitCode; -pub mod generate; -pub mod traces; +mod generate; +mod traces; #[derive(Parser)] #[clap(author, version)] diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 97d0578..31cef35 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -10,8 +10,8 @@ use clap::{Args, Subcommand}; use serde::Deserialize; use std::process::ExitCode; -pub mod drivers; -pub mod processes; +mod drivers; +mod processes; #[derive(Args, Deserialize)] pub struct Traces { diff --git a/src/commands/traces/drivers.rs b/src/commands/traces/drivers.rs index bff8d89..b06049f 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -7,7 +7,7 @@ use clap::{Args, Subcommand}; use serde::Deserialize; use std::process::ExitCode; -pub mod byovd; +mod byovd; #[derive(Args, Deserialize)] pub struct Drivers { diff --git a/src/commands/traces/processes.rs b/src/commands/traces/processes.rs index af85f00..7ec821b 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -7,7 +7,7 @@ use clap::{Args, Subcommand}; use serde::Deserialize; use std::process::ExitCode; -pub mod spoofing; +mod spoofing; #[derive(Args, Deserialize)] pub struct Processes { From 9215bff06b5cd3eeb26fe49fe933bb36ed4520ea Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 18 Jan 2025 01:53:52 +0100 Subject: [PATCH 19/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Rename=20comma?= =?UTF-8?q?nd=20to=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 8 ++++---- src/commands/traces.rs | 6 +++--- src/commands/traces/drivers.rs | 6 +++--- src/commands/traces/processes.rs | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index e60c292..8f7c863 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -14,11 +14,11 @@ mod traces; #[clap(arg_required_else_help = true)] pub struct Arguments { #[clap(subcommand)] - pub command: Command, + pub command: Commands, } #[derive(Subcommand)] -pub enum Command { +pub enum Commands { Traces(Traces), Generate(Generate), } @@ -30,8 +30,8 @@ pub trait Runnable { impl Runnable for Arguments { fn run(&self) -> ExitCode { match &self.command { - Command::Traces(traces) => traces as &dyn Runnable, - Command::Generate(generate) => generate, + Commands::Traces(traces) => traces as &dyn Runnable, + Commands::Generate(generate) => generate, } .run() } diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 31cef35..e30eefc 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -17,7 +17,7 @@ mod processes; pub struct Traces { #[clap(subcommand)] #[serde(flatten)] - pub command: Command, + pub command: Commands, } #[derive(Subcommand, Deserialize)] @@ -30,8 +30,8 @@ pub enum Command { impl Runnable for Traces { fn run(&self) -> ExitCode { match &self.command { - Command::Drivers(drivers) => drivers as &dyn Runnable, - Command::Processes(processes) => processes, + Commands::Drivers(drivers) => drivers as &dyn Runnable, + Commands::Processes(processes) => processes, } .run() } diff --git a/src/commands/traces/drivers.rs b/src/commands/traces/drivers.rs index b06049f..16ff97d 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -13,19 +13,19 @@ mod byovd; pub struct Drivers { #[clap(subcommand)] #[serde(flatten)] - pub command: Command, + pub command: Commands, } #[derive(Subcommand, Deserialize)] #[serde(rename_all = "snake_case")] -pub enum Command { +pub enum Commands { Byovd(Byovd), } impl Runnable for Drivers { fn run(&self) -> ExitCode { match &self.command { - Command::Byovd(byovd) => byovd as &dyn Runnable, + Commands::Byovd(byovd) => byovd as &dyn Runnable, } .run() } diff --git a/src/commands/traces/processes.rs b/src/commands/traces/processes.rs index 7ec821b..aa1dd6e 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -13,19 +13,19 @@ mod spoofing; pub struct Processes { #[clap(subcommand)] #[serde(flatten)] - pub command: Command, + pub command: Commands, } #[derive(Subcommand, Deserialize)] #[serde(rename_all = "snake_case")] -pub enum Command { +pub enum Commands { Spoofing(Spoofing), } impl Runnable for Processes { fn run(&self) -> ExitCode { match &self.command { - Command::Spoofing(spoofing) => spoofing as &dyn Runnable, + Commands::Spoofing(spoofing) => spoofing as &dyn Runnable, } .run() } From 57cfe1736a987928195c5f20a96fe890edce4eb0 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 18 Jan 2025 14:12:12 +0100 Subject: [PATCH 20/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Add=20missing?= =?UTF-8?q?=20renaming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/traces.rs b/src/commands/traces.rs index e30eefc..7566a79 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -22,7 +22,7 @@ pub struct Traces { #[derive(Subcommand, Deserialize)] #[serde(rename_all = "snake_case", untagged)] -pub enum Command { +pub enum Commands { Drivers(Drivers), Processes(Processes), } From ecd7fe5cb878fd770279ffa1b13fb3f4338dc8ae Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 19 Jan 2025 16:57:57 +0100 Subject: [PATCH 21/61] =?UTF-8?q?build:=20=F0=9F=93=A6=20Add=20indicatif?= =?UTF-8?q?=20and=20console?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index bd36025..4a78813 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,8 @@ rand = "0.8.5" regex_generate = "0.2.3" toml = "0.8.19" serde = { version = "1.0.214", features = ["derive"] } +indicatif = { version = "0.17.9" } +console = { version = "0.15.10" } [build-dependencies] embed-resource = "3.0.1" From 90ab28447c5416ec4552a4b682b068bd46fa3f50 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 19 Jan 2025 18:07:17 +0100 Subject: [PATCH 22/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20a=20displayer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/displayer.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/displayer.rs diff --git a/src/displayer.rs b/src/displayer.rs new file mode 100644 index 0000000..bd347ec --- /dev/null +++ b/src/displayer.rs @@ -0,0 +1,109 @@ +use console::{Emoji, Style}; +use indicatif::{ProgressBar, ProgressStyle}; +use std::{borrow::Cow, fmt::Display, time::Duration}; + +pub struct Displayer { + spinner: ProgressBar, + emojis: Emojis, + styles: Styles, +} + +pub struct Emojis { + pub success: Emoji<'static, 'static>, + pub failure: Emoji<'static, 'static>, +} + +pub struct Styles { + pub success: Style, + pub failure: Style, +} + +impl Displayer { + pub fn new(spinner: ProgressBar, emojis: Emojis, styles: Styles) -> Self { + Self { + spinner, + emojis, + styles, + } + } + + pub fn loading(&mut self, message: impl Into> + Display) { + self.stop(); + + self.spinner.set_message(message); + self.spinner.enable_steady_tick(Duration::from_millis(100)); + } + + pub fn success(&mut self, message: impl Into> + Display) { + self.stop(); + + println!( + "{}", + self.format(&self.emojis.success, &self.styles.success, message) + ); + } + + pub fn failure(&mut self, message: impl Into> + Display) { + self.stop(); + + eprintln!( + "{}", + self.format(&self.emojis.failure, &self.styles.failure, message) + ); + } + + fn stop(&mut self) { + self.spinner.finish_and_clear(); + self.spinner = ProgressBar::new_spinner().with_style(self.spinner.style()); + } + + fn format( + &self, + emoji: &Emoji<'_, '_>, + style: &Style, + message: impl Into> + Display, + ) -> String { + format!("{}{}", style.apply_to(emoji), message) + } +} + +impl Default for Displayer { + fn default() -> Self { + Self { + spinner: ProgressBar::new_spinner() + .with_style(ProgressStyle::with_template("{spinner:.yellow.bold} {msg}").unwrap()), + emojis: Emojis::default(), + styles: Styles::default(), + } + } +} + +impl Emojis { + fn new(success: Emoji<'static, 'static>, failure: Emoji<'static, 'static>) -> Self { + Self { success, failure } + } +} + +impl Default for Emojis { + fn default() -> Self { + Self { + success: Emoji("✔️ ", ""), + failure: Emoji("❌ ", ""), + } + } +} + +impl Styles { + fn new(success: Style, failure: Style) -> Self { + Self { success, failure } + } +} + +impl Default for Styles { + fn default() -> Self { + Self { + success: Style::new().green().bold(), + failure: Style::new().red().bold().for_stderr(), + } + } +} From 1ec5a9848a73f3da14db2689d41a70d13f005291 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 19 Jan 2025 18:45:46 +0100 Subject: [PATCH 23/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20displayer=20mod?= =?UTF-8?q?ule=20declaration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index 169734e..72ccc1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use commands::{Arguments, Runnable}; use std::process::ExitCode; mod commands; +mod displayer; mod windows; fn main() -> ExitCode { From 9e8bdbe2935f8c6948845ebeb14c7b744e329894 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 19 Jan 2025 19:13:17 +0100 Subject: [PATCH 24/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Remove=20unused=20new?= =?UTF-8?q?=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/displayer.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/displayer.rs b/src/displayer.rs index bd347ec..238505a 100644 --- a/src/displayer.rs +++ b/src/displayer.rs @@ -19,14 +19,6 @@ pub struct Styles { } impl Displayer { - pub fn new(spinner: ProgressBar, emojis: Emojis, styles: Styles) -> Self { - Self { - spinner, - emojis, - styles, - } - } - pub fn loading(&mut self, message: impl Into> + Display) { self.stop(); @@ -78,12 +70,6 @@ impl Default for Displayer { } } -impl Emojis { - fn new(success: Emoji<'static, 'static>, failure: Emoji<'static, 'static>) -> Self { - Self { success, failure } - } -} - impl Default for Emojis { fn default() -> Self { Self { @@ -93,12 +79,6 @@ impl Default for Emojis { } } -impl Styles { - fn new(success: Style, failure: Style) -> Self { - Self { success, failure } - } -} - impl Default for Styles { fn default() -> Self { Self { From 51dda0769f3178f2bd1fb1f389e6f1fc91b47f41 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 19 Jan 2025 19:13:57 +0100 Subject: [PATCH 25/61] =?UTF-8?q?chore:=20=F0=9F=A7=B9=20Add=20SPDX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/displayer.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/displayer.rs b/src/displayer.rs index 238505a..d0f038a 100644 --- a/src/displayer.rs +++ b/src/displayer.rs @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 The MalwareTracesGenerator development team +// +// SPDX-License-Identifier: GPL-3.0-or-later + use console::{Emoji, Style}; use indicatif::{ProgressBar, ProgressStyle}; use std::{borrow::Cow, fmt::Display, time::Duration}; From 87d0fd8ee33ac9c761ea92980de646df7cea88c0 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Mon, 20 Jan 2025 18:35:45 +0100 Subject: [PATCH 26/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20Trace=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces.rs | 5 +++++ src/commands/traces/drivers/byovd.rs | 15 ++++++++++++++- src/commands/traces/processes/spoofing.rs | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 7566a79..8a23b64 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -27,6 +27,11 @@ pub enum Commands { Processes(Processes), } +pub trait Trace: Runnable { + fn name(&self) -> &str; + fn as_runnable(&self) -> &dyn Runnable; +} + impl Runnable for Traces { fn run(&self) -> ExitCode { match &self.command { diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9e8dfb2..121b653 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::{commands::Runnable, windows::users::is_administrator}; +use crate::{ + commands::{traces::Trace, Runnable}, + windows::users::is_administrator, +}; use clap::Parser; use serde::Deserialize; use std::{path::PathBuf, process::ExitCode}; @@ -76,3 +79,13 @@ impl Runnable for Byovd { ExitCode::SUCCESS } } + +impl Trace for Byovd { + fn name(&self) -> &str { + "Bring Your Own Vulnerable Driver" + } + + fn as_runnable(&self) -> &dyn Runnable { + self + } +} diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index d1eedf1..ef4e7b9 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::{commands::Runnable, windows::processes::get_pid}; +use crate::{ + commands::{traces::Trace, Runnable}, + windows::processes::get_pid, +}; use clap::Parser; use serde::Deserialize; use std::{ @@ -122,3 +125,13 @@ impl Runnable for Spoofing { ExitCode::SUCCESS } } + +impl Trace for Spoofing { + fn name(&self) -> &str { + "Spoofing" + } + + fn as_runnable(&self) -> &dyn Runnable { + self + } +} From a6c93613b9df45ff0aa0c92c649b8d36a5cb639b Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Mon, 20 Jan 2025 18:46:09 +0100 Subject: [PATCH 27/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20traversable=20t?= =?UTF-8?q?rait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands.rs | 16 +++++++++++----- src/commands/traces.rs | 13 ++++++++----- src/commands/traces/drivers.rs | 10 ++++------ src/commands/traces/processes.rs | 10 ++++------ src/main.rs | 4 ++-- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 8f7c863..f4d8262 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{generate::Generate, traces::Traces}; +use crate::commands::{ + generate::Generate, + traces::{Traces, Traversable as TracesTraversable}, +}; use clap::{Parser, Subcommand}; use std::process::ExitCode; @@ -23,16 +26,19 @@ pub enum Commands { Generate(Generate), } +pub trait Traversable { + fn traverse(&self) -> &dyn Runnable; +} + pub trait Runnable { fn run(&self) -> ExitCode; } -impl Runnable for Arguments { - fn run(&self) -> ExitCode { +impl Traversable for Arguments { + fn traverse(&self) -> &dyn Runnable { match &self.command { - Commands::Traces(traces) => traces as &dyn Runnable, + Commands::Traces(traces) => traces.traverse().as_runnable(), Commands::Generate(generate) => generate, } - .run() } } diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 8a23b64..1483cc2 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -8,7 +8,6 @@ use crate::commands::{ }; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::process::ExitCode; mod drivers; mod processes; @@ -32,12 +31,16 @@ pub trait Trace: Runnable { fn as_runnable(&self) -> &dyn Runnable; } -impl Runnable for Traces { - fn run(&self) -> ExitCode { +pub trait Traversable { + fn traverse(&self) -> &dyn Trace; +} + +impl Traversable for Traces { + fn traverse(&self) -> &dyn Trace { match &self.command { - Commands::Drivers(drivers) => drivers as &dyn Runnable, + Commands::Drivers(drivers) => drivers as &dyn Traversable, Commands::Processes(processes) => processes, } - .run() + .traverse() } } diff --git a/src/commands/traces/drivers.rs b/src/commands/traces/drivers.rs index 16ff97d..36e1fdf 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -2,10 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{traces::drivers::byovd::Byovd, Runnable}; +use crate::commands::traces::{drivers::byovd::Byovd, Trace, Traversable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::process::ExitCode; mod byovd; @@ -22,11 +21,10 @@ pub enum Commands { Byovd(Byovd), } -impl Runnable for Drivers { - fn run(&self) -> ExitCode { +impl Traversable for Drivers { + fn traverse(&self) -> &dyn Trace { match &self.command { - Commands::Byovd(byovd) => byovd as &dyn Runnable, + Commands::Byovd(byovd) => byovd, } - .run() } } diff --git a/src/commands/traces/processes.rs b/src/commands/traces/processes.rs index aa1dd6e..2dd8b6d 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -2,10 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{traces::processes::spoofing::Spoofing, Runnable}; +use crate::commands::traces::{processes::spoofing::Spoofing, Trace, Traversable}; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::process::ExitCode; mod spoofing; @@ -22,11 +21,10 @@ pub enum Commands { Spoofing(Spoofing), } -impl Runnable for Processes { - fn run(&self) -> ExitCode { +impl Traversable for Processes { + fn traverse(&self) -> &dyn Trace { match &self.command { - Commands::Spoofing(spoofing) => spoofing as &dyn Runnable, + Commands::Spoofing(spoofing) => spoofing, } - .run() } } diff --git a/src/main.rs b/src/main.rs index 72ccc1a..59e1298 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use clap::Parser; -use commands::{Arguments, Runnable}; +use commands::{Arguments, Traversable}; use std::process::ExitCode; mod commands; @@ -11,5 +11,5 @@ mod displayer; mod windows; fn main() -> ExitCode { - Arguments::parse().run() + Arguments::parse().traverse().run() } From 7f0770d5ca771251956d19b4114d2caae5f32647 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 21 Jan 2025 00:29:56 +0100 Subject: [PATCH 28/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Print=20the=20name=20?= =?UTF-8?q?of=20the=20trace=20being=20generated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 720baf7..1b914b1 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{traces::Traces, Runnable}; +use crate::commands::{ + traces::{Trace, Traces, Traversable}, + Runnable, +}; use clap::Parser; use serde::Deserialize; use std::{ @@ -16,7 +19,8 @@ use toml::{de::Error as TomlError, from_str}; #[derive(Deserialize)] struct Generation { metadata: Metadata, - traces: Vec, + #[serde(rename(deserialize = "traces"))] + commands: Vec, } #[derive(Deserialize)] @@ -110,7 +114,16 @@ impl Runnable for Generate { println!("{}", generation.metadata); - for trace in generation.traces { + for (index, command) in generation.commands.iter().enumerate() { + let trace: &dyn Trace = command.traverse(); + + println!( + "\n[{}/{}] Generating {} trace", + index + 1, + generation.commands.len(), + trace.name(), + ); + if trace.run() == ExitCode::FAILURE { return ExitCode::FAILURE; } From adc1c209a12538da011a3436ddd1f407089bad12 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 21 Jan 2025 21:54:11 +0100 Subject: [PATCH 29/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20display=20to=20?= =?UTF-8?q?the=20byovd=20trace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 61 ++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 121b653..bb64532 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -4,6 +4,7 @@ use crate::{ commands::{traces::Trace, Runnable}, + displayer::Displayer, windows::users::is_administrator, }; use clap::Parser; @@ -29,30 +30,55 @@ pub struct Byovd { impl Runnable for Byovd { fn run(&self) -> ExitCode { + let mut displayer: Displayer = Displayer::default(); + displayer.loading("Checking administrator privileges"); + let Ok(is_administrator) = is_administrator() else { + displayer.failure("Could not check administrator privileges"); + return ExitCode::FAILURE; }; if !is_administrator { + displayer.failure("The application needs administrator privileges to run this trace"); + return ExitCode::FAILURE; } + displayer.success("The application has administrator privileges"); + displayer.loading("Checking the driver path validity"); + let Ok(path_exists) = self.path.try_exists() else { + displayer.failure("Could not verify existence of driver path"); + return ExitCode::FAILURE; }; if !path_exists || !self.path.is_file() { + displayer.failure("Driver path does not exist or is not a file path"); + return ExitCode::FAILURE; } - unsafe { - let service_manager: Owned = - match OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) { - Ok(handle) => Owned::new(handle), - Err(_) => return ExitCode::FAILURE, - }; + displayer.success("Driver path is valid"); + displayer.loading("Creating the service manager"); + + let service_manager: Owned = match unsafe { + OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(_) => { + displayer.failure("Could not create the service manager"); + + return ExitCode::FAILURE; + } + }; + + displayer.success("Service manager created"); + displayer.loading("Creating the driver service"); - let service: Owned = match CreateServiceW( + let service: Owned = match unsafe { + CreateServiceW( *service_manager, &HSTRING::from(self.service_name.as_str()), &HSTRING::from(self.displayed_name.as_str()), @@ -66,16 +92,27 @@ impl Runnable for Byovd { PCWSTR::null(), PCWSTR::null(), PCWSTR::null(), - ) { - Ok(handle) => Owned::new(handle), - Err(_) => return ExitCode::FAILURE, - }; + ) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(_) => { + displayer.failure("Could not create the driver service"); - if let Err(_) = StartServiceW(*service, None) { return ExitCode::FAILURE; } + }; + + displayer.success("Driver service created"); + displayer.loading("Starting the driver service"); + + if let Err(_) = unsafe { StartServiceW(*service, None) } { + displayer.failure("Could not start the driver service"); + + return ExitCode::FAILURE; } + displayer.success("Driver service started"); + ExitCode::SUCCESS } } From 44953d7e0e03d74cdb660610b6b2a35d77f9af02 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 21 Jan 2025 23:02:38 +0100 Subject: [PATCH 30/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Improve=20english=20(?= =?UTF-8?q?I=20hope)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index bb64532..4b5713a 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -49,18 +49,18 @@ impl Runnable for Byovd { displayer.loading("Checking the driver path validity"); let Ok(path_exists) = self.path.try_exists() else { - displayer.failure("Could not verify existence of driver path"); + displayer.failure("Could not check the existence of the driver path"); return ExitCode::FAILURE; }; if !path_exists || !self.path.is_file() { - displayer.failure("Driver path does not exist or is not a file path"); + displayer.failure("The driver path does not exist or is not a file path"); return ExitCode::FAILURE; } - displayer.success("Driver path is valid"); + displayer.success("The driver path is valid"); displayer.loading("Creating the service manager"); let service_manager: Owned = match unsafe { @@ -74,7 +74,7 @@ impl Runnable for Byovd { } }; - displayer.success("Service manager created"); + displayer.success("The service manager is created"); displayer.loading("Creating the driver service"); let service: Owned = match unsafe { @@ -102,7 +102,7 @@ impl Runnable for Byovd { } }; - displayer.success("Driver service created"); + displayer.success("The driver service is created"); displayer.loading("Starting the driver service"); if let Err(_) = unsafe { StartServiceW(*service, None) } { @@ -111,7 +111,7 @@ impl Runnable for Byovd { return ExitCode::FAILURE; } - displayer.success("Driver service started"); + displayer.success("The driver service is started"); ExitCode::SUCCESS } From bdbeeaae877291f113f92a1da52559c52a62f432 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 28 Jan 2025 22:46:52 +0100 Subject: [PATCH 31/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Do=20not=20put?= =?UTF-8?q?=20type=20information=20in=20the=20variable=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 4b5713a..9b6c0b1 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -20,12 +20,12 @@ use windows::{ #[derive(Parser, Deserialize)] pub struct Byovd { + #[clap(required = true, help = "Path to the driver")] + driver: PathBuf, #[clap(required = true, help = "Name of the service")] service_name: String, #[clap(required = true, help = "Displayed name of the service")] displayed_name: String, - #[clap(required = true, help = "Path to the driver")] - path: PathBuf, } impl Runnable for Byovd { @@ -48,13 +48,13 @@ impl Runnable for Byovd { displayer.success("The application has administrator privileges"); displayer.loading("Checking the driver path validity"); - let Ok(path_exists) = self.path.try_exists() else { + let Ok(driver_exists) = self.driver.try_exists() else { displayer.failure("Could not check the existence of the driver path"); return ExitCode::FAILURE; }; - if !path_exists || !self.path.is_file() { + if !driver_exists || !self.driver.is_file() { displayer.failure("The driver path does not exist or is not a file path"); return ExitCode::FAILURE; @@ -86,7 +86,7 @@ impl Runnable for Byovd { SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, - &HSTRING::from(self.path.to_str().unwrap()), + &HSTRING::from(self.driver.to_str().unwrap()), PCWSTR::null(), None, PCWSTR::null(), From 096e15611418b410037994027069a1c1d90af5c0 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 28 Jan 2025 22:47:30 +0100 Subject: [PATCH 32/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Change=20an=20error?= =?UTF-8?q?=20message=20to=20be=20more=20accurate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9b6c0b1..b226db4 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -40,7 +40,7 @@ impl Runnable for Byovd { }; if !is_administrator { - displayer.failure("The application needs administrator privileges to run this trace"); + displayer.failure("The application needs administrator privileges to run the driver"); return ExitCode::FAILURE; } From 34ea748f073f537b0e0954aba6e3aa31c53fb2fb Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 28 Jan 2025 22:48:45 +0100 Subject: [PATCH 33/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Put=20more=20i?= =?UTF-8?q?mportant=20informations=20for=20the=20user=20at=20the=20top?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index b226db4..dddfad9 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -22,10 +22,10 @@ use windows::{ pub struct Byovd { #[clap(required = true, help = "Path to the driver")] driver: PathBuf, - #[clap(required = true, help = "Name of the service")] - service_name: String, #[clap(required = true, help = "Displayed name of the service")] displayed_name: String, + #[clap(required = true, help = "Name of the service")] + service_name: String, } impl Runnable for Byovd { From 9a23a9c828c4db2442b8d9c907a53644dda4636a Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 28 Jan 2025 22:54:05 +0100 Subject: [PATCH 34/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Same=20here,?= =?UTF-8?q?=20don't=20put=20type=20information=20in=20the=20variable=20nam?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 8 ++++---- src/commands/traces/processes/spoofing.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 1b914b1..4078905 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -40,7 +40,7 @@ struct Author { #[derive(Parser)] pub struct Generate { #[clap(required = true, help = "Path to the generation file")] - path: PathBuf, + generation: PathBuf, } impl Display for Metadata { @@ -96,15 +96,15 @@ impl Display for Author { impl Runnable for Generate { fn run(&self) -> ExitCode { - let Ok(path_exists) = self.path.try_exists() else { + let Ok(generation_exists) = self.generation.try_exists() else { return ExitCode::FAILURE; }; - if !path_exists || !self.path.is_file() { + if !generation_exists || !self.generation.is_file() { return ExitCode::FAILURE; } - let Ok(file_content) = read_to_string(self.path.clone()) else { + let Ok(file_content) = read_to_string(self.generation.clone()) else { return ExitCode::FAILURE; }; diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index ef4e7b9..8ccd50f 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -35,11 +35,11 @@ pub struct Spoofing { impl Runnable for Spoofing { fn run(&self) -> ExitCode { - let Ok(path_exists) = self.executable.try_exists() else { + let Ok(executable_exists) = self.executable.try_exists() else { return ExitCode::FAILURE; }; - if !path_exists || !self.executable.is_file() { + if !executable_exists || !self.executable.is_file() { return ExitCode::FAILURE; } From 8ddf1329f66fd5579ea2baf4d62869c6a7fbb3e8 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 28 Jan 2025 23:12:26 +0100 Subject: [PATCH 35/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20abbre?= =?UTF-8?q?viation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/windows/users.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/windows/users.rs b/src/windows/users.rs index 36dd513..593d01c 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -12,7 +12,7 @@ use windows::{ }; pub fn is_administrator() -> WindowsResult { - let mut is_admin: BOOL = false.into(); + let mut is_administrator: BOOL = false.into(); unsafe { let mut administrators_group: Owned = Owned::new(PSID::default()); @@ -31,8 +31,8 @@ pub fn is_administrator() -> WindowsResult { &mut *administrators_group, )?; - CheckTokenMembership(None, *administrators_group, &mut is_admin as *mut _)?; + CheckTokenMembership(None, *administrators_group, &mut is_administrator as *mut _)?; } - Ok(is_admin.as_bool()) + Ok(is_administrator.as_bool()) } From bb3a423eb87643775deebf9e2fde680564ab1d05 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Wed, 29 Jan 2025 20:45:33 +0100 Subject: [PATCH 36/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20printing=20to?= =?UTF-8?q?=20spoofing!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 90 +++++++++++++++++------ 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 8ccd50f..02a9a9e 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -4,6 +4,7 @@ use crate::{ commands::{traces::Trace, Runnable}, + displayer::Displayer, windows::processes::get_pid, }; use clap::Parser; @@ -35,23 +36,33 @@ pub struct Spoofing { impl Runnable for Spoofing { fn run(&self) -> ExitCode { + let mut displayer: Displayer = Displayer::default(); + displayer.loading("Checking the executable path validity"); + let Ok(executable_exists) = self.executable.try_exists() else { + displayer.failure("Could not check the existence of the executable path"); + return ExitCode::FAILURE; }; if !executable_exists || !self.executable.is_file() { + displayer.failure("The executable path does not exist or is not a file path"); + return ExitCode::FAILURE; } + displayer.success("The executable path is valid"); + displayer.loading("Initializing the startup information"); + let mut required_size: usize = 0; - unsafe { - let _: WindowsResult<()> = InitializeProcThreadAttributeList( + let _: WindowsResult<()> = unsafe { + InitializeProcThreadAttributeList( LPPROC_THREAD_ATTRIBUTE_LIST::default(), 1, 0, &mut required_size, - ); + ) }; let mut attributes: Box<[u8]> = vec![0; required_size].into_boxed_slice(); @@ -68,27 +79,47 @@ impl Runnable for Spoofing { lpAttributeList: *attributes_list, }; - unsafe { - if let Err(_) = InitializeProcThreadAttributeList( + if let Err(_) = unsafe { + InitializeProcThreadAttributeList( startup_informations.lpAttributeList, 1, 0, &mut required_size, - ) { - return ExitCode::FAILURE; - } + ) + } { + displayer.failure("Could not initialize the startup information"); + + return ExitCode::FAILURE; + } + + displayer.success("The startup information is initialized"); + displayer.loading("Retrieving the parent process identifier"); + + let Ok(parent_process_identifier) = get_pid(self.parent_executable.as_str()) else { + displayer.failure("Could not retrieve the parent process identifier"); + + return ExitCode::FAILURE; + }; + + displayer.success("The parent process identifier is retrieved"); + displayer.loading("Retrieving a handle to the parent process"); + + let mut parent_process: Owned = match unsafe { + OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(_) => { + displayer.failure("Could not retrieve a handle to the parent process"); - let Ok(parent_process_identifier) = get_pid(self.parent_executable.as_str()) else { return ExitCode::FAILURE; - }; + } + }; - let mut parent_process: Owned = - match OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) { - Ok(handle) => Owned::new(handle), - Err(_) => return ExitCode::FAILURE, - }; + displayer.success("A handle to the parent process is retrieved"); + displayer.loading("Setting the parent process in the startup information"); - if let Err(_) = UpdateProcThreadAttribute( + if let Err(_) = unsafe { + UpdateProcThreadAttribute( startup_informations.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS as usize, @@ -96,11 +127,18 @@ impl Runnable for Spoofing { size_of::(), None, None, - ) { - return ExitCode::FAILURE; - } + ) + } { + displayer.failure("Could not set the parent process in the startup information"); + + return ExitCode::FAILURE; + } + + displayer.success("The parent process in the startup information is set"); + displayer.loading("Creating the spoofed process"); - if let Err(_) = CreateProcessW( + if let Err(_) = unsafe { + CreateProcessW( None, PWSTR( OsString::from(self.executable.as_os_str()) @@ -117,10 +155,14 @@ impl Runnable for Spoofing { None, &startup_informations.StartupInfo, &mut PROCESS_INFORMATION::default(), - ) { - return ExitCode::FAILURE; - } - }; + ) + } { + displayer.failure("Could not create the spoofed process"); + + return ExitCode::FAILURE; + } + + displayer.success("The spoofed process is created"); ExitCode::SUCCESS } From 5c74ea05a4aa582ff1956fc6ddce85813783506c Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Wed, 29 Jan 2025 20:47:06 +0100 Subject: [PATCH 37/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Information=20?= =?UTF-8?q?don't=20take=20a=20s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 02a9a9e..6efbb43 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -71,7 +71,7 @@ impl Runnable for Spoofing { attributes.as_mut_ptr() as *mut _ )) }; - let startup_informations: STARTUPINFOEXW = STARTUPINFOEXW { + let startup_information: STARTUPINFOEXW = STARTUPINFOEXW { StartupInfo: STARTUPINFOW { cb: size_of::() as u32, ..Default::default() @@ -81,7 +81,7 @@ impl Runnable for Spoofing { if let Err(_) = unsafe { InitializeProcThreadAttributeList( - startup_informations.lpAttributeList, + startup_information.lpAttributeList, 1, 0, &mut required_size, @@ -120,7 +120,7 @@ impl Runnable for Spoofing { if let Err(_) = unsafe { UpdateProcThreadAttribute( - startup_informations.lpAttributeList, + startup_information.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS as usize, Some(&mut *parent_process as *mut _ as *mut _), @@ -153,7 +153,7 @@ impl Runnable for Spoofing { EXTENDED_STARTUPINFO_PRESENT, None, None, - &startup_informations.StartupInfo, + &startup_information.StartupInfo, &mut PROCESS_INFORMATION::default(), ) } { From adb262d9c2d20a9fc47b4f8597f52eae312bb63d Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Wed, 29 Jan 2025 23:20:14 +0100 Subject: [PATCH 38/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20emojis=20and=20?= =?UTF-8?q?colors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 4078905..035f8d8 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -7,6 +7,7 @@ use crate::commands::{ Runnable, }; use clap::Parser; +use console::{style, Emoji}; use serde::Deserialize; use std::{ fmt::{Display, Formatter, Result as FormatResult}, @@ -51,8 +52,9 @@ impl Display for Metadata { for (index, author) in authors.iter().enumerate() { authors_lines.push_str( format!( - "Author n°{}\n\ + "{}Author n°{}\n\ {}", + Emoji("🧑 ", ""), index + 1, author ) @@ -67,12 +69,17 @@ impl Display for Metadata { write!( formatter, - "Metadata\n\ - Name: {}\n\ - Version: {}\n\ - References: {:#?}\n\n\ + "{}Name: {}\n\ + {}Version: {}\n\ + {}References: {:#?}\n\n\ {}", - self.name, self.version, self.references, authors_lines + Emoji("📝 ", ""), + self.name, + Emoji("🤖 ", ""), + self.version, + Emoji("🔗 ", ""), + self.references, + authors_lines ) } } @@ -82,14 +89,16 @@ impl Display for Author { let mut email_line: String = String::default(); if let Some(email) = &self.email { - email_line = format!("\nEmail: {}", email); + email_line = format!("\n{}Email: {}", Emoji("📧 ", ""), email); } write!( formatter, - "Name: {}\ + "{}Name: {}\ {}", - self.name, email_line + Emoji("💬 ", ""), + self.name, + email_line ) } } @@ -112,15 +121,20 @@ impl Runnable for Generate { return ExitCode::FAILURE; }; - println!("{}", generation.metadata); + println!( + "Generation metadata\n\ + {}", + generation.metadata + ); for (index, command) in generation.commands.iter().enumerate() { let trace: &dyn Trace = command.traverse(); println!( - "\n[{}/{}] Generating {} trace", - index + 1, - generation.commands.len(), + "\n{} Generating {} trace", + style(format!("[{}/{}]", index + 1, generation.commands.len())) + .blue() + .bold(), trace.name(), ); From 590f31c9373ddb41a7904fda1c1253350c46da5b Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Wed, 29 Jan 2025 23:25:09 +0100 Subject: [PATCH 39/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Remove=20bold=20in=20?= =?UTF-8?q?the=20displayer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/displayer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayer.rs b/src/displayer.rs index d0f038a..d6ea822 100644 --- a/src/displayer.rs +++ b/src/displayer.rs @@ -86,8 +86,8 @@ impl Default for Emojis { impl Default for Styles { fn default() -> Self { Self { - success: Style::new().green().bold(), - failure: Style::new().red().bold().for_stderr(), + success: Style::new().green(), + failure: Style::new().red().for_stderr(), } } } From cc96733f83a2f5747cf7fa153efadf4eb9ac2f22 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 31 Jan 2025 22:19:45 +0100 Subject: [PATCH 40/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Simplify=20the?= =?UTF-8?q?=20Displayer=20and=20add=20new=20constructor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As written here https://rust-lang.github.io/api-guidelines/predictability.html#constructors-are-static-inherent-methods-c-ctor. It's a good practice to have new and default. --- src/commands/traces/drivers/byovd.rs | 2 +- src/commands/traces/processes/spoofing.rs | 2 +- src/displayer.rs | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index dddfad9..69f6bf6 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -30,7 +30,7 @@ pub struct Byovd { impl Runnable for Byovd { fn run(&self) -> ExitCode { - let mut displayer: Displayer = Displayer::default(); + let mut displayer: Displayer = Displayer::new(); displayer.loading("Checking administrator privileges"); let Ok(is_administrator) = is_administrator() else { diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 6efbb43..79c97ee 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -36,7 +36,7 @@ pub struct Spoofing { impl Runnable for Spoofing { fn run(&self) -> ExitCode { - let mut displayer: Displayer = Displayer::default(); + let mut displayer: Displayer = Displayer::new(); displayer.loading("Checking the executable path validity"); let Ok(executable_exists) = self.executable.try_exists() else { diff --git a/src/displayer.rs b/src/displayer.rs index d6ea822..1a50097 100644 --- a/src/displayer.rs +++ b/src/displayer.rs @@ -4,7 +4,7 @@ use console::{Emoji, Style}; use indicatif::{ProgressBar, ProgressStyle}; -use std::{borrow::Cow, fmt::Display, time::Duration}; +use std::time::Duration; pub struct Displayer { spinner: ProgressBar, @@ -12,25 +12,29 @@ pub struct Displayer { styles: Styles, } -pub struct Emojis { +struct Emojis { pub success: Emoji<'static, 'static>, pub failure: Emoji<'static, 'static>, } -pub struct Styles { +struct Styles { pub success: Style, pub failure: Style, } impl Displayer { - pub fn loading(&mut self, message: impl Into> + Display) { + pub fn new() -> Self { + Self::default() + } + + pub fn loading(&mut self, message: &'static str) { self.stop(); self.spinner.set_message(message); self.spinner.enable_steady_tick(Duration::from_millis(100)); } - pub fn success(&mut self, message: impl Into> + Display) { + pub fn success(&mut self, message: &str) { self.stop(); println!( @@ -39,7 +43,7 @@ impl Displayer { ); } - pub fn failure(&mut self, message: impl Into> + Display) { + pub fn failure(&mut self, message: &str) { self.stop(); eprintln!( @@ -53,12 +57,7 @@ impl Displayer { self.spinner = ProgressBar::new_spinner().with_style(self.spinner.style()); } - fn format( - &self, - emoji: &Emoji<'_, '_>, - style: &Style, - message: impl Into> + Display, - ) -> String { + fn format(&self, emoji: &Emoji, style: &Style, message: &str) -> String { format!("{}{}", style.apply_to(emoji), message) } } From fafdacb5c2365deabcb93612070d6565f4407d19 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 31 Jan 2025 22:30:57 +0100 Subject: [PATCH 41/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Remplace=20"Could=20n?= =?UTF-8?q?ot"=20by=20"Failed=20to"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 10 +++++----- src/commands/traces/processes/spoofing.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 69f6bf6..56d4d33 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -34,7 +34,7 @@ impl Runnable for Byovd { displayer.loading("Checking administrator privileges"); let Ok(is_administrator) = is_administrator() else { - displayer.failure("Could not check administrator privileges"); + displayer.failure("Failed to check administrator privileges"); return ExitCode::FAILURE; }; @@ -49,7 +49,7 @@ impl Runnable for Byovd { displayer.loading("Checking the driver path validity"); let Ok(driver_exists) = self.driver.try_exists() else { - displayer.failure("Could not check the existence of the driver path"); + displayer.failure("Failed to check the existence of the driver path"); return ExitCode::FAILURE; }; @@ -68,7 +68,7 @@ impl Runnable for Byovd { } { Ok(handle) => unsafe { Owned::new(handle) }, Err(_) => { - displayer.failure("Could not create the service manager"); + displayer.failure("Failed to create the service manager"); return ExitCode::FAILURE; } @@ -96,7 +96,7 @@ impl Runnable for Byovd { } { Ok(handle) => unsafe { Owned::new(handle) }, Err(_) => { - displayer.failure("Could not create the driver service"); + displayer.failure("Failed to create the driver service"); return ExitCode::FAILURE; } @@ -106,7 +106,7 @@ impl Runnable for Byovd { displayer.loading("Starting the driver service"); if let Err(_) = unsafe { StartServiceW(*service, None) } { - displayer.failure("Could not start the driver service"); + displayer.failure("Failed to start the driver service"); return ExitCode::FAILURE; } diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 79c97ee..3ded90d 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -87,7 +87,7 @@ impl Runnable for Spoofing { &mut required_size, ) } { - displayer.failure("Could not initialize the startup information"); + displayer.failure("Failed to initialize the startup information"); return ExitCode::FAILURE; } @@ -96,7 +96,7 @@ impl Runnable for Spoofing { displayer.loading("Retrieving the parent process identifier"); let Ok(parent_process_identifier) = get_pid(self.parent_executable.as_str()) else { - displayer.failure("Could not retrieve the parent process identifier"); + displayer.failure("Failed to retrieve the parent process identifier"); return ExitCode::FAILURE; }; @@ -109,7 +109,7 @@ impl Runnable for Spoofing { } { Ok(handle) => unsafe { Owned::new(handle) }, Err(_) => { - displayer.failure("Could not retrieve a handle to the parent process"); + displayer.failure("Failed to retrieve a handle to the parent process"); return ExitCode::FAILURE; } @@ -129,7 +129,7 @@ impl Runnable for Spoofing { None, ) } { - displayer.failure("Could not set the parent process in the startup information"); + displayer.failure("Failed to set the parent process in the startup information"); return ExitCode::FAILURE; } @@ -157,7 +157,7 @@ impl Runnable for Spoofing { &mut PROCESS_INFORMATION::default(), ) } { - displayer.failure("Could not create the spoofed process"); + displayer.failure("Failed to create the spoofed process"); return ExitCode::FAILURE; } From e868146d0981a95c76b42abbd55a55d0c45e204d Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 31 Jan 2025 22:37:26 +0100 Subject: [PATCH 42/61] =?UTF-8?q?feat:=20=E2=9C=A8=20I=20forgot=20one=20"C?= =?UTF-8?q?ould=20not"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 3ded90d..791f00d 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -40,7 +40,7 @@ impl Runnable for Spoofing { displayer.loading("Checking the executable path validity"); let Ok(executable_exists) = self.executable.try_exists() else { - displayer.failure("Could not check the existence of the executable path"); + displayer.failure("Failed to check the existence of the executable path"); return ExitCode::FAILURE; }; From 34ed2d096c7c2aa3a2485e64fb645b6e736169c1 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Fri, 31 Jan 2025 22:49:02 +0100 Subject: [PATCH 43/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Display=20information?= =?UTF-8?q?=20for=20the=20generate=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 035f8d8..1ba2889 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -2,9 +2,12 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{ - traces::{Trace, Traces, Traversable}, - Runnable, +use crate::{ + commands::{ + traces::{Trace, Traces, Traversable}, + Runnable, + }, + displayer::Displayer, }; use clap::Parser; use console::{style, Emoji}; @@ -105,24 +108,43 @@ impl Display for Author { impl Runnable for Generate { fn run(&self) -> ExitCode { + let mut displayer: Displayer = Displayer::new(); + displayer.loading("Checking the generation path validity"); + let Ok(generation_exists) = self.generation.try_exists() else { + displayer.failure("Failed to check the existence of the generation path"); + return ExitCode::FAILURE; }; if !generation_exists || !self.generation.is_file() { + displayer.failure("The generation path does not exist or is not a file path"); + return ExitCode::FAILURE; } + displayer.success("The generation path is valid"); + displayer.loading("Reading the generation file"); + let Ok(file_content) = read_to_string(self.generation.clone()) else { + displayer.failure("Failed to read the generation file"); + return ExitCode::FAILURE; }; + displayer.success("The generation file is read"); + displayer.loading("Parsing the content"); + let Ok(generation): Result = from_str(file_content.as_str()) else { + displayer.failure("Failed to parse the content"); + return ExitCode::FAILURE; }; + displayer.success("The content is parsed"); + println!( - "Generation metadata\n\ + "\nGeneration metadata\n\ {}", generation.metadata ); From a686a9e91360d3a004b6881d9830e34b675a27d4 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 14:24:39 +0100 Subject: [PATCH 44/61] =?UTF-8?q?ci:=20=F0=9F=A4=96=20Readd=20back=20the?= =?UTF-8?q?=20fsfe=20copyright?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/lint.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 7c3fc8e..c6bd20c 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -1,5 +1,7 @@ --- # SPDX-FileCopyrightText: 2023 The MalwareTracesGenerator development team +# yamllint disable-line +# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. # # SPDX-License-Identifier: CC0-1.0 name: Lint the project From 1830a0b7f6016750985b8ab1cedcf4cd3a5ec22b Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 16:06:32 +0100 Subject: [PATCH 45/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Display=20error=20mes?= =?UTF-8?q?sage=20for=20the=20Windows=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 18 ++++++++---- src/commands/traces/processes/spoofing.rs | 36 ++++++++++++++++++----- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 56d4d33..6a00ca3 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -67,8 +67,10 @@ impl Runnable for Byovd { OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) } { Ok(handle) => unsafe { Owned::new(handle) }, - Err(_) => { - displayer.failure("Failed to create the service manager"); + Err(error) => { + displayer.failure( + format!("Failed to create the service manager: {}", error.message()).as_str(), + ); return ExitCode::FAILURE; } @@ -95,8 +97,10 @@ impl Runnable for Byovd { ) } { Ok(handle) => unsafe { Owned::new(handle) }, - Err(_) => { - displayer.failure("Failed to create the driver service"); + Err(error) => { + displayer.failure( + format!("Failed to create the driver service: {}", error.message()).as_str(), + ); return ExitCode::FAILURE; } @@ -105,8 +109,10 @@ impl Runnable for Byovd { displayer.success("The driver service is created"); displayer.loading("Starting the driver service"); - if let Err(_) = unsafe { StartServiceW(*service, None) } { - displayer.failure("Failed to start the driver service"); + if let Err(error) = unsafe { StartServiceW(*service, None) } { + displayer.failure( + format!("Failed to start the driver service: {}", error.message()).as_str(), + ); return ExitCode::FAILURE; } diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 791f00d..11c2f7f 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -79,7 +79,7 @@ impl Runnable for Spoofing { lpAttributeList: *attributes_list, }; - if let Err(_) = unsafe { + if let Err(error) = unsafe { InitializeProcThreadAttributeList( startup_information.lpAttributeList, 1, @@ -87,7 +87,13 @@ impl Runnable for Spoofing { &mut required_size, ) } { - displayer.failure("Failed to initialize the startup information"); + displayer.failure( + format!( + "Failed to initialize the startup information: {}", + error.message() + ) + .as_str(), + ); return ExitCode::FAILURE; } @@ -108,8 +114,14 @@ impl Runnable for Spoofing { OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) } { Ok(handle) => unsafe { Owned::new(handle) }, - Err(_) => { - displayer.failure("Failed to retrieve a handle to the parent process"); + Err(error) => { + displayer.failure( + format!( + "Failed to retrieve a handle to the parent process: {}", + error.message() + ) + .as_str(), + ); return ExitCode::FAILURE; } @@ -118,7 +130,7 @@ impl Runnable for Spoofing { displayer.success("A handle to the parent process is retrieved"); displayer.loading("Setting the parent process in the startup information"); - if let Err(_) = unsafe { + if let Err(error) = unsafe { UpdateProcThreadAttribute( startup_information.lpAttributeList, 0, @@ -129,7 +141,13 @@ impl Runnable for Spoofing { None, ) } { - displayer.failure("Failed to set the parent process in the startup information"); + displayer.failure( + format!( + "Failed to set the parent process in the startup information: {}", + error.message() + ) + .as_str(), + ); return ExitCode::FAILURE; } @@ -137,7 +155,7 @@ impl Runnable for Spoofing { displayer.success("The parent process in the startup information is set"); displayer.loading("Creating the spoofed process"); - if let Err(_) = unsafe { + if let Err(error) = unsafe { CreateProcessW( None, PWSTR( @@ -157,7 +175,9 @@ impl Runnable for Spoofing { &mut PROCESS_INFORMATION::default(), ) } { - displayer.failure("Failed to create the spoofed process"); + displayer.failure( + format!("Failed to create the spoofed process: {}", error.message()).as_str(), + ); return ExitCode::FAILURE; } From ac376e5e76870c6ccc8d9aaf50b3b8eae41d0830 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 16:13:34 +0100 Subject: [PATCH 46/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Reduce=20unsaf?= =?UTF-8?q?e=20scope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/windows/users.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/windows/users.rs b/src/windows/users.rs index 593d01c..b255c99 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -13,10 +13,9 @@ use windows::{ pub fn is_administrator() -> WindowsResult { let mut is_administrator: BOOL = false.into(); + let mut administrators_group: Owned = unsafe { Owned::new(PSID::default()) }; unsafe { - let mut administrators_group: Owned = Owned::new(PSID::default()); - AllocateAndInitializeSid( &SECURITY_NT_AUTHORITY, 2, From a8944a12eeefc75d1d32e7c7d4d47df7e87928e0 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 16:14:55 +0100 Subject: [PATCH 47/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20alias?= =?UTF-8?q?=20as=20the=20name=20don't=20collide=20with=20others?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/windows/users.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/windows/users.rs b/src/windows/users.rs index b255c99..0042fde 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use windows::{ - core::{Owned, Result as WindowsResult}, + core::{Owned, Result}, Win32::{ Foundation::BOOL, Security::{AllocateAndInitializeSid, CheckTokenMembership, PSID, SECURITY_NT_AUTHORITY}, @@ -11,7 +11,7 @@ use windows::{ }, }; -pub fn is_administrator() -> WindowsResult { +pub fn is_administrator() -> Result { let mut is_administrator: BOOL = false.into(); let mut administrators_group: Owned = unsafe { Owned::new(PSID::default()) }; From 4dc4156cbf861c37c0bbd8c6c49c6bc8ba5ac172 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 16:18:21 +0100 Subject: [PATCH 48/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Display=20the=20windo?= =?UTF-8?q?ws=20error=20message=20if=20we=20failed=20to=20check=20administ?= =?UTF-8?q?rator=20privileges?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 6a00ca3..9ef40fa 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -33,10 +33,19 @@ impl Runnable for Byovd { let mut displayer: Displayer = Displayer::new(); displayer.loading("Checking administrator privileges"); - let Ok(is_administrator) = is_administrator() else { - displayer.failure("Failed to check administrator privileges"); + let is_administrator = match is_administrator() { + Ok(is_administrator) => is_administrator, + Err(error) => { + displayer.failure( + format!( + "Failed to check administrator privileges: {}", + error.message() + ) + .as_str(), + ); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; if !is_administrator { From baf539d9c041b2768d44b401e9ca4b86fae9df20 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 16:47:46 +0100 Subject: [PATCH 49/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Use=20type=20i?= =?UTF-8?q?nference?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eventhough I'm not a big fan of inference, it has a big place in Rust and in new programming languages. We need to evolve too and start using it. --- src/commands/generate.rs | 14 +++++++------- src/commands/traces/processes/spoofing.rs | 12 ++++++------ src/windows/processes.rs | 14 +++++--------- src/windows/users.rs | 2 +- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 1ba2889..f884843 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -4,7 +4,7 @@ use crate::{ commands::{ - traces::{Trace, Traces, Traversable}, + traces::{Traces, Traversable}, Runnable, }, displayer::Displayer, @@ -18,7 +18,7 @@ use std::{ path::PathBuf, process::ExitCode, }; -use toml::{de::Error as TomlError, from_str}; +use toml::from_str; #[derive(Deserialize)] struct Generation { @@ -49,7 +49,7 @@ pub struct Generate { impl Display for Metadata { fn fmt(&self, formatter: &mut Formatter) -> FormatResult { - let mut authors_lines: String = String::default(); + let mut authors_lines = String::new(); if let Some(authors) = &self.authors { for (index, author) in authors.iter().enumerate() { @@ -89,7 +89,7 @@ impl Display for Metadata { impl Display for Author { fn fmt(&self, formatter: &mut Formatter) -> FormatResult { - let mut email_line: String = String::default(); + let mut email_line = String::new(); if let Some(email) = &self.email { email_line = format!("\n{}Email: {}", Emoji("📧 ", ""), email); @@ -108,7 +108,7 @@ impl Display for Author { impl Runnable for Generate { fn run(&self) -> ExitCode { - let mut displayer: Displayer = Displayer::new(); + let mut displayer = Displayer::new(); displayer.loading("Checking the generation path validity"); let Ok(generation_exists) = self.generation.try_exists() else { @@ -135,7 +135,7 @@ impl Runnable for Generate { displayer.success("The generation file is read"); displayer.loading("Parsing the content"); - let Ok(generation): Result = from_str(file_content.as_str()) else { + let Ok(generation) = from_str::(file_content.as_str()) else { displayer.failure("Failed to parse the content"); return ExitCode::FAILURE; @@ -150,7 +150,7 @@ impl Runnable for Generate { ); for (index, command) in generation.commands.iter().enumerate() { - let trace: &dyn Trace = command.traverse(); + let trace = command.traverse(); println!( "\n{} Generating {} trace", diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 11c2f7f..0aea739 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -14,7 +14,7 @@ use std::{ process::ExitCode, }; use windows::{ - core::{Owned, Result as WindowsResult, PWSTR}, + core::{Owned, PWSTR}, Win32::{ Foundation::HANDLE, System::Threading::{ @@ -36,7 +36,7 @@ pub struct Spoofing { impl Runnable for Spoofing { fn run(&self) -> ExitCode { - let mut displayer: Displayer = Displayer::new(); + let mut displayer = Displayer::new(); displayer.loading("Checking the executable path validity"); let Ok(executable_exists) = self.executable.try_exists() else { @@ -56,7 +56,7 @@ impl Runnable for Spoofing { let mut required_size: usize = 0; - let _: WindowsResult<()> = unsafe { + let _ = unsafe { InitializeProcThreadAttributeList( LPPROC_THREAD_ATTRIBUTE_LIST::default(), 1, @@ -66,12 +66,12 @@ impl Runnable for Spoofing { }; let mut attributes: Box<[u8]> = vec![0; required_size].into_boxed_slice(); - let attributes_list: Owned = unsafe { + let attributes_list = unsafe { Owned::new(LPPROC_THREAD_ATTRIBUTE_LIST( attributes.as_mut_ptr() as *mut _ )) }; - let startup_information: STARTUPINFOEXW = STARTUPINFOEXW { + let startup_information = STARTUPINFOEXW { StartupInfo: STARTUPINFOW { cb: size_of::() as u32, ..Default::default() @@ -110,7 +110,7 @@ impl Runnable for Spoofing { displayer.success("The parent process identifier is retrieved"); displayer.loading("Retrieving a handle to the parent process"); - let mut parent_process: Owned = match unsafe { + let mut parent_process = match unsafe { OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) } { Ok(handle) => unsafe { Owned::new(handle) }, diff --git a/src/windows/processes.rs b/src/windows/processes.rs index 8017dd9..8c6d3e7 100644 --- a/src/windows/processes.rs +++ b/src/windows/processes.rs @@ -9,12 +9,9 @@ use std::{ }; use windows::{ core::{Owned, HSTRING}, - Win32::{ - Foundation::HANDLE, - System::Diagnostics::ToolHelp::{ - CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, - TH32CS_SNAPPROCESS, - }, + Win32::System::Diagnostics::ToolHelp::{ + CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, + TH32CS_SNAPPROCESS, }, }; @@ -30,9 +27,8 @@ impl Display for ProcessNotFound { } pub fn get_pid(name: &str) -> Result> { - let snapshot: Owned = - unsafe { Owned::new(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?) }; - let mut process_entry: PROCESSENTRY32W = PROCESSENTRY32W { + let snapshot = unsafe { Owned::new(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?) }; + let mut process_entry = PROCESSENTRY32W { dwSize: size_of::() as u32, ..Default::default() }; diff --git a/src/windows/users.rs b/src/windows/users.rs index 0042fde..ece136b 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -13,7 +13,7 @@ use windows::{ pub fn is_administrator() -> Result { let mut is_administrator: BOOL = false.into(); - let mut administrators_group: Owned = unsafe { Owned::new(PSID::default()) }; + let mut administrators_group = unsafe { Owned::new(PSID::default()) }; unsafe { AllocateAndInitializeSid( From 6d0f399ab5d20a83213d13440f8bb9b32d4e8fa8 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 17:04:17 +0100 Subject: [PATCH 50/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Simplify=20get?= =?UTF-8?q?=5Fpid=20return=20value=20by=20using=20Windows=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 15 ++++++++--- src/windows/processes.rs | 32 +++++++---------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 0aea739..014bc6b 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -101,10 +101,19 @@ impl Runnable for Spoofing { displayer.success("The startup information is initialized"); displayer.loading("Retrieving the parent process identifier"); - let Ok(parent_process_identifier) = get_pid(self.parent_executable.as_str()) else { - displayer.failure("Failed to retrieve the parent process identifier"); + let parent_process_identifier = match get_pid(self.parent_executable.as_str()) { + Ok(parent_process_identifier) => parent_process_identifier, + Err(error) => { + displayer.failure( + format!( + "Failed to retrieve the parent process identifier: {}", + error.message() + ) + .as_str(), + ); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; displayer.success("The parent process identifier is retrieved"); diff --git a/src/windows/processes.rs b/src/windows/processes.rs index 8c6d3e7..5438c92 100644 --- a/src/windows/processes.rs +++ b/src/windows/processes.rs @@ -2,31 +2,19 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use std::{ - error::Error, - fmt::{Display, Formatter, Result as FormatterResult}, - mem::size_of, -}; +use std::mem::size_of; use windows::{ - core::{Owned, HSTRING}, - Win32::System::Diagnostics::ToolHelp::{ - CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, - TH32CS_SNAPPROCESS, + core::{Error, Owned, Result, HSTRING}, + Win32::{ + Foundation::E_INVALIDARG, + System::Diagnostics::ToolHelp::{ + CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, + TH32CS_SNAPPROCESS, + }, }, }; -#[derive(Debug)] -pub struct ProcessNotFound; - -impl Error for ProcessNotFound {} - -impl Display for ProcessNotFound { - fn fmt(&self, formatter: &mut Formatter) -> FormatterResult { - write!(formatter, "Process not found") - } -} - -pub fn get_pid(name: &str) -> Result> { +pub fn get_pid(name: &str) -> Result { let snapshot = unsafe { Owned::new(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?) }; let mut process_entry = PROCESSENTRY32W { dwSize: size_of::() as u32, @@ -55,5 +43,5 @@ pub fn get_pid(name: &str) -> Result> { } } - Err(Box::new(ProcessNotFound)) + Err(Error::new(E_INVALIDARG, "Process not found")) } From 5f0fbbe43bd4decbec2f115ad21084306bb67a54 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 17:12:53 +0100 Subject: [PATCH 51/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20abbre?= =?UTF-8?q?viation=20for=20the=20function=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/processes/spoofing.rs | 31 ++++++++++++----------- src/windows/processes.rs | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 014bc6b..f13bab0 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -5,7 +5,7 @@ use crate::{ commands::{traces::Trace, Runnable}, displayer::Displayer, - windows::processes::get_pid, + windows::processes::get_process_identifier, }; use clap::Parser; use serde::Deserialize; @@ -101,20 +101,21 @@ impl Runnable for Spoofing { displayer.success("The startup information is initialized"); displayer.loading("Retrieving the parent process identifier"); - let parent_process_identifier = match get_pid(self.parent_executable.as_str()) { - Ok(parent_process_identifier) => parent_process_identifier, - Err(error) => { - displayer.failure( - format!( - "Failed to retrieve the parent process identifier: {}", - error.message() - ) - .as_str(), - ); - - return ExitCode::FAILURE; - } - }; + let parent_process_identifier = + match get_process_identifier(self.parent_executable.as_str()) { + Ok(parent_process_identifier) => parent_process_identifier, + Err(error) => { + displayer.failure( + format!( + "Failed to retrieve the parent process identifier: {}", + error.message() + ) + .as_str(), + ); + + return ExitCode::FAILURE; + } + }; displayer.success("The parent process identifier is retrieved"); displayer.loading("Retrieving a handle to the parent process"); diff --git a/src/windows/processes.rs b/src/windows/processes.rs index 5438c92..aa750de 100644 --- a/src/windows/processes.rs +++ b/src/windows/processes.rs @@ -14,7 +14,7 @@ use windows::{ }, }; -pub fn get_pid(name: &str) -> Result { +pub fn get_process_identifier(name: &str) -> Result { let snapshot = unsafe { Owned::new(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?) }; let mut process_entry = PROCESSENTRY32W { dwSize: size_of::() as u32, From 33211fb55c30d17ebc7bb8e3c3196bb8f29f1abd Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 1 Feb 2025 17:26:09 +0100 Subject: [PATCH 52/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Use=20f-string?= =?UTF-8?q?=20like=20formating=20as=20much=20as=20we=20can?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maybe we will need some refactoring later and not use a mix of these two types of formatting --- src/commands/generate.rs | 11 ++++------- src/displayer.rs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index f884843..e1165a5 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -56,10 +56,9 @@ impl Display for Metadata { authors_lines.push_str( format!( "{}Author n°{}\n\ - {}", + {author}", Emoji("🧑 ", ""), index + 1, - author ) .as_str(), ); @@ -75,14 +74,13 @@ impl Display for Metadata { "{}Name: {}\n\ {}Version: {}\n\ {}References: {:#?}\n\n\ - {}", + {authors_lines}", Emoji("📝 ", ""), self.name, Emoji("🤖 ", ""), self.version, Emoji("🔗 ", ""), self.references, - authors_lines ) } } @@ -92,16 +90,15 @@ impl Display for Author { let mut email_line = String::new(); if let Some(email) = &self.email { - email_line = format!("\n{}Email: {}", Emoji("📧 ", ""), email); + email_line = format!("\n{}Email: {email}", Emoji("📧 ", "")); } write!( formatter, "{}Name: {}\ - {}", + {email_line}", Emoji("💬 ", ""), self.name, - email_line ) } } diff --git a/src/displayer.rs b/src/displayer.rs index 1a50097..5b1d315 100644 --- a/src/displayer.rs +++ b/src/displayer.rs @@ -58,7 +58,7 @@ impl Displayer { } fn format(&self, emoji: &Emoji, style: &Style, message: &str) -> String { - format!("{}{}", style.apply_to(emoji), message) + format!("{}{message}", style.apply_to(emoji)) } } From 54328120b53fdcb15d31bcbbba22477f94e6af1a Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 00:35:37 +0100 Subject: [PATCH 53/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Also=20print=20errors?= =?UTF-8?q?=20from=20the=20std=20lib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 11 ++++++++--- src/commands/traces/processes/spoofing.rs | 12 +++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9ef40fa..9a11184 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -57,10 +57,15 @@ impl Runnable for Byovd { displayer.success("The application has administrator privileges"); displayer.loading("Checking the driver path validity"); - let Ok(driver_exists) = self.driver.try_exists() else { - displayer.failure("Failed to check the existence of the driver path"); + let driver_exists = match self.driver.try_exists() { + Ok(driver_exists) => driver_exists, + Err(error) => { + displayer.failure( + format!("Failed to check the existence of the driver path: {error}").as_str(), + ); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; if !driver_exists || !self.driver.is_file() { diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index f13bab0..7ac0fc4 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -39,10 +39,16 @@ impl Runnable for Spoofing { let mut displayer = Displayer::new(); displayer.loading("Checking the executable path validity"); - let Ok(executable_exists) = self.executable.try_exists() else { - displayer.failure("Failed to check the existence of the executable path"); + let executable_exists = match self.executable.try_exists() { + Ok(executable_exists) => executable_exists, + Err(error) => { + displayer.failure( + format!("Failed to check the existence of the executable path: {error}") + .as_str(), + ); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; if !executable_exists || !self.executable.is_file() { From bcec314289db6c015f93382e62c0384a4fe017f9 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 01:00:39 +0100 Subject: [PATCH 54/61] =?UTF-8?q?ci:=20=F0=9F=A4=96=20Update=20the=20licen?= =?UTF-8?q?se=20spdx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 2fba265..0bf507b 100644 --- a/deny.toml +++ b/deny.toml @@ -8,7 +8,7 @@ all-features = true [licenses] confidence-threshold = 1.0 -allow = ["Apache-2.0", "MIT", "Unicode-DFS-2016"] +allow = ["Apache-2.0", "MIT", "Unicode-3.0"] [bans] multiple-versions = "deny" From f9c7e428299f5de5616b407fdcd33003c1c45783 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 01:12:58 +0100 Subject: [PATCH 55/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Display=20errors=20fo?= =?UTF-8?q?r=20the=20std=20calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/generate.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/commands/generate.rs b/src/commands/generate.rs index e1165a5..2b541cf 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -108,10 +108,16 @@ impl Runnable for Generate { let mut displayer = Displayer::new(); displayer.loading("Checking the generation path validity"); - let Ok(generation_exists) = self.generation.try_exists() else { - displayer.failure("Failed to check the existence of the generation path"); + let generation_exists = match self.generation.try_exists() { + Ok(exists) => exists, + Err(error) => { + displayer.failure( + format!("Failed to check the existence of the generation path: {error}") + .as_str(), + ); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; if !generation_exists || !self.generation.is_file() { @@ -123,19 +129,25 @@ impl Runnable for Generate { displayer.success("The generation path is valid"); displayer.loading("Reading the generation file"); - let Ok(file_content) = read_to_string(self.generation.clone()) else { - displayer.failure("Failed to read the generation file"); + let file_content = match read_to_string(self.generation.clone()) { + Ok(content) => content, + Err(error) => { + displayer.failure(format!("Failed to read the generation file: {error}").as_str()); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; displayer.success("The generation file is read"); displayer.loading("Parsing the content"); - let Ok(generation) = from_str::(file_content.as_str()) else { - displayer.failure("Failed to parse the content"); + let generation = match from_str::(file_content.as_str()) { + Ok(generation) => generation, + Err(error) => { + displayer.failure(format!("Failed to parse the content: {error}").as_str()); - return ExitCode::FAILURE; + return ExitCode::FAILURE; + } }; displayer.success("The content is parsed"); From 2fda7f41bc137ca6c6304e04c1bca1df82a5053c Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 01:16:40 +0100 Subject: [PATCH 56/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Rename=20varia?= =?UTF-8?q?bles=20in=20some=20Ok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the match we don't care about the context. We should name our variable by what the valid result is. Like for OpenProcess we return an handle so we call it handle and the variable that takes the result from the match have the context, not inside. --- src/commands/traces/drivers/byovd.rs | 2 +- src/commands/traces/processes/spoofing.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9a11184..5676f6f 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -58,7 +58,7 @@ impl Runnable for Byovd { displayer.loading("Checking the driver path validity"); let driver_exists = match self.driver.try_exists() { - Ok(driver_exists) => driver_exists, + Ok(exists) => exists, Err(error) => { displayer.failure( format!("Failed to check the existence of the driver path: {error}").as_str(), diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 7ac0fc4..9933eee 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -40,7 +40,7 @@ impl Runnable for Spoofing { displayer.loading("Checking the executable path validity"); let executable_exists = match self.executable.try_exists() { - Ok(executable_exists) => executable_exists, + Ok(exists) => exists, Err(error) => { displayer.failure( format!("Failed to check the existence of the executable path: {error}") @@ -109,7 +109,7 @@ impl Runnable for Spoofing { let parent_process_identifier = match get_process_identifier(self.parent_executable.as_str()) { - Ok(parent_process_identifier) => parent_process_identifier, + Ok(process_identifier) => process_identifier, Err(error) => { displayer.failure( format!( From 252b6f1079bc433c3b59fa7a8bc27ed712cb79f9 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 14:11:23 +0100 Subject: [PATCH 57/61] =?UTF-8?q?build:=20=F0=9F=93=A6=20Update=20indicati?= =?UTF-8?q?f=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4a78813..b808b78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ rand = "0.8.5" regex_generate = "0.2.3" toml = "0.8.19" serde = { version = "1.0.214", features = ["derive"] } -indicatif = { version = "0.17.9" } +indicatif = { version = "0.17.11" } console = { version = "0.15.10" } [build-dependencies] From 635f5a3b135d5afa1829f762463a6b69e3a5af79 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 14:14:45 +0100 Subject: [PATCH 58/61] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Use=20type=20i?= =?UTF-8?q?nference?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 6 +++--- src/commands/traces/processes/spoofing.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 5676f6f..239713b 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -13,7 +13,7 @@ use std::{path::PathBuf, process::ExitCode}; use windows::{ core::{Owned, HSTRING, PCWSTR}, Win32::System::Services::{ - CreateServiceW, OpenSCManagerW, StartServiceW, SC_HANDLE, SC_MANAGER_ALL_ACCESS, + CreateServiceW, OpenSCManagerW, StartServiceW, SC_MANAGER_ALL_ACCESS, SC_MANAGER_CREATE_SERVICE, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, SERVICE_KERNEL_DRIVER, }, }; @@ -77,7 +77,7 @@ impl Runnable for Byovd { displayer.success("The driver path is valid"); displayer.loading("Creating the service manager"); - let service_manager: Owned = match unsafe { + let service_manager = match unsafe { OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) } { Ok(handle) => unsafe { Owned::new(handle) }, @@ -93,7 +93,7 @@ impl Runnable for Byovd { displayer.success("The service manager is created"); displayer.loading("Creating the driver service"); - let service: Owned = match unsafe { + let service = match unsafe { CreateServiceW( *service_manager, &HSTRING::from(self.service_name.as_str()), diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 9933eee..5736632 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -60,7 +60,7 @@ impl Runnable for Spoofing { displayer.success("The executable path is valid"); displayer.loading("Initializing the startup information"); - let mut required_size: usize = 0; + let mut required_size = 0; let _ = unsafe { InitializeProcThreadAttributeList( From b2654d1007973dc0f10f0775b27d3650cc4fe603 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 14:43:17 +0100 Subject: [PATCH 59/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Rename=20fields=20wit?= =?UTF-8?q?h=20better=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/traces/drivers/byovd.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 239713b..17fde7f 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -22,10 +22,10 @@ use windows::{ pub struct Byovd { #[clap(required = true, help = "Path to the driver")] driver: PathBuf, - #[clap(required = true, help = "Displayed name of the service")] - displayed_name: String, - #[clap(required = true, help = "Name of the service")] - service_name: String, + #[clap(required = true, help = "Name of the driver")] + name: String, + #[clap(required = true, help = "Description of the driver")] + description: String, } impl Runnable for Byovd { @@ -96,8 +96,8 @@ impl Runnable for Byovd { let service = match unsafe { CreateServiceW( *service_manager, - &HSTRING::from(self.service_name.as_str()), - &HSTRING::from(self.displayed_name.as_str()), + &HSTRING::from(self.name.as_str()), + &HSTRING::from(self.description.as_str()), SC_MANAGER_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START, From 2b4554b5c918c9510c989c9591450eaee370c34d Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 15:05:15 +0100 Subject: [PATCH 60/61] =?UTF-8?q?feat:=20=E2=9C=A8=20Heavily=20simplify=20?= =?UTF-8?q?functions=20by=20not=20checking=20parameter=20validity=20as=20f?= =?UTF-8?q?unctions=20already=20check=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moreover, even if we check beforehand we can't be sure that the next call will work. "Do and ask for redemption" --- src/commands/generate.rs | 21 ----------- src/commands/traces/drivers/byovd.rs | 45 ----------------------- src/commands/traces/processes/spoofing.rs | 21 ----------- src/windows.rs | 1 - src/windows/users.rs | 37 ------------------- 5 files changed, 125 deletions(-) delete mode 100644 src/windows/users.rs diff --git a/src/commands/generate.rs b/src/commands/generate.rs index 2b541cf..e295d70 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -106,27 +106,6 @@ impl Display for Author { impl Runnable for Generate { fn run(&self) -> ExitCode { let mut displayer = Displayer::new(); - displayer.loading("Checking the generation path validity"); - - let generation_exists = match self.generation.try_exists() { - Ok(exists) => exists, - Err(error) => { - displayer.failure( - format!("Failed to check the existence of the generation path: {error}") - .as_str(), - ); - - return ExitCode::FAILURE; - } - }; - - if !generation_exists || !self.generation.is_file() { - displayer.failure("The generation path does not exist or is not a file path"); - - return ExitCode::FAILURE; - } - - displayer.success("The generation path is valid"); displayer.loading("Reading the generation file"); let file_content = match read_to_string(self.generation.clone()) { diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 17fde7f..5c1f3e7 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -5,7 +5,6 @@ use crate::{ commands::{traces::Trace, Runnable}, displayer::Displayer, - windows::users::is_administrator, }; use clap::Parser; use serde::Deserialize; @@ -31,50 +30,6 @@ pub struct Byovd { impl Runnable for Byovd { fn run(&self) -> ExitCode { let mut displayer: Displayer = Displayer::new(); - displayer.loading("Checking administrator privileges"); - - let is_administrator = match is_administrator() { - Ok(is_administrator) => is_administrator, - Err(error) => { - displayer.failure( - format!( - "Failed to check administrator privileges: {}", - error.message() - ) - .as_str(), - ); - - return ExitCode::FAILURE; - } - }; - - if !is_administrator { - displayer.failure("The application needs administrator privileges to run the driver"); - - return ExitCode::FAILURE; - } - - displayer.success("The application has administrator privileges"); - displayer.loading("Checking the driver path validity"); - - let driver_exists = match self.driver.try_exists() { - Ok(exists) => exists, - Err(error) => { - displayer.failure( - format!("Failed to check the existence of the driver path: {error}").as_str(), - ); - - return ExitCode::FAILURE; - } - }; - - if !driver_exists || !self.driver.is_file() { - displayer.failure("The driver path does not exist or is not a file path"); - - return ExitCode::FAILURE; - } - - displayer.success("The driver path is valid"); displayer.loading("Creating the service manager"); let service_manager = match unsafe { diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 5736632..53fff6c 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -37,27 +37,6 @@ pub struct Spoofing { impl Runnable for Spoofing { fn run(&self) -> ExitCode { let mut displayer = Displayer::new(); - displayer.loading("Checking the executable path validity"); - - let executable_exists = match self.executable.try_exists() { - Ok(exists) => exists, - Err(error) => { - displayer.failure( - format!("Failed to check the existence of the executable path: {error}") - .as_str(), - ); - - return ExitCode::FAILURE; - } - }; - - if !executable_exists || !self.executable.is_file() { - displayer.failure("The executable path does not exist or is not a file path"); - - return ExitCode::FAILURE; - } - - displayer.success("The executable path is valid"); displayer.loading("Initializing the startup information"); let mut required_size = 0; diff --git a/src/windows.rs b/src/windows.rs index 36568b5..47df618 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -3,4 +3,3 @@ // SPDX-License-Identifier: GPL-3.0-or-later pub mod processes; -pub mod users; diff --git a/src/windows/users.rs b/src/windows/users.rs deleted file mode 100644 index ece136b..0000000 --- a/src/windows/users.rs +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The MalwareTracesGenerator development team -// -// SPDX-License-Identifier: GPL-3.0-or-later - -use windows::{ - core::{Owned, Result}, - Win32::{ - Foundation::BOOL, - Security::{AllocateAndInitializeSid, CheckTokenMembership, PSID, SECURITY_NT_AUTHORITY}, - System::SystemServices::{DOMAIN_ALIAS_RID_ADMINS, SECURITY_BUILTIN_DOMAIN_RID}, - }, -}; - -pub fn is_administrator() -> Result { - let mut is_administrator: BOOL = false.into(); - let mut administrators_group = unsafe { Owned::new(PSID::default()) }; - - unsafe { - AllocateAndInitializeSid( - &SECURITY_NT_AUTHORITY, - 2, - SECURITY_BUILTIN_DOMAIN_RID as u32, - DOMAIN_ALIAS_RID_ADMINS as u32, - 0, - 0, - 0, - 0, - 0, - 0, - &mut *administrators_group, - )?; - - CheckTokenMembership(None, *administrators_group, &mut is_administrator as *mut _)?; - } - - Ok(is_administrator.as_bool()) -} From fd0af1bd606bdaafa49f1c20d42de549c1c2cf9a Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 2 Feb 2025 20:01:00 +0100 Subject: [PATCH 61/61] =?UTF-8?q?build:=20=F0=9F=93=A6=20Bump=20MSRV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b808b78..f7cf999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "malware-traces-generator" version = "1.0.0" edition = "2021" -rust-version = "1.74.1" +rust-version = "1.83.0" description = "Generate malware traces for detection tests" documentation = "https://frack113.github.io/MalwareTracesGenerator/" repository = "https://github.com/frack113/MalwareTracesGenerator/"