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 diff --git a/Cargo.toml b/Cargo.toml index bd36025..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/" @@ -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.11" } +console = { version = "0.15.10" } [build-dependencies] embed-resource = "3.0.1" 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" diff --git a/src/commands.rs b/src/commands.rs index 8835879..f4d8262 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -2,37 +2,43 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -pub mod generate; -pub mod traces; - -use crate::commands::{generate::Generate, traces::Traces}; +use crate::commands::{ + generate::Generate, + traces::{Traces, Traversable as TracesTraversable}, +}; use clap::{Parser, Subcommand}; -use std::error::Error; +use std::process::ExitCode; + +mod generate; +mod traces; #[derive(Parser)] #[clap(author, version)] #[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), } +pub trait Traversable { + fn traverse(&self) -> &dyn Runnable; +} + pub trait Runnable { - fn run(&self) -> Result<(), Box>; + fn run(&self) -> ExitCode; } -impl Runnable for Arguments { - fn run(&self) -> Result<(), Box> { +impl Traversable for Arguments { + fn traverse(&self) -> &dyn Runnable { match &self.command { - Command::Traces(traces) => traces as &dyn Runnable, - Command::Generate(generate) => generate, + Commands::Traces(traces) => traces.traverse().as_runnable(), + Commands::Generate(generate) => generate, } - .run() } } diff --git a/src/commands/generate.rs b/src/commands/generate.rs index d70130c..e295d70 100644 --- a/src/commands/generate.rs +++ b/src/commands/generate.rs @@ -2,16 +2,29 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::commands::{traces::Traces, Runnable}; +use crate::{ + commands::{ + traces::{Traces, Traversable}, + Runnable, + }, + displayer::Displayer, +}; use clap::Parser; +use console::{style, Emoji}; use serde::Deserialize; -use std::{error::Error, fs::read_to_string, path::PathBuf}; +use std::{ + fmt::{Display, Formatter, Result as FormatResult}, + fs::read_to_string, + path::PathBuf, + process::ExitCode, +}; use toml::from_str; #[derive(Deserialize)] -struct Configuration { +struct Generation { metadata: Metadata, - traces: Vec, + #[serde(rename(deserialize = "traces"))] + commands: Vec, } #[derive(Deserialize)] @@ -30,22 +43,116 @@ struct Author { #[derive(Parser)] pub struct Generate { - #[clap(required = true, help = "Path to the configuration file")] - path: PathBuf, + #[clap(required = true, help = "Path to the generation file")] + generation: PathBuf, } -impl Runnable for Generate { - fn run(&self) -> Result<(), Box> { - if !self.path.try_exists()? || !self.path.is_file() { - return Ok(()); +impl Display for Metadata { + fn fmt(&self, formatter: &mut Formatter) -> FormatResult { + let mut authors_lines = String::new(); + + if let Some(authors) = &self.authors { + for (index, author) in authors.iter().enumerate() { + authors_lines.push_str( + format!( + "{}Author nĀ°{}\n\ + {author}", + Emoji("šŸ§‘ ", ""), + index + 1, + ) + .as_str(), + ); + + if index != authors.len() - 1 { + authors_lines.push_str("\n\n"); + } + } } - let configuration: Configuration = from_str(read_to_string(self.path.clone())?.as_str())?; + write!( + formatter, + "{}Name: {}\n\ + {}Version: {}\n\ + {}References: {:#?}\n\n\ + {authors_lines}", + Emoji("šŸ“ ", ""), + self.name, + Emoji("šŸ¤– ", ""), + self.version, + Emoji("šŸ”— ", ""), + self.references, + ) + } +} + +impl Display for Author { + fn fmt(&self, formatter: &mut Formatter) -> FormatResult { + let mut email_line = String::new(); + + if let Some(email) = &self.email { + email_line = format!("\n{}Email: {email}", Emoji("šŸ“§ ", "")); + } + + write!( + formatter, + "{}Name: {}\ + {email_line}", + Emoji("šŸ’¬ ", ""), + self.name, + ) + } +} + +impl Runnable for Generate { + fn run(&self) -> ExitCode { + let mut displayer = Displayer::new(); + displayer.loading("Reading 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; + } + }; + + displayer.success("The generation file is read"); + displayer.loading("Parsing 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; + } + }; + + displayer.success("The content is parsed"); + + println!( + "\nGeneration metadata\n\ + {}", + generation.metadata + ); + + for (index, command) in generation.commands.iter().enumerate() { + let trace = command.traverse(); + + println!( + "\n{} Generating {} trace", + style(format!("[{}/{}]", index + 1, generation.commands.len())) + .blue() + .bold(), + trace.name(), + ); - for trace in configuration.traces { - trace.run()?; + if trace.run() == ExitCode::FAILURE { + return ExitCode::FAILURE; + } } - Ok(()) + ExitCode::SUCCESS } } diff --git a/src/commands/traces.rs b/src/commands/traces.rs index 00450e7..1483cc2 100644 --- a/src/commands/traces.rs +++ b/src/commands/traces.rs @@ -8,31 +8,39 @@ use crate::commands::{ }; use clap::{Args, Subcommand}; use serde::Deserialize; -use std::error::Error; -pub mod drivers; -pub mod processes; +mod drivers; +mod processes; #[derive(Args, Deserialize)] pub struct Traces { #[clap(subcommand)] #[serde(flatten)] - pub command: Command, + pub command: Commands, } #[derive(Subcommand, Deserialize)] #[serde(rename_all = "snake_case", untagged)] -pub enum Command { +pub enum Commands { Drivers(Drivers), Processes(Processes), } -impl Runnable for Traces { - fn run(&self) -> Result<(), Box> { +pub trait Trace: Runnable { + fn name(&self) -> &str; + fn as_runnable(&self) -> &dyn Runnable; +} + +pub trait Traversable { + fn traverse(&self) -> &dyn Trace; +} + +impl Traversable for Traces { + fn traverse(&self) -> &dyn Trace { match &self.command { - Command::Drivers(drivers) => drivers as &dyn Runnable, - Command::Processes(processes) => processes, + 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 b0b3582..36e1fdf 100644 --- a/src/commands/traces/drivers.rs +++ b/src/commands/traces/drivers.rs @@ -2,31 +2,29 @@ // // 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::error::Error; -pub mod byovd; +mod byovd; #[derive(Args, Deserialize)] 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) -> Result<(), Box> { +impl Traversable for Drivers { + fn traverse(&self) -> &dyn Trace { match &self.command { - Command::Byovd(byovd) => byovd as &dyn Runnable, + Commands::Byovd(byovd) => byovd, } - .run() } } diff --git a/src/commands/traces/drivers/byovd.rs b/src/commands/traces/drivers/byovd.rs index 9c8552e..5c1f3e7 100644 --- a/src/commands/traces/drivers/byovd.rs +++ b/src/commands/traces/drivers/byovd.rs @@ -2,76 +2,102 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::{commands::Runnable, windows::users::is_administrator}; +use crate::{ + commands::{traces::Trace, Runnable}, + displayer::Displayer, +}; use clap::Parser; use serde::Deserialize; -use std::{error::Error, path::PathBuf}; +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_MANAGER_ALL_ACCESS, + SC_MANAGER_CREATE_SERVICE, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, SERVICE_KERNEL_DRIVER, }, }; #[derive(Parser, Deserialize)] pub struct Byovd { - #[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, + driver: PathBuf, + #[clap(required = true, help = "Name of the driver")] + name: String, + #[clap(required = true, help = "Description of the driver")] + description: String, } impl Runnable for Byovd { - fn run(&self) -> Result<(), Box> { - if !is_administrator()? { - return Ok(()); - } - - if !self.path.try_exists()? || !self.path.is_file() { - return Ok(()); - } + fn run(&self) -> ExitCode { + let mut displayer: Displayer = Displayer::new(); + displayer.loading("Creating the service manager"); - unsafe { - let service_manager: Owned = Owned::new(OpenSCManagerW( - PCWSTR::null(), - PCWSTR::null(), - SC_MANAGER_CREATE_SERVICE, - )?); + let service_manager = match unsafe { + OpenSCManagerW(PCWSTR::null(), PCWSTR::null(), SC_MANAGER_CREATE_SERVICE) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(error) => { + displayer.failure( + format!("Failed to create the service manager: {}", error.message()).as_str(), + ); - if OpenServiceW( - *service_manager, - &HSTRING::from(self.service_name.as_str()), - GENERIC_READ.0, - ) - .is_ok() - { - return Ok(()); + return ExitCode::FAILURE; } + }; + + displayer.success("The service manager is created"); + displayer.loading("Creating the driver service"); - let service: Owned = Owned::new(CreateServiceW( + 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, SERVICE_ERROR_IGNORE, - &HSTRING::from(self.path.to_str().unwrap()), + &HSTRING::from(self.driver.to_str().unwrap()), PCWSTR::null(), None, PCWSTR::null(), PCWSTR::null(), PCWSTR::null(), - )?); + ) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(error) => { + displayer.failure( + format!("Failed to create the driver service: {}", error.message()).as_str(), + ); - Ok(StartServiceW(*service, None)?) + return ExitCode::FAILURE; + } + }; + + displayer.success("The driver service is created"); + displayer.loading("Starting 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; } + + displayer.success("The driver service is started"); + + 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.rs b/src/commands/traces/processes.rs index 2238f5f..2dd8b6d 100644 --- a/src/commands/traces/processes.rs +++ b/src/commands/traces/processes.rs @@ -2,31 +2,29 @@ // // 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::error::Error; -pub mod spoofing; +mod spoofing; #[derive(Args, Deserialize)] 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) -> Result<(), Box> { +impl Traversable for Processes { + fn traverse(&self) -> &dyn Trace { match &self.command { - Command::Spoofing(spoofing) => spoofing as &dyn Runnable, + Commands::Spoofing(spoofing) => spoofing, } - .run() } } diff --git a/src/commands/traces/processes/spoofing.rs b/src/commands/traces/processes/spoofing.rs index 5ce0a1f..53fff6c 100644 --- a/src/commands/traces/processes/spoofing.rs +++ b/src/commands/traces/processes/spoofing.rs @@ -2,12 +2,16 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use crate::{commands::Runnable, windows::processes::get_pid}; +use crate::{ + commands::{traces::Trace, Runnable}, + displayer::Displayer, + windows::processes::get_process_identifier, +}; use clap::Parser; use serde::Deserialize; use std::{ - error::Error, ffi::OsString, iter::once, mem::size_of, os::windows::ffi::OsStrExt, - path::PathBuf, + ffi::OsString, iter::once, mem::size_of, os::windows::ffi::OsStrExt, path::PathBuf, + process::ExitCode, }; use windows::{ core::{Owned, PWSTR}, @@ -31,29 +35,28 @@ 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 mut displayer = Displayer::new(); + displayer.loading("Initializing the startup information"); - let mut required_size: usize = 0; + let mut required_size = 0; - unsafe { - let _ = InitializeProcThreadAttributeList( + let _ = unsafe { + InitializeProcThreadAttributeList( LPPROC_THREAD_ATTRIBUTE_LIST::default(), 1, 0, &mut required_size, - ); + ) }; 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_informations: STARTUPINFOEXW = STARTUPINFOEXW { + let startup_information = STARTUPINFOEXW { StartupInfo: STARTUPINFOW { cb: size_of::() as u32, ..Default::default() @@ -61,29 +64,93 @@ impl Runnable for Spoofing { lpAttributeList: *attributes_list, }; - unsafe { + if let Err(error) = unsafe { InitializeProcThreadAttributeList( - startup_informations.lpAttributeList, + startup_information.lpAttributeList, 1, 0, &mut required_size, - )?; + ) + } { + displayer.failure( + format!( + "Failed to initialize the startup information: {}", + error.message() + ) + .as_str(), + ); - let mut parent_process: Owned = Owned::new(OpenProcess( - PROCESS_CREATE_PROCESS, - false, - get_pid(self.parent_executable.as_str())?, - )?); + return ExitCode::FAILURE; + } + + displayer.success("The startup information is initialized"); + displayer.loading("Retrieving the parent process identifier"); + + let parent_process_identifier = + match get_process_identifier(self.parent_executable.as_str()) { + Ok(process_identifier) => 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"); + + let mut parent_process = match unsafe { + OpenProcess(PROCESS_CREATE_PROCESS, false, parent_process_identifier) + } { + Ok(handle) => unsafe { Owned::new(handle) }, + Err(error) => { + displayer.failure( + format!( + "Failed to retrieve a handle to the parent process: {}", + error.message() + ) + .as_str(), + ); + + 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(error) = unsafe { UpdateProcThreadAttribute( - startup_informations.lpAttributeList, + startup_information.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS as usize, Some(&mut *parent_process as *mut _ as *mut _), size_of::(), None, None, - )?; + ) + } { + displayer.failure( + format!( + "Failed to set the parent process in the startup information: {}", + error.message() + ) + .as_str(), + ); + + return ExitCode::FAILURE; + } + displayer.success("The parent process in the startup information is set"); + displayer.loading("Creating the spoofed process"); + + if let Err(error) = unsafe { CreateProcessW( None, PWSTR( @@ -99,11 +166,29 @@ impl Runnable for Spoofing { EXTENDED_STARTUPINFO_PRESENT, None, None, - &startup_informations.StartupInfo, + &startup_information.StartupInfo, &mut PROCESS_INFORMATION::default(), - )?; - }; + ) + } { + displayer.failure( + format!("Failed to create the spoofed process: {}", error.message()).as_str(), + ); + + return ExitCode::FAILURE; + } + + displayer.success("The spoofed process is created"); + + ExitCode::SUCCESS + } +} + +impl Trace for Spoofing { + fn name(&self) -> &str { + "Spoofing" + } - Ok(()) + fn as_runnable(&self) -> &dyn Runnable { + self } } diff --git a/src/displayer.rs b/src/displayer.rs new file mode 100644 index 0000000..5b1d315 --- /dev/null +++ b/src/displayer.rs @@ -0,0 +1,92 @@ +// 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::time::Duration; + +pub struct Displayer { + spinner: ProgressBar, + emojis: Emojis, + styles: Styles, +} + +struct Emojis { + pub success: Emoji<'static, 'static>, + pub failure: Emoji<'static, 'static>, +} + +struct Styles { + pub success: Style, + pub failure: Style, +} + +impl Displayer { + 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: &str) { + self.stop(); + + println!( + "{}", + self.format(&self.emojis.success, &self.styles.success, message) + ); + } + + pub fn failure(&mut self, message: &str) { + 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: &str) -> String { + format!("{}{message}", style.apply_to(emoji)) + } +} + +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 Default for Emojis { + fn default() -> Self { + Self { + success: Emoji("āœ”ļø ", ""), + failure: Emoji("āŒ ", ""), + } + } +} + +impl Default for Styles { + fn default() -> Self { + Self { + success: Style::new().green(), + failure: Style::new().red().for_stderr(), + } + } +} diff --git a/src/main.rs b/src/main.rs index 8b41b3b..59e1298 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,14 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +use clap::Parser; +use commands::{Arguments, Traversable}; +use std::process::ExitCode; + mod commands; +mod displayer; mod windows; -use clap::Parser; -use commands::{Arguments, Runnable}; -use std::error::Error; - -fn main() -> Result<(), Box> { - Arguments::parse().run() +fn main() -> ExitCode { + Arguments::parse().traverse().run() } 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/processes.rs b/src/windows/processes.rs index 8017dd9..aa750de 100644 --- a/src/windows/processes.rs +++ b/src/windows/processes.rs @@ -2,15 +2,11 @@ // // 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}, + core::{Error, Owned, Result, HSTRING}, Win32::{ - Foundation::HANDLE, + Foundation::E_INVALIDARG, System::Diagnostics::ToolHelp::{ CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, TH32CS_SNAPPROCESS, @@ -18,21 +14,9 @@ use windows::{ }, }; -#[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> { - let snapshot: Owned = - unsafe { Owned::new(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?) }; - let mut process_entry: PROCESSENTRY32W = PROCESSENTRY32W { +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, ..Default::default() }; @@ -59,5 +43,5 @@ pub fn get_pid(name: &str) -> Result> { } } - Err(Box::new(ProcessNotFound)) + Err(Error::new(E_INVALIDARG, "Process not found")) } diff --git a/src/windows/users.rs b/src/windows/users.rs deleted file mode 100644 index 36dd513..0000000 --- a/src/windows/users.rs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The MalwareTracesGenerator development team -// -// SPDX-License-Identifier: GPL-3.0-or-later - -use windows::{ - core::{Owned, Result as WindowsResult}, - Win32::{ - Foundation::BOOL, - Security::{AllocateAndInitializeSid, CheckTokenMembership, PSID, SECURITY_NT_AUTHORITY}, - System::SystemServices::{DOMAIN_ALIAS_RID_ADMINS, SECURITY_BUILTIN_DOMAIN_RID}, - }, -}; - -pub fn is_administrator() -> WindowsResult { - let mut is_admin: BOOL = false.into(); - - unsafe { - let mut administrators_group: Owned = Owned::new(PSID::default()); - - 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_admin as *mut _)?; - } - - Ok(is_admin.as_bool()) -}