diff --git a/Cargo.lock b/Cargo.lock index 6050ac7..17411a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2463,6 +2463,29 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy-regex" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576c8060ecfdf2e56995cf3274b4f2d71fa5e4fa3607c1c0b63c10180ee58741" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9efb9e65d4503df81c615dc33ff07042a9408ac7f26b45abee25566f7fbfd12c" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "regex", + "syn 2.0.71", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2540,7 +2563,7 @@ dependencies = [ "kerberos_asn1", "kerberos_constants", "kerberos_crypto", - "lazy_static", + "lazy-regex", "ldap3", "log", "memory-stats", diff --git a/Cargo.toml b/Cargo.toml index fe7c1cd..b553577 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ clap = { version = "4.4.4", features = ["derive"] } clap_complete = "4.4.6" ctrlc = "3.4.1" indexmap = { version = "2.0.1", features = ["serde"] } -lazy_static = "1.4.0" log = "0.4.20" num_cpus = "1.16.0" rlimit = "0.10.1" @@ -92,6 +91,7 @@ nix = { version = "0.29.0", features = ["signal"] } strip-ansi-escapes = "0.2.0" actix-cors = "0.7.0" x509-parser = "0.16.0" +lazy-regex = "3.2.0" [dev-dependencies] tempfile = "3.8.0" diff --git a/src/api/handlers.rs b/src/api/handlers.rs index 9c629f4..62e846b 100644 --- a/src/api/handlers.rs +++ b/src/api/handlers.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::sync::LazyLock; use actix_web::get; use actix_web::post; @@ -7,20 +8,17 @@ use actix_web::HttpRequest; use actix_web::HttpResponse; use clap::CommandFactory; use clap::Parser; -use lazy_static::lazy_static; use serde::Serialize; use crate::api::SharedState; use crate::plugins; use crate::Options; -lazy_static! { - // nasty hack to check for plugin specific options - static ref OPTIONS_MAP: HashMap = { - let opts = serde_json::to_string(&Options::parse()).unwrap(); - serde_json::from_str(&opts).unwrap() - }; -} +// nasty hack to check for plugin specific options +static OPTIONS_MAP: LazyLock> = LazyLock::new(|| { + let opts = serde_json::to_string(&Options::parse()).unwrap(); + serde_json::from_str(&opts).unwrap() +}); #[derive(Serialize)] struct PluginOption { @@ -68,10 +66,7 @@ fn get_plugin_options(plugin_name: &str) -> HashMap { }; let opts = match OPTIONS_MAP.get(&opt_name) { - None => match OPTIONS_MAP.get(opt_root) { - None => None, - Some(v) => Some(v.clone()), - }, + None => OPTIONS_MAP.get(opt_root).cloned(), Some(v) => Some(v.clone()), }; @@ -81,7 +76,7 @@ fn get_plugin_options(plugin_name: &str) -> HashMap { opt_name.to_owned(), PluginOption { name: opt_name.to_owned(), - description: get_plugin_option_help(&opt_name), + description: get_plugin_option_help(opt_name), value: opt_val.clone(), }, ); @@ -106,10 +101,7 @@ pub async fn plugins_list(_: web::Data) -> HttpResponse { name: name.to_string(), description: plug.description().to_string(), strategy: plug.payload_strategy().to_string(), - override_payload: match plug.override_payload() { - Some(over) => Some(over.as_string()), - None => None, - }, + override_payload: plug.override_payload().map(|s| s.as_string()), options, }) } diff --git a/src/api/sessions.rs b/src/api/sessions.rs index 1da49b2..60ad970 100644 --- a/src/api/sessions.rs +++ b/src/api/sessions.rs @@ -8,15 +8,15 @@ use std::{ use actix_web::Result; use clap::Parser; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; use serde::Serialize; use tokio::{io::AsyncBufReadExt, sync::RwLock}; -lazy_static! { - static ref STATS_PARSER: Regex = Regex::new(r"(?m)^.+tasks=(\d+)\s+mem=(.+)\stargets=(\d+)\sattempts=(\d+)\sdone=(\d+)\s\((.+)%\)(\serrors=(\d+))?\sspeed=(.+) reqs/s").unwrap(); - static ref LOOT_PARSER: Regex = Regex::new(r"(?m)^.+\[(.+)\]\s\(([^)]+)\)(\s<(.+)>)?\s(.+)").unwrap(); -} +static STATS_PARSER: Lazy = lazy_regex!( + r"(?m)^.+tasks=(\d+)\s+mem=(.+)\stargets=(\d+)\sattempts=(\d+)\sdone=(\d+)\s\((.+)%\)(\serrors=(\d+))?\sspeed=(.+) reqs/s" +); +static LOOT_PARSER: Lazy = lazy_regex!(r"(?m)^.+\[(.+)\]\s\(([^)]+)\)(\s<(.+)>)?\s(.+)"); use crate::{session::Error, utils::parse_multiple_targets, Options}; diff --git a/src/creds/expression.rs b/src/creds/expression.rs index 85d31d0..ee57f0e 100644 --- a/src/creds/expression.rs +++ b/src/creds/expression.rs @@ -1,7 +1,7 @@ use std::fmt; use std::path::Path; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; use serde::Serialize; @@ -9,11 +9,9 @@ const DEFAULT_PERMUTATIONS_MIN_LEN: usize = 4; const DEFAULT_PERMUTATIONS_MAX_LEN: usize = 8; const DEFAULT_PERMUTATIONS_CHARSET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ !\"#$%&\'()*+,-./:;<=>?@[\\]^`{|}~"; -lazy_static! { - static ref PERMUTATIONS_PARSER: Regex = Regex::new(r"^#(\d+)-(\d+)(:.+)?$").unwrap(); - static ref RANGE_MIN_MAX_PARSER: Regex = Regex::new(r"^\[(\d+)-(\d+)\]$").unwrap(); - static ref RANGE_SET_PARSER: Regex = Regex::new(r"^\[(\d+(,\s*\d+)*)?\]$").unwrap(); -} +static PERMUTATIONS_PARSER: Lazy = lazy_regex!(r"^#(\d+)-(\d+)(:.+)?$"); +static RANGE_MIN_MAX_PARSER: Lazy = lazy_regex!(r"^\[(\d+)-(\d+)\]$"); +static RANGE_SET_PARSER: Lazy = lazy_regex!(r"^\[(\d+(,\s*\d+)*)?\]$"); #[derive(Clone, Debug, PartialEq, Serialize)] pub(crate) enum Expression { diff --git a/src/plugins/port_scanner/grabbers/http.rs b/src/plugins/port_scanner/grabbers/http.rs index 0f2f03f..8722713 100644 --- a/src/plugins/port_scanner/grabbers/http.rs +++ b/src/plugins/port_scanner/grabbers/http.rs @@ -4,16 +4,13 @@ use crate::{ plugins::port_scanner::options, utils::net::{upgrade_tcp_stream_to_tls, StreamLike}, }; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; use x509_parser::prelude::{FromDer, GeneralName, X509Certificate}; use super::Banner; -lazy_static! { - static ref HTML_TITLE_PARSER: Regex = - Regex::new(r"(?i)<\s*title\s*>([^<]+)<\s*/\s*title\s*>").unwrap(); -} +static HTML_TITLE_PARSER: Lazy = lazy_regex!(r"(?i)<\s*title\s*>([^<]+)<\s*/\s*title\s*>"); pub(crate) fn is_http_port(opts: &options::Options, port: u16) -> (bool, bool) { if opts.port_scanner_http == "*" { diff --git a/src/plugins/port_scanner/grabbers/mysql.rs b/src/plugins/port_scanner/grabbers/mysql.rs index fd13a54..6a3e357 100644 --- a/src/plugins/port_scanner/grabbers/mysql.rs +++ b/src/plugins/port_scanner/grabbers/mysql.rs @@ -1,15 +1,13 @@ use std::time::Duration; -use lazy_static::lazy_static; +use lazy_regex::{bytes_lazy_regex, Lazy}; use tokio::io::AsyncReadExt; use super::Banner; use crate::utils::net::StreamLike; -lazy_static! { - static ref BANNER_PARSER: regex::bytes::Regex = - regex::bytes::Regex::new(r"(?-u).{4}\x0a([^\x00]+)\x00.+").unwrap(); -} +static BANNER_PARSER: Lazy = + bytes_lazy_regex!(r"(?-u).{4}\x0a([^\x00]+)\x00.+"); pub(crate) fn is_mysql_port(port: u16) -> bool { port == 3306 diff --git a/src/plugins/samba/mod.rs b/src/plugins/samba/mod.rs index 574121a..8558e73 100644 --- a/src/plugins/samba/mod.rs +++ b/src/plugins/samba/mod.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::sync::LazyLock; use std::time::Duration; use async_trait::async_trait; @@ -10,14 +11,11 @@ use crate::session::{Error, Loot}; use crate::Plugin; use crate::{utils, Options}; -use lazy_static::lazy_static; - pub(crate) mod options; -lazy_static! { - static ref SHARE_CACHE: Mutex> = Mutex::new(HashMap::new()); - static ref PAVAO_LOCK: Mutex = tokio::sync::Mutex::new(true); -} +static SHARE_CACHE: LazyLock>> = + LazyLock::new(|| Mutex::new(HashMap::new())); +static PAVAO_LOCK: Mutex<()> = Mutex::const_new(()); super::manager::register_plugin! { "smb" => SMB::new() diff --git a/src/plugins/sql/mod.rs b/src/plugins/sql/mod.rs index ae31e34..d9803c6 100644 --- a/src/plugins/sql/mod.rs +++ b/src/plugins/sql/mod.rs @@ -1,8 +1,6 @@ -use std::collections::HashMap; use std::time::Duration; use async_trait::async_trait; -use lazy_static::lazy_static; use sqlx::pool::PoolOptions; use sqlx::{MySql, Postgres}; @@ -12,17 +10,6 @@ use crate::utils; use crate::Options; use crate::Plugin; -lazy_static! { - static ref DESCRIPTIONS: HashMap = { - HashMap::from([ - (Flavour::My, "MySQL password authentication."), - (Flavour::PG, "PostgreSQL password authentication."), - ]) - }; - static ref DEFAULT_PORTS: HashMap = - HashMap::from([(Flavour::My, 3306), (Flavour::PG, 5432),]); -} - super::manager::register_plugin! { "mysql" => SQL::new(Flavour::My), "pgsql" => SQL::new(Flavour::PG) @@ -34,6 +21,22 @@ pub(crate) enum Flavour { PG, } +impl Flavour { + fn description(&self) -> &'static str { + match self { + Self::My => "MySQL password authentication.", + Self::PG => "PostgreSQL password authentication.", + } + } + + fn default_port(&self) -> u16 { + match self { + Self::My => 3306, + Self::PG => 5432, + } + } +} + #[derive(Clone)] pub(crate) struct SQL { flavour: Flavour, @@ -42,7 +45,7 @@ pub(crate) struct SQL { impl SQL { pub fn new(flavour: Flavour) -> Self { - let port = *DEFAULT_PORTS.get(&flavour).unwrap(); + let port = flavour.default_port(); SQL { flavour, port } } @@ -82,7 +85,7 @@ impl SQL { #[async_trait] impl Plugin for SQL { fn description(&self) -> &'static str { - DESCRIPTIONS.get(&self.flavour).unwrap() + self.flavour.description() } fn setup(&mut self, _opts: &Options) -> Result<(), Error> { diff --git a/src/recipe/context.rs b/src/recipe/context.rs index 0ea8dd2..716ddd2 100644 --- a/src/recipe/context.rs +++ b/src/recipe/context.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; use crate::session::Error; @@ -8,9 +8,7 @@ use crate::session::Error; const CONTEXT_EXPRESSION_ERROR: &str = "context expression must be in the form of KEY1=VALUE1&KEY2=VALUE2&..."; -lazy_static! { - static ref USER_CONTEXT_PARSER: Regex = Regex::new(r"(?m)&?([^&]+)=([^&]+)").unwrap(); -} +static USER_CONTEXT_PARSER: Lazy = lazy_regex!(r"(?m)&?([^&]+)=([^&]+)"); #[derive(Default)] pub(crate) struct Context { diff --git a/src/recipe/mod.rs b/src/recipe/mod.rs index d6fa24b..7af19e9 100644 --- a/src/recipe/mod.rs +++ b/src/recipe/mod.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, path::PathBuf}; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -16,10 +16,7 @@ const ARG_EXPRESSION_ERROR: &str = const RESERVED_VAR_MAMES: [&str; 3] = ["username", "password", "payload"]; -lazy_static! { - static ref ARG_VALUE_PARSER: Regex = - Regex::new(r"(?m)\{\s*\$([\w\.]+)(\s+or\s+([^}]+))?\}").unwrap(); -} +static ARG_VALUE_PARSER: Lazy = lazy_regex!(r"(?m)\{\s*\$([\w\.]+)(\s+or\s+([^}]+))?\}"); #[derive(Serialize, Deserialize, Default, PartialEq, Debug)] pub(crate) struct Recipe { diff --git a/src/utils/target/multi.rs b/src/utils/target/multi.rs index d74d466..b3bafbc 100644 --- a/src/utils/target/multi.rs +++ b/src/utils/target/multi.rs @@ -6,13 +6,10 @@ use std::{ use crate::session::Error; use cidr_utils::cidr::IpCidr; -use lazy_static::lazy_static; +use lazy_regex::{lazy_regex, Lazy}; use regex::Regex; -lazy_static! { - static ref IPV4_RANGE_PARSER: Regex = - Regex::new(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+):?(\d+)?$").unwrap(); -} +static IPV4_RANGE_PARSER: Lazy = lazy_regex!(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+):?(\d+)?$"); fn parse_multiple_targets_atom(expression: &str) -> Result, Error> { if let Some(path) = expression.strip_prefix('@') {