From 7efe284746e4ebc4d1622360ee0d7f6349c34c72 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Thu, 13 Jun 2024 18:39:46 +0200 Subject: [PATCH 01/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20dead?= =?UTF-8?q?=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/tools.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/malware/tools.rs b/src/malware/tools.rs index 23d37c8..8f07b80 100644 --- a/src/malware/tools.rs +++ b/src/malware/tools.rs @@ -6,8 +6,6 @@ pub const EXIST_ALL_GOOD: i32 = 0; pub const EXIST_CLI_ERROR: i32 = 10; pub const EXIST_TEST_ERROR: i32 = 11; -use std::collections::HashSet; - use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use windows::Win32::UI::Shell::IsUserAnAdmin; @@ -38,12 +36,3 @@ pub fn regex_to_string(name: &String) -> String { pub fn process_is_admin() -> bool { return unsafe { IsUserAnAdmin().into() }; } - -pub fn pretty_print_hashset(title: String, data: HashSet) { - println!("{} :", title); - println!("----------------"); - for name in data { - println!("👉 {}", name); - } - println!("----------------"); -} From d1e205310f76d668d012640acc30ea7a96468df7 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Thu, 13 Jun 2024 22:25:17 +0200 Subject: [PATCH 02/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Use=20standard?= =?UTF-8?q?=20return=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/ads.rs | 8 ++++---- src/malware/file.rs | 8 ++++---- src/malware/mutex.rs | 4 ++-- src/malware/namepipe.rs | 4 ++-- src/malware/ppid.rs | 5 ++--- src/malware/service.rs | 8 ++++---- src/malware/tools.rs | 4 ---- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/malware/ads.rs b/src/malware/ads.rs index f592a6a..14db676 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -7,7 +7,7 @@ // Last update 20240224 use crate::malware::tools::{ - hex_to_bytes, regex_to_string, EXIST_ALL_GOOD, EXIST_CLI_ERROR, EXIST_TEST_ERROR, + hex_to_bytes, regex_to_string, }; use clap::Parser; @@ -90,12 +90,12 @@ impl ADS { let barrow_ads: String = self.ads.to_string(); let ret_ads: bool = create_ads(fullname, barrow_ads, payload); if ret_ads == true { - return EXIST_ALL_GOOD; + return 0; } else { - return EXIST_TEST_ERROR; + return 1; } } - EXIST_CLI_ERROR + return 1; } } diff --git a/src/malware/file.rs b/src/malware/file.rs index 8f1df88..5a0c950 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -19,7 +19,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ use crate::malware::tools::{ - hex_to_bytes, process_is_admin, regex_to_string, EXIST_ALL_GOOD, EXIST_TEST_ERROR, + hex_to_bytes, process_is_admin, regex_to_string, }; use clap::Parser; use std::env; @@ -109,7 +109,7 @@ impl FileCreate { pub fn run(&self) -> i32 { if self.admin && !process_is_admin() { println!("Need to have Administrator right to create the file"); - return EXIST_TEST_ERROR; + return 1; } let header: Option> = hex_to_bytes(&self.magicbyte); @@ -133,9 +133,9 @@ impl FileCreate { let ret: bool = create_file(fullname, payload); if ret == true { - return EXIST_ALL_GOOD; + return 0; } else { - return EXIST_TEST_ERROR; + return 1; } } } diff --git a/src/malware/mutex.rs b/src/malware/mutex.rs index ff8467f..19eb1f0 100644 --- a/src/malware/mutex.rs +++ b/src/malware/mutex.rs @@ -10,7 +10,7 @@ use windows::core::{Result as WindowsResult, PCSTR}; use windows::Win32::Foundation::{CloseHandle, HANDLE}; use windows::Win32::System::Threading::CreateMutexA; -use crate::malware::tools::{regex_to_string, EXIST_ALL_GOOD}; +use crate::malware::tools::regex_to_string; use clap::Parser; use std::{thread, time}; @@ -42,6 +42,6 @@ impl Mutex { full_payload = regex_to_string(&self.name); println!("Create the Mutex : {}", full_payload); create_mutex(&full_payload, 2000); - return EXIST_ALL_GOOD; + return 0; } } diff --git a/src/malware/namepipe.rs b/src/malware/namepipe.rs index 6fe0178..09ffd5d 100644 --- a/src/malware/namepipe.rs +++ b/src/malware/namepipe.rs @@ -11,7 +11,7 @@ use windows::Win32::Foundation::{CloseHandle, HANDLE}; use windows::Win32::Storage::FileSystem::PIPE_ACCESS_DUPLEX; use windows::Win32::System::Pipes::{CreateNamedPipeA, PIPE_TYPE_MESSAGE}; -use crate::malware::tools::{regex_to_string, EXIST_ALL_GOOD}; +use crate::malware::tools::regex_to_string; use clap::Parser; use std::{thread, time}; @@ -54,6 +54,6 @@ impl NamePipe { full_payload = regex_to_string(&self.name); println!("Create the namepipe : {}", full_payload); create_name_pipe(&full_payload, 2000); - return EXIST_ALL_GOOD; + return 0; } } diff --git a/src/malware/ppid.rs b/src/malware/ppid.rs index ac6eb64..75c95e2 100644 --- a/src/malware/ppid.rs +++ b/src/malware/ppid.rs @@ -6,7 +6,6 @@ // // Last update 20240224 -use crate::malware::tools::{EXIST_ALL_GOOD, EXIST_TEST_ERROR}; use clap::Parser; use rand::prelude::SliceRandom; @@ -131,10 +130,10 @@ impl PPID { let result: bool = create_ppid(&self.executable); if result { println!("All good "); - return EXIST_ALL_GOOD; + return 0; } else { println!("Sorry get a error"); - return EXIST_TEST_ERROR; + return 1; } } } diff --git a/src/malware/service.rs b/src/malware/service.rs index 1a928f9..4522df1 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -13,7 +13,7 @@ use windows::Win32::System::Services::{ ENUM_SERVICE_TYPE, SC_MANAGER_ALL_ACCESS, SERVICE_CONTROL_STOP, SERVICE_ERROR, SERVICE_START_TYPE, SERVICE_STATUS, }; -use crate::malware::tools::{process_is_admin, EXIST_ALL_GOOD, EXIST_TEST_ERROR}; +use crate::malware::tools::process_is_admin; use clap::Parser; use std::{thread, time}; @@ -102,7 +102,7 @@ impl BYOVD { println!("Bring Your Own Vulnerable Driver"); if process_is_admin() == false { - return EXIST_TEST_ERROR; + return 1; } // Todo check path is valid or not :) @@ -110,10 +110,10 @@ impl BYOVD { let result: bool = create_driver_service(&self.internal, &self.display, &self.path); if result { println!("All good "); - return EXIST_ALL_GOOD; + return 0; } else { println!("Sorry get a error"); - return EXIST_TEST_ERROR; + return 1; } } } diff --git a/src/malware/tools.rs b/src/malware/tools.rs index 8f07b80..1408030 100644 --- a/src/malware/tools.rs +++ b/src/malware/tools.rs @@ -2,10 +2,6 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -pub const EXIST_ALL_GOOD: i32 = 0; -pub const EXIST_CLI_ERROR: i32 = 10; -pub const EXIST_TEST_ERROR: i32 = 11; - use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use windows::Win32::UI::Shell::IsUserAnAdmin; From bfd03043dae76b099324df0cf6f42c6117c844c6 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 16 Jun 2024 13:24:51 +0200 Subject: [PATCH 03/14] =?UTF-8?q?style:=20=F0=9F=92=84=20Format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 2 +- src/malware/ads.rs | 4 +--- src/malware/file.rs | 4 +--- src/malware/service.rs | 6 +++--- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 96123f5..fe394a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,8 @@ mod cli; mod malware; -use cli::Arguments; use clap::Parser; +use cli::Arguments; fn banner() { let banner: &str = " diff --git a/src/malware/ads.rs b/src/malware/ads.rs index 14db676..8f9f42f 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -6,9 +6,7 @@ // // Last update 20240224 -use crate::malware::tools::{ - hex_to_bytes, regex_to_string, -}; +use crate::malware::tools::{hex_to_bytes, regex_to_string}; use clap::Parser; use std::path::Path; diff --git a/src/malware/file.rs b/src/malware/file.rs index 5a0c950..b145e61 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -18,9 +18,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ -use crate::malware::tools::{ - hex_to_bytes, process_is_admin, regex_to_string, -}; +use crate::malware::tools::{hex_to_bytes, process_is_admin, regex_to_string}; use clap::Parser; use std::env; use std::ffi::OsString; diff --git a/src/malware/service.rs b/src/malware/service.rs index 4522df1..b92907e 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -6,6 +6,9 @@ // // Last update 20240224 +use crate::malware::tools::process_is_admin; +use clap::Parser; +use std::{thread, time}; use windows::core::{Result as WindowsResult, PCWSTR}; use windows::Win32::Security::SC_HANDLE; use windows::Win32::System::Services::{ @@ -13,9 +16,6 @@ use windows::Win32::System::Services::{ ENUM_SERVICE_TYPE, SC_MANAGER_ALL_ACCESS, SERVICE_CONTROL_STOP, SERVICE_ERROR, SERVICE_START_TYPE, SERVICE_STATUS, }; -use crate::malware::tools::process_is_admin; -use clap::Parser; -use std::{thread, time}; #[derive(Parser)] pub struct BYOVD { From edd5e681df76ca4a3a9dfca99fa07a940ea7c15b Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Mon, 17 Jun 2024 14:03:35 +0200 Subject: [PATCH 04/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Directly=20par?= =?UTF-8?q?se=20vector=20with=20clap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/ads.rs | 17 +++++++---------- src/malware/file.rs | 17 +++++++---------- src/malware/tools.rs | 14 -------------- 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/malware/ads.rs b/src/malware/ads.rs index 8f9f42f..cfd53a8 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -6,7 +6,7 @@ // // Last update 20240224 -use crate::malware::tools::{hex_to_bytes, regex_to_string}; +use crate::malware::tools::regex_to_string; use clap::Parser; use std::path::Path; @@ -32,11 +32,14 @@ pub struct ADS { #[clap( short = 'd', long, + value_parser, + num_args = 1.., + value_delimiter = ' ', required = true, - default_value = "", + default_value = "70 114 97 99 107 49 49 51", help = "Data to write in HEX" )] - data: String, + data: Vec, } fn create_ads(fullpath: String, adsname: String, hex_data: Vec) -> bool { @@ -79,14 +82,8 @@ impl ADS { if self.filename.len() > 0 { let fullname: String = regex_to_string(&self.filename); - let header: Option> = hex_to_bytes(&self.data); - let payload: Vec = match header { - Some(data) => data, - None => vec![70, 114, 97, 99, 107, 49, 49, 51], - }; - let barrow_ads: String = self.ads.to_string(); - let ret_ads: bool = create_ads(fullname, barrow_ads, payload); + let ret_ads: bool = create_ads(fullname, barrow_ads, self.data.to_vec()); if ret_ads == true { return 0; } else { diff --git a/src/malware/file.rs b/src/malware/file.rs index b145e61..a842ba3 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -18,7 +18,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ -use crate::malware::tools::{hex_to_bytes, process_is_admin, regex_to_string}; +use crate::malware::tools::{process_is_admin, regex_to_string}; use clap::Parser; use std::env; use std::ffi::OsString; @@ -56,11 +56,14 @@ pub struct FileCreate { #[clap( short = 'm', long, + value_parser, + num_args = 1.., + value_delimiter = ' ', required = true, - default_value = "", + default_value = "70 114 97 99 107 49 49 51", help = "MagicBytes name to use with module manual " )] - magicbyte: String, + magicbyte: Vec, #[clap( short = 'a', long, @@ -110,12 +113,6 @@ impl FileCreate { return 1; } - let header: Option> = hex_to_bytes(&self.magicbyte); - let payload: Vec = match header { - Some(data) => data, - None => vec![70, 114, 97, 99, 107, 49, 49, 51], - }; - let fullname: String; if self.filename.len() > 0 { fullname = regex_to_string(&self.filename); @@ -128,7 +125,7 @@ impl FileCreate { println!("Create a file on disk"); - let ret: bool = create_file(fullname, payload); + let ret: bool = create_file(fullname, self.magicbyte.to_vec()); if ret == true { return 0; diff --git a/src/malware/tools.rs b/src/malware/tools.rs index 1408030..748fa14 100644 --- a/src/malware/tools.rs +++ b/src/malware/tools.rs @@ -5,20 +5,6 @@ use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use windows::Win32::UI::Shell::IsUserAnAdmin; -pub fn hex_to_bytes(s: &str) -> Option> { - if s.len() % 2 == 0 { - (0..s.len()) - .step_by(2) - .map(|i| { - s.get(i..i + 2) - .and_then(|sub| u8::from_str_radix(sub, 16).ok()) - }) - .collect() - } else { - None - } -} - pub fn regex_to_string(name: &String) -> String { let mut gen: Generator = Generator::new(name, rand::thread_rng(), DEFAULT_MAX_REPEAT).unwrap(); From 62ad09effe40dfed979ddd104b6ddcc75e77eaed Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Tue, 25 Jun 2024 12:52:05 +0200 Subject: [PATCH 05/14] =?UTF-8?q?feat:=20=E2=9C=A8=20Use=20base64=20instea?= =?UTF-8?q?d=20of=20a=20byte=20array?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/malware/ads.rs | 21 +++++++++++++-------- src/malware/file.rs | 20 +++++++++++++------- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fb7e7d..4b3dc44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "cc" version = "1.0.83" @@ -436,6 +442,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "wag" version = "1.0.0" dependencies = [ + "base64", "clap", "rand", "regex_generate", diff --git a/Cargo.toml b/Cargo.toml index de740dd..1e4dc76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ rpath = false winres = "0" [dependencies] +base64 = { version = "0.22.1" } windows = { version = "0.52", features = [ "Win32_System_Pipes", "Win32_Foundation", diff --git a/src/malware/ads.rs b/src/malware/ads.rs index cfd53a8..0d8447f 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -7,7 +7,7 @@ // Last update 20240224 use crate::malware::tools::regex_to_string; - +use base64::engine::{general_purpose, Engine}; use clap::Parser; use std::path::Path; @@ -32,14 +32,11 @@ pub struct ADS { #[clap( short = 'd', long, - value_parser, - num_args = 1.., - value_delimiter = ' ', required = true, - default_value = "70 114 97 99 107 49 49 51", - help = "Data to write in HEX" + default_value = "V2VsY29tZSB0byB0aGUgV0FH", + help = "Data to write in base64" )] - data: Vec, + data: String, } fn create_ads(fullpath: String, adsname: String, hex_data: Vec) -> bool { @@ -83,7 +80,15 @@ impl ADS { let fullname: String = regex_to_string(&self.filename); let barrow_ads: String = self.ads.to_string(); - let ret_ads: bool = create_ads(fullname, barrow_ads, self.data.to_vec()); + let payload: Vec = match general_purpose::STANDARD.decode(self.data.as_str()) { + Ok(decoded) => decoded, + Err(_) => { + println!("Could not decode the data."); + + return 1; + } + }; + let ret_ads: bool = create_ads(fullname, barrow_ads, payload); if ret_ads == true { return 0; } else { diff --git a/src/malware/file.rs b/src/malware/file.rs index a842ba3..4714913 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -19,6 +19,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ use crate::malware::tools::{process_is_admin, regex_to_string}; +use base64::engine::{general_purpose, Engine}; use clap::Parser; use std::env; use std::ffi::OsString; @@ -56,14 +57,11 @@ pub struct FileCreate { #[clap( short = 'm', long, - value_parser, - num_args = 1.., - value_delimiter = ' ', required = true, - default_value = "70 114 97 99 107 49 49 51", - help = "MagicBytes name to use with module manual " + default_value = "V2VsY29tZSB0byB0aGUgV0FH", + help = "MagicBytes name to use with module manual in base64" )] - magicbyte: Vec, + magicbyte: String, #[clap( short = 'a', long, @@ -125,7 +123,15 @@ impl FileCreate { println!("Create a file on disk"); - let ret: bool = create_file(fullname, self.magicbyte.to_vec()); + let payload: Vec = match general_purpose::STANDARD.decode(self.magicbyte.as_str()) { + Ok(decoded) => decoded, + Err(_) => { + println!("Could not decode the data."); + + return 1; + } + }; + let ret: bool = create_file(fullname, payload); if ret == true { return 0; From 63d557bb8f97574db6972d8a11bc68e883884303 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 29 Jun 2024 12:47:09 +0200 Subject: [PATCH 06/14] =?UTF-8?q?feat!:=20=E2=9C=A8=20Remove=20support=20f?= =?UTF-8?q?or=20env=20variables,=20put=20the=20full=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/file.rs | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/malware/file.rs b/src/malware/file.rs index 4714913..85707dd 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -21,10 +21,8 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list use crate::malware::tools::{process_is_admin, regex_to_string}; use base64::engine::{general_purpose, Engine}; use clap::Parser; -use std::env; -use std::ffi::OsString; use std::io::Result as IOResult; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::time::Duration; use std::{thread, time}; @@ -33,27 +31,11 @@ pub struct FileCreate { #[clap( short = 'f', long, - required = false, + required = true, default_value = "", help = "Full path filename (regex)" )] filename: String, - #[clap( - short = 'v', - long, - required = false, - default_value = "", - help = "Use the CMD variable" - )] - cmd_var: String, - #[clap( - short = 'p', - long, - required = false, - default_value = "", - help = "Use the CMD path" - )] - cmd_path: String, #[clap( short = 'm', long, @@ -111,15 +93,6 @@ impl FileCreate { return 1; } - let fullname: String; - if self.filename.len() > 0 { - fullname = regex_to_string(&self.filename); - } else { - let filename: String = regex_to_string(&self.cmd_path); - let var_path: OsString = env::var_os(&self.cmd_var).unwrap(); - let full_path: PathBuf = Path::new(&var_path).join(filename); - fullname = String::from(full_path.to_string_lossy()); - } println!("Create a file on disk"); From ccc70e6c19c2611b91a04f3fd52f8df94bf5383b Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sat, 29 Jun 2024 12:51:15 +0200 Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20regex?= =?UTF-8?q?=5Fto=5Fstring=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/ads.rs | 21 +++++++++++++++++++-- src/malware/file.rs | 22 +++++++++++++++++++++- src/malware/mutex.rs | 36 ++++++++++++++++++++++++++++-------- src/malware/namepipe.rs | 31 ++++++++++++++++++++++++++----- src/malware/tools.rs | 11 ----------- 5 files changed, 94 insertions(+), 27 deletions(-) diff --git a/src/malware/ads.rs b/src/malware/ads.rs index 0d8447f..67f587a 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -6,9 +6,9 @@ // // Last update 20240224 -use crate::malware::tools::regex_to_string; use base64::engine::{general_purpose, Engine}; use clap::Parser; +use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use std::path::Path; #[derive(Parser)] @@ -77,8 +77,25 @@ impl ADS { println!("Alternate Data Stream"); if self.filename.len() > 0 { - let fullname: String = regex_to_string(&self.filename); + let mut generator: Generator = + match Generator::new(&self.filename, rand::thread_rng(), DEFAULT_MAX_REPEAT) { + Ok(generator) => generator, + Err(_) => { + println!("Regex expressions are malformed."); + return 1; + } + }; + let mut buffer: Vec = vec![]; + generator.generate(&mut buffer).unwrap(); + let fullname: String = match String::from_utf8(buffer) { + Ok(string) => string, + Err(_) => { + println!("Filename contains non-utf8 characters."); + + return 1; + } + }; let barrow_ads: String = self.ads.to_string(); let payload: Vec = match general_purpose::STANDARD.decode(self.data.as_str()) { Ok(decoded) => decoded, diff --git a/src/malware/file.rs b/src/malware/file.rs index 85707dd..90adfb3 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -18,9 +18,10 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ -use crate::malware::tools::{process_is_admin, regex_to_string}; +use crate::malware::tools::process_is_admin; use base64::engine::{general_purpose, Engine}; use clap::Parser; +use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use std::io::Result as IOResult; use std::path::Path; use std::time::Duration; @@ -93,6 +94,25 @@ impl FileCreate { return 1; } + let mut generator: Generator = + match Generator::new(&self.filename, rand::thread_rng(), DEFAULT_MAX_REPEAT) { + Ok(generator) => generator, + Err(_) => { + println!("Regex expressions are malformed."); + + return 1; + } + }; + let mut buffer: Vec = vec![]; + generator.generate(&mut buffer).unwrap(); + let fullname: String = match String::from_utf8(buffer) { + Ok(string) => string, + Err(_) => { + println!("Filename contains non-utf8 characters."); + + return 1; + } + }; println!("Create a file on disk"); diff --git a/src/malware/mutex.rs b/src/malware/mutex.rs index 19eb1f0..95655e9 100644 --- a/src/malware/mutex.rs +++ b/src/malware/mutex.rs @@ -6,14 +6,13 @@ // // Last update 20240224 +use clap::Parser; +use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; +use std::{thread, time}; use windows::core::{Result as WindowsResult, PCSTR}; use windows::Win32::Foundation::{CloseHandle, HANDLE}; use windows::Win32::System::Threading::CreateMutexA; -use crate::malware::tools::regex_to_string; -use clap::Parser; -use std::{thread, time}; - #[derive(Parser)] pub struct Mutex { #[clap( @@ -38,10 +37,31 @@ fn create_mutex(name: &String, wait: u64) { impl Mutex { pub fn run(&self) -> i32 { println!("Create Mutex"); - let full_payload: String; - full_payload = regex_to_string(&self.name); - println!("Create the Mutex : {}", full_payload); - create_mutex(&full_payload, 2000); + + let mut generator: Generator = + match Generator::new(&self.name, rand::thread_rng(), DEFAULT_MAX_REPEAT) { + Ok(generator) => generator, + Err(_) => { + println!("Regex expressions are malformed."); + + return 1; + } + }; + let mut buffer: Vec = vec![]; + generator.generate(&mut buffer).unwrap(); + let payload: String = match String::from_utf8(buffer) { + Ok(string) => string, + Err(_) => { + println!("Filename contains non-utf8 characters."); + + return 1; + } + }; + + println!("Create the Mutex : {}", payload); + + create_mutex(&payload, 2000); + return 0; } } diff --git a/src/malware/namepipe.rs b/src/malware/namepipe.rs index 09ffd5d..2bd3995 100644 --- a/src/malware/namepipe.rs +++ b/src/malware/namepipe.rs @@ -6,12 +6,12 @@ // // Last update 20240224 +use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use windows::core::{Result as WindowsResult, PCSTR}; use windows::Win32::Foundation::{CloseHandle, HANDLE}; use windows::Win32::Storage::FileSystem::PIPE_ACCESS_DUPLEX; use windows::Win32::System::Pipes::{CreateNamedPipeA, PIPE_TYPE_MESSAGE}; -use crate::malware::tools::regex_to_string; use clap::Parser; use std::{thread, time}; @@ -50,10 +50,31 @@ fn create_name_pipe(name: &String, wait: u64) { impl NamePipe { pub fn run(&self) -> i32 { println!("Create NamePipe"); - let full_payload: String; - full_payload = regex_to_string(&self.name); - println!("Create the namepipe : {}", full_payload); - create_name_pipe(&full_payload, 2000); + + let mut generator: Generator = + match Generator::new(&self.name, rand::thread_rng(), DEFAULT_MAX_REPEAT) { + Ok(generator) => generator, + Err(_) => { + println!("Regex expressions are malformed."); + + return 1; + } + }; + let mut buffer: Vec = vec![]; + generator.generate(&mut buffer).unwrap(); + let payload: String = match String::from_utf8(buffer) { + Ok(string) => string, + Err(_) => { + println!("Filename contains non-utf8 characters."); + + return 1; + } + }; + + println!("Create the namepipe : {}", payload); + + create_name_pipe(&payload, 2000); + return 0; } } diff --git a/src/malware/tools.rs b/src/malware/tools.rs index 748fa14..b0dbba6 100644 --- a/src/malware/tools.rs +++ b/src/malware/tools.rs @@ -2,19 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; use windows::Win32::UI::Shell::IsUserAnAdmin; -pub fn regex_to_string(name: &String) -> String { - let mut gen: Generator = - Generator::new(name, rand::thread_rng(), DEFAULT_MAX_REPEAT).unwrap(); - let mut buffer: Vec = vec![]; - gen.generate(&mut buffer).unwrap(); - let output: String = String::from_utf8(buffer).unwrap(); - - return output; -} - pub fn process_is_admin() -> bool { return unsafe { IsUserAnAdmin().into() }; } From ee5a632f579b2e9e35c73c8f488accf615e88e64 Mon Sep 17 00:00:00 2001 From: frack113 <62423083+frack113@users.noreply.github.com> Date: Sat, 29 Jun 2024 17:12:33 +0200 Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20usele?= =?UTF-8?q?ss=20default=5Fvalue=20for=20clap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/ads.rs | 11 ++--------- src/malware/file.rs | 3 +-- src/malware/mutex.rs | 1 - src/malware/namepipe.rs | 1 - src/malware/ppid.rs | 1 + src/malware/service.rs | 21 ++++++++++++++++++--- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/malware/ads.rs b/src/malware/ads.rs index 67f587a..1e71a1a 100644 --- a/src/malware/ads.rs +++ b/src/malware/ads.rs @@ -17,22 +17,15 @@ pub struct ADS { short = 'f', long, required = true, - default_value = "", help = "Full path filename (regex)" )] filename: String, - #[clap( - short = 'a', - long, - required = true, - default_value = "", - help = "ADS to use" - )] + #[clap(short = 'a', long, required = true, help = "ADS to use")] ads: String, #[clap( short = 'd', long, - required = true, + required = false, default_value = "V2VsY29tZSB0byB0aGUgV0FH", help = "Data to write in base64" )] diff --git a/src/malware/file.rs b/src/malware/file.rs index 90adfb3..567d829 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -33,14 +33,13 @@ pub struct FileCreate { short = 'f', long, required = true, - default_value = "", help = "Full path filename (regex)" )] filename: String, #[clap( short = 'm', long, - required = true, + required = false, default_value = "V2VsY29tZSB0byB0aGUgV0FH", help = "MagicBytes name to use with module manual in base64" )] diff --git a/src/malware/mutex.rs b/src/malware/mutex.rs index 95655e9..e186a04 100644 --- a/src/malware/mutex.rs +++ b/src/malware/mutex.rs @@ -19,7 +19,6 @@ pub struct Mutex { short = 'n', long, required = true, - default_value = "wag", help = "Regex of the Mutex to Create" )] name: String, diff --git a/src/malware/namepipe.rs b/src/malware/namepipe.rs index 2bd3995..d025143 100644 --- a/src/malware/namepipe.rs +++ b/src/malware/namepipe.rs @@ -21,7 +21,6 @@ pub struct NamePipe { short = 'n', long, required = true, - default_value = "wag", help = "Regex of the PipeName to Create" )] name: String, diff --git a/src/malware/ppid.rs b/src/malware/ppid.rs index 75c95e2..11df1b8 100644 --- a/src/malware/ppid.rs +++ b/src/malware/ppid.rs @@ -31,6 +31,7 @@ pub struct PPID { #[clap( short = 'e', long, + required = true, help = "Full path to the executable eg: c:\\temp..." )] executable: String, diff --git a/src/malware/service.rs b/src/malware/service.rs index b92907e..6ce560c 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -19,11 +19,26 @@ use windows::Win32::System::Services::{ #[derive(Parser)] pub struct BYOVD { - #[clap(short = 'n', long, help = "Internal Name of the service")] + #[clap( + short = 'n', + long, + required = true, + help = "Internal Name of the service" + )] internal: String, - #[clap(short = 'd', long, help = "Displayed Name of the service")] + #[clap( + short = 'd', + long, + required = true, + help = "Displayed Name of the service" + )] display: String, - #[clap(short = 'p', long, help = "Full path to the driver eg: c:\\temp...")] + #[clap( + short = 'p', + long, + required = true, + help = "Full path to the driver eg: c:\\temp..." + )] path: String, } From 33fe0ba73943bdf831422efd803870d7da43f841 Mon Sep 17 00:00:00 2001 From: frack113 <62423083+frack113@users.noreply.github.com> Date: Sat, 29 Jun 2024 17:14:05 +0200 Subject: [PATCH 09/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Add=20missing?= =?UTF-8?q?=20warning=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/service.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/malware/service.rs b/src/malware/service.rs index 6ce560c..115a7d0 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -117,6 +117,7 @@ impl BYOVD { println!("Bring Your Own Vulnerable Driver"); if process_is_admin() == false { + println!("Need to have Administrator right to create the service"); return 1; } From d4eefd833d11e832d29b028167e19f614f2a2e17 Mon Sep 17 00:00:00 2001 From: frack113 <62423083+frack113@users.noreply.github.com> Date: Sun, 30 Jun 2024 10:39:28 +0200 Subject: [PATCH 10/14] =?UTF-8?q?docs:=20=F0=9F=93=9A=20Update=20the=20doc?= =?UTF-8?q?=20to=20the=20last=20cli?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 ++++ docs/cli_help.md | 155 +++++++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index f083ce4..b512d4a 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,16 @@ wag.exe ``` Example can be found here [cli_help](./docs/cli_help.md) + +# Actions + + - [X] Alternate data stream + - [X] BYOVD: load a driver + - [X] file drop from executable + - [X] mutex + - [X] named pipe + - [X] ppid spoofing + - [ ] Stealer browers information (only open file) + - [ ] Stealer cryto wallet (only open file) + - [ ] Stealer file of interrest + - [ ] WMI action \ No newline at end of file diff --git a/docs/cli_help.md b/docs/cli_help.md index c2a6d0c..507527b 100644 --- a/docs/cli_help.md +++ b/docs/cli_help.md @@ -6,93 +6,104 @@ SPDX-License-Identifier: GPL-3.0-or-later # Ads -`wag ads -f file_full_path -a ads -d data` +`wag ads -f fullpath -a ads -d data` -| Type | ads | data | -| -------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| ZoneTransfer 0 | Zone.Identifier | 5b5a6f6e655472616e736665725d0d0a5a6f6e6549643d300d0a526566657272657255726c3d633a5c77696e646f77735c7761672e7a69700d0a | -| ZoneTransfer 1 | Zone.Identifier | 5b5a6f6e655472616e736665725d0d0a5a6f6e6549643d310d0a526566657272657255726c3d2f2f7376725f41442f7761672e7a69700d0a | -| ZoneTransfer 2 | Zone.Identifier | 5b5a6f6e655472616e736665725d0d0a5a6f6e6549643d320d0a526566657272657255726c3d687474703a2f2f6d79736974652e6f72672f7761672e7a69700d0a | -| ZoneTransfer 3 | Zone.Identifier | 5b5a6f6e655472616e736665725d0d0a5a6f6e6549643d330d0a526566657272657255726c3d68747470733a2f2f736f6d65736974652e636f6d2f7761672e7a69700d0a | -| ZoneTransfer 4 | Zone.Identifier | 5b5a6f6e655472616e736665725d0d0a5a6f6e6549643d340d0a526566657272657255726c3d687474703a2f2f6d616c776172652e6261642f7761672e7a69700d0a | -| Sysmon | sysmon | 4920616D20746865206265737420746F20686964652066726F6D207379736D6F6E" | +* fullpath: regex of the full path +* ads: name of the stream +* data: base64 of the data to write + +| Type | ads | data | +| -------------- | --------------- | -------------------------------------------------------------------------------------------- | +| ZoneTransfer 0 | Zone.Identifier | W1pvbmVUcmFuc2Zlcl0NClpvbmVJZD0wDQpSZWZlcnJlclVybD1jOlx3aW5kb3dzXHdhZy56aXANCg== | +| ZoneTransfer 1 | Zone.Identifier | W1pvbmVUcmFuc2Zlcl0NClpvbmVJZD0xDQpSZWZlcnJlclVybD0vL3N2cl9BRC93YWcuemlwDQo= | +| ZoneTransfer 2 | Zone.Identifier | W1pvbmVUcmFuc2Zlcl0NClpvbmVJZD0yDQpSZWZlcnJlclVybD1odHRwOi8vbXlzaXRlLm9yZy93YWcuemlwDQo= | +| ZoneTransfer 3 | Zone.Identifier | W1pvbmVUcmFuc2Zlcl0NClpvbmVJZD0zDQpSZWZlcnJlclVybD1odHRwczovL3NvbWVzaXRlLmNvbS93YWcuemlwDQo= | +| ZoneTransfer 4 | Zone.Identifier | W1pvbmVUcmFuc2Zlcl0NClpvbmVJZD00DQpSZWZlcnJlclVybD1odHRwOi8vbWFsd2FyZS5iYWQvd2FnLnppcA0K | +| Sysmon | sysmon | SSBhbSB0aGUgYmVzdCB0byBoaWRlIGZyb20gc3lzbW9u | # File ## magicbytes -| Type | Hex | -| ---- | ---------------------------------------------------- | -| Exe | 4D5A | -| Zip | 504B0304 | -| Vmdk | 4B444D | -| Iso | 4344303031 | -| Txt | 412073696d706c6520746578742066696c65 | -| Ps1 | 77726974652d686f73742022574147207761732048657265220a | +| Type | Hex | +| ---- | ------------------------------------ | +| Exe | TVo= | +| Zip | UEsDBA== | +| Vmdk | S0RN | +| Iso | Q0QwMDE= | +| Txt | QSBzaW1wbGUgdGV4dCBmaWxl | +| Ps1 | d3JpdGUtaG9zdCAiV0FHIHdhcyBIZXJlIgo= | ## well known File -`wag file-create -f fullpath -m Magicbyte_Hex` -`wag file-create -v cmd_var -p cmd_path -m Magicbyte_Hex` - -| name | Admin | Magicbyte | fullpath | cmd_var | cmd_path | -| -------------- | ----- | --------- | -------------------------------------------- | ------------ | -------------------------------------- | -| NPPSpy | true | Exe | `C:/Windows/System32/NPPSpy\.dll` | | | -| SafetyKatz | false | Zip | | SystemRoot | `Temp\\debug\.bin` | -| SmallSieve_txt | false | Txt | | LocalAppData | `MicrosoftWindowsOutlookDataPlus\.txt` | -| SmallSieve_exe | false | Exe | | AppData | `OutlookMicrosift\\index\.exe` | -| SNAKE_jpsetup | false | Exe | | TEMP | `jpsetup\.exe` | -| SNAKE_jpinst | false | Exe | | TEMP | `jpinst\\.exe` | -| SNAKE_Comadmin | true | Exe | `C:\\Windows\\System32\\Com\\Comadmin\.dat` | | | -| COLDSTEEL_exe | false | Exe | `C:\\users\\public\\Documents\\dllhost\.exe` | | | -| COLDSTEEL_dll | false | Exe | | APPDATA | `newdev\.dll` | -| temp_ps1_12 | false | Ps1 | | SystemRoot | `temp\[0-9a-f]{12}\.ps1` | +`wag file-create -f fullpath -m Magicbyte_Hex ` + +* fullpath: regex of the full path +* Magicbyte_Hex: base64 of the magicbytes to write +* admin: can use `--admin` to check if run as administrator + +| Type | Admin | Magicbyte | fullpath | +| -------------- | ----- | --------- | -------------------------------------------------------- | +| NPPSpy | true | Exe | `C:/Windows/System32/NPPSpy\.dll` | +| SafetyKatz | false | Zip | *SystemRoot* + `Temp\\debug\.bin` | +| SmallSieve_txt | false | Txt | *LocalAppData* + `MicrosoftWindowsOutlookDataPlus\.txt` | +| SmallSieve_exe | false | Exe | *AppData* + `OutlookMicrosift\\index\.exe` | +| SNAKE_jpsetup | false | Exe | *TEMP* + `jpsetup\.exe` | +| SNAKE_jpinst | false | Exe | *TEMP* + `jpinst\\.exe` | +| SNAKE_Comadmin | true | Exe | `C:\\Windows\\System32\\Com\\Comadmin\.dat` | +| COLDSTEEL_exe | false | Exe | `C:\\users\\public\\Documents\\dllhost\.exe` | +| COLDSTEEL_dll | false | Exe | *APPDATA* + `newdev\.dll` | +| temp_ps1_12 | false | Ps1 | *SystemRoot* + `temp\[0-9a-f]{12}\.ps1` | + +Remark: You need to convert the environment variable into a correct regular expression. # Named pipe -`wag name-pipe -n "regex"` - -| name | regex | | -| ------------------ | -------------------------------------------------- | ------------------------------ | -| CSExec | `\\csexecsvc` | | -| psexec | `\\psexec` | | -| psexec | `\\PAExec` | | -| psexec | `\\remcom` | | -| psexec | `\\csexec` | | -| psexec | `\\PSEXESVC` | | -| Cobal_strike | `\\mojo\\.5688\\.8052\\.(?:183894939787088877 | 35780273329370473)[0-9a-f]{2}` | -| Cobal_strike | `\\wkssvc_?[0-9a-f]{2}` | | -| Cobal_strike | `\\ntsvcs[0-9a-f]{2}` | | -| Cobal_strike | `\\DserNamePipe[0-9a-f]{2}` | | -| Cobal_strike | `\\SearchTextHarvester[0-9a-f]{2}` | | -| Cobal_strike | `\\mypipe-(?:f | h)[0-9a-f]{2}` | -| Cobal_strike | `\\windows\\.update\\.manager[0-9a-f]{2,3}` | | -| Cobal_strike | `\\ntsvcs_[0-9a-f]{2}` | | -| Cobal_strike | `\\scerpc_?[0-9a-f]{2}` | | -| Cobal_strike | `\\PGMessagePipe[0-9a-f]{2}` | | -| Cobal_strike | `\\MsFteWds[0-9a-f]{2}` | | -| Cobal_strike | `\\f4c3[0-9a-f]{2}` | | -| Cobal_strike | `\\fullduplex_[0-9a-f]{2}` | | -| Cobal_strike | `\\msrpc_[0-9a-f]{4}` | | -| Cobal_strike | `\\win\\msrpc_[0-9a-f]{2}` | | -| Cobal_strike | `\\f53f[0-9a-f]{2}` | | -| Cobal_strike | `\\rpc_[0-9a-f]{2}` | | -| Cobal_strike | `\\spoolss_[0-9a-f]{2}` | | -| Cobal_strike | `\\Winsock2\\CatalogChangeListener-[0-9a-f]{3}-0,` | | -| DiagTrackEoP | `thisispipe` | | -| EfsPotato | `\\pipe\\srvsvc` | | -| Credential_Dumping | `\\cachedump` | | -| Credential_Dumping | `\\lsadump` | | -| Credential_Dumping | `\\wceservicepipe` | | -| Koh | `\\imposecost` | | -| Koh | `\\imposingcost` | | -| PowerShell | `\\PSHost` | | -| ADFS | `\\MICROSOFT##WID\\tsql\\query` | | +`wag name-pipe -n name` + +* name: named pipe name as a regex + +| Type | name | +| ------------------ | -------------------------------------------------- | +| CSExec | `\\csexecsvc` | +| psexec | `\\psexec` | +| psexec | `\\PAExec` | +| psexec | `\\remcom` | +| psexec | `\\csexec` | +| psexec | `\\PSEXESVC` | +| Cobal_strike | `\\wkssvc_?[0-9a-f]{2}` | +| Cobal_strike | `\\ntsvcs[0-9a-f]{2}` | +| Cobal_strike | `\\DserNamePipe[0-9a-f]{2}` | +| Cobal_strike | `\\SearchTextHarvester[0-9a-f]{2}` | +| Cobal_strike | `\\windows\\.update\\.manager[0-9a-f]{2,3}` | +| Cobal_strike | `\\ntsvcs_[0-9a-f]{2}` | +| Cobal_strike | `\\scerpc_?[0-9a-f]{2}` | +| Cobal_strike | `\\PGMessagePipe[0-9a-f]{2}` | +| Cobal_strike | `\\MsFteWds[0-9a-f]{2}` | +| Cobal_strike | `\\f4c3[0-9a-f]{2}` | +| Cobal_strike | `\\fullduplex_[0-9a-f]{2}` | +| Cobal_strike | `\\msrpc_[0-9a-f]{4}` | +| Cobal_strike | `\\win\\msrpc_[0-9a-f]{2}` | +| Cobal_strike | `\\f53f[0-9a-f]{2}` | +| Cobal_strike | `\\rpc_[0-9a-f]{2}` | +| Cobal_strike | `\\spoolss_[0-9a-f]{2}` | +| Cobal_strike | `\\Winsock2\\CatalogChangeListener-[0-9a-f]{3}-0,` | +| DiagTrackEoP | `thisispipe` | +| EfsPotato | `\\pipe\\srvsvc` | +| Credential_Dumping | `\\cachedump` | +| Credential_Dumping | `\\lsadump` | +| Credential_Dumping | `\\wceservicepipe` | +| Koh | `\\imposecost` | +| Koh | `\\imposingcost` | +| PowerShell | `\\PSHost` | +| ADFS | `\\MICROSOFT##WID\\tsql\\query` | # Mutex -`wag mutex -n "regex"` +`wag mutex -n name` + +* name: mutex name as a regex -| name | regex | +| Type | name | | ---------- | ------------------ | | avoslocker | `Cheic0WaZie6zeiy` | From 5f0000a83a35afde9fa85a1cf44d308a212d3014 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 30 Jun 2024 22:00:33 +0200 Subject: [PATCH 11/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Move=20adminis?= =?UTF-8?q?trator=20check=20to=20its=20own=20file=20and=20remove=20tools.r?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 1 + src/main.rs | 1 + src/malware.rs | 1 - src/malware/file.rs | 16 ++++++++++++++-- src/malware/service.rs | 14 ++++++++++++-- src/malware/tools.rs | 9 --------- src/windows.rs | 1 + src/windows/users.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 69 insertions(+), 14 deletions(-) delete mode 100644 src/malware/tools.rs create mode 100644 src/windows.rs create mode 100644 src/windows/users.rs diff --git a/Cargo.toml b/Cargo.toml index 1e4dc76..5f8fc51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ windows = { version = "0.52", features = [ "Win32_UI_Shell", "Win32_System_IO", "Win32_System_Services", + "Win32_System_SystemServices", ] } clap = { version = "4", features = ["derive"] } rand = "0" diff --git a/src/main.rs b/src/main.rs index fe394a8..d5f43e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod cli; mod malware; +mod windows; use clap::Parser; use cli::Arguments; diff --git a/src/malware.rs b/src/malware.rs index 2c4de67..ad1cf64 100644 --- a/src/malware.rs +++ b/src/malware.rs @@ -8,4 +8,3 @@ pub mod mutex; pub mod namepipe; pub mod ppid; pub mod service; -pub mod tools; diff --git a/src/malware/file.rs b/src/malware/file.rs index 567d829..03049e1 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -18,7 +18,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ -use crate::malware::tools::process_is_admin; +use crate::windows::users::is_admin; use base64::engine::{general_purpose, Engine}; use clap::Parser; use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; @@ -88,7 +88,19 @@ fn create_file(fullpath: String, hex_data: Vec) -> bool { impl FileCreate { pub fn run(&self) -> i32 { - if self.admin && !process_is_admin() { + if self.admin + && match is_admin() { + Ok(is_admin) => is_admin, + Err(error) => { + println!( + "Could not check if the user is an administrator or not.\nError: {}", + error + ); + + return 1; + } + } + { println!("Need to have Administrator right to create the file"); return 1; } diff --git a/src/malware/service.rs b/src/malware/service.rs index 115a7d0..1a16020 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -6,7 +6,7 @@ // // Last update 20240224 -use crate::malware::tools::process_is_admin; +use crate::windows::users::is_admin; use clap::Parser; use std::{thread, time}; use windows::core::{Result as WindowsResult, PCWSTR}; @@ -116,7 +116,17 @@ impl BYOVD { pub fn run(&self) -> i32 { println!("Bring Your Own Vulnerable Driver"); - if process_is_admin() == false { + if match is_admin() { + Ok(is_admin) => is_admin, + Err(error) => { + println!( + "Could not check if the user is an administrator or not.\nError: {}", + error + ); + + return 1; + } + } { println!("Need to have Administrator right to create the service"); return 1; } diff --git a/src/malware/tools.rs b/src/malware/tools.rs deleted file mode 100644 index b0dbba6..0000000 --- a/src/malware/tools.rs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The WAG development team -// -// SPDX-License-Identifier: GPL-3.0-or-later - -use windows::Win32::UI::Shell::IsUserAnAdmin; - -pub fn process_is_admin() -> bool { - return unsafe { IsUserAnAdmin().into() }; -} diff --git a/src/windows.rs b/src/windows.rs new file mode 100644 index 0000000..913bd46 --- /dev/null +++ b/src/windows.rs @@ -0,0 +1 @@ +pub mod users; diff --git a/src/windows/users.rs b/src/windows/users.rs new file mode 100644 index 0000000..adaab43 --- /dev/null +++ b/src/windows/users.rs @@ -0,0 +1,40 @@ +use windows::{ + core::Error as WindowsError, + Win32::{ + Foundation::{BOOL, PSID}, + Security::{ + AllocateAndInitializeSid, CheckTokenMembership, FreeSid, SECURITY_NT_AUTHORITY, + }, + System::SystemServices::{DOMAIN_ALIAS_RID_ADMINS, SECURITY_BUILTIN_DOMAIN_RID}, + }, +}; + +pub fn is_admin() -> Result { + let is_admin: *mut BOOL = &mut BOOL::from(false); + let mut administrators_group: PSID = 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, + )?; + + let result: Result<(), WindowsError> = + CheckTokenMembership(None, administrators_group, is_admin); + + FreeSid(administrators_group); + + result?; + } + + return Ok(unsafe { (*is_admin).into() }); +} From 4a8e78e31fb1ae7bb73bccc79db95d45be70a7c3 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Sun, 30 Jun 2024 22:11:33 +0200 Subject: [PATCH 12/14] =?UTF-8?q?style:=20=F0=9F=92=84=20Add=20missing=20s?= =?UTF-8?q?px=20headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/windows.rs | 4 ++++ src/windows/users.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/windows.rs b/src/windows.rs index 913bd46..3ac4988 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The WAG development team +// +// SPDX-License-Identifier: GPL-3.0-or-later + pub mod users; diff --git a/src/windows/users.rs b/src/windows/users.rs index adaab43..328330a 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 The WAG development team +// +// SPDX-License-Identifier: GPL-3.0-or-later + use windows::{ core::Error as WindowsError, Win32::{ From b45f3c69e312b10262c5fa598be466e87cddacb3 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Mon, 1 Jul 2024 14:23:15 +0200 Subject: [PATCH 13/14] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Invert=20logic=20wh?= =?UTF-8?q?en=20calling=20is=5Fadmin=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We run code that needs administrator privileges when they don't have them and vice versa --- src/malware/file.rs | 2 +- src/malware/service.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/malware/file.rs b/src/malware/file.rs index 03049e1..113f2e8 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -89,7 +89,7 @@ fn create_file(fullpath: String, hex_data: Vec) -> bool { impl FileCreate { pub fn run(&self) -> i32 { if self.admin - && match is_admin() { + && !match is_admin() { Ok(is_admin) => is_admin, Err(error) => { println!( diff --git a/src/malware/service.rs b/src/malware/service.rs index 1a16020..3502593 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -116,7 +116,7 @@ impl BYOVD { pub fn run(&self) -> i32 { println!("Bring Your Own Vulnerable Driver"); - if match is_admin() { + if !match is_admin() { Ok(is_admin) => is_admin, Err(error) => { println!( From 6051126fcbd88acb9ee3521c297baa99d96d7e57 Mon Sep 17 00:00:00 2001 From: AntwortEinesLebens Date: Mon, 1 Jul 2024 14:29:31 +0200 Subject: [PATCH 14/14] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20Remove=20abbre?= =?UTF-8?q?viation=20from=20the=20function's=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/malware/file.rs | 4 ++-- src/malware/service.rs | 4 ++-- src/windows/users.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/malware/file.rs b/src/malware/file.rs index 113f2e8..add13e8 100644 --- a/src/malware/file.rs +++ b/src/malware/file.rs @@ -18,7 +18,7 @@ You can use `SET | more` or `Get-ChildItem Env:` to get the list */ -use crate::windows::users::is_admin; +use crate::windows::users::is_administrator; use base64::engine::{general_purpose, Engine}; use clap::Parser; use regex_generate::{Generator, DEFAULT_MAX_REPEAT}; @@ -89,7 +89,7 @@ fn create_file(fullpath: String, hex_data: Vec) -> bool { impl FileCreate { pub fn run(&self) -> i32 { if self.admin - && !match is_admin() { + && !match is_administrator() { Ok(is_admin) => is_admin, Err(error) => { println!( diff --git a/src/malware/service.rs b/src/malware/service.rs index 3502593..ca5e589 100644 --- a/src/malware/service.rs +++ b/src/malware/service.rs @@ -6,7 +6,7 @@ // // Last update 20240224 -use crate::windows::users::is_admin; +use crate::windows::users::is_administrator; use clap::Parser; use std::{thread, time}; use windows::core::{Result as WindowsResult, PCWSTR}; @@ -116,7 +116,7 @@ impl BYOVD { pub fn run(&self) -> i32 { println!("Bring Your Own Vulnerable Driver"); - if !match is_admin() { + if !match is_administrator() { Ok(is_admin) => is_admin, Err(error) => { println!( diff --git a/src/windows/users.rs b/src/windows/users.rs index 328330a..a8b149f 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -13,7 +13,7 @@ use windows::{ }, }; -pub fn is_admin() -> Result { +pub fn is_administrator() -> Result { let is_admin: *mut BOOL = &mut BOOL::from(false); let mut administrators_group: PSID = PSID::default();