From 0c544409f42da55a1d1b70005453799157bfac20 Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Thu, 6 Oct 2022 09:52:46 +0900 Subject: [PATCH 1/5] Reimplement bruteforce module --- src/data.rs | 39 +++++++++++ src/modules/bruteforce.rs | 139 ++++++++++++++++++++++++++++++++++++++ src/modules/mod.rs | 4 +- 3 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 src/modules/bruteforce.rs diff --git a/src/data.rs b/src/data.rs index 74693c419..c09f9dee2 100644 --- a/src/data.rs +++ b/src/data.rs @@ -49,3 +49,42 @@ pub static EXTENSIONS_LIST: &[&str] = &[ pub static COMPRESSION_FORMATS_LIST: &[&str] = &["gzip", "bzip2", "lzma", "xz", "lzop", "lz4", "zstd"]; + +pub static PASSWORDS_AND_HASHES_LIST: &[(&str, &str)] = &[ + ( + "password", + "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", + ), + ( + "welcome", + "280d44ab1e9f79b5cce2dd4f58f5fe91f0fbacdac9f7447dffc318ceb79f2d02", + ), + ( + "qwerty", + "65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5", + ), + ( + "monkey", + "000c285457fc971f862a79b786476c78812c8897063c6fa9c045f579a3b2d63f", + ), + ( + "jesus", + "a54e71f0e17f5aaf7946e66ab42cf3b1fd4e61d60581736c9f0eb1c3f794eb7c", + ), + ( + "love", + "686f746a95b6f836d7d70567c302c3f9ebb5ee0def3d1220ee9d4e9f34f5e131", + ), + ( + "money", + "8d2ac8b58ead9744d77286de9b0bcb7a894f238c3149fc9f3b1e3caff36330fe", + ), + ( + "freedom", + "13b1f7ec5beaefc781e43a3b344371cd49923a8a05edd71844b92f56f6a08d38", + ), + ( + "ninja", + "54482595177116e6103b076dbf30648e5d0537dd1ed9cf5ae4562fa8a700d47b", + ), +]; diff --git a/src/modules/bruteforce.rs b/src/modules/bruteforce.rs new file mode 100644 index 000000000..eb859380e --- /dev/null +++ b/src/modules/bruteforce.rs @@ -0,0 +1,139 @@ +//! Choose a password, hash it, and pretend to decrypt that hash +use std::str::from_utf8; + +use async_trait::async_trait; +use rand::seq::SliceRandom; +use yansi::Paint; + +use crate::args::AppConfig; +use crate::data::PASSWORDS_AND_HASHES_LIST; +use crate::generators::gen_hex_string; +use crate::io::{csleep, newline, print}; +use crate::modules::Module; + +pub struct Bruteforce; + +#[async_trait(?Send)] +impl Module for Bruteforce { + fn name(&self) -> &'static str { + "bruteforce" + } + fn signature(&self) -> String { + "./bruteforce.sh".to_string() + } + async fn run(&self, app_config: &AppConfig) { + let mut rng = rand::thread_rng(); + let (password, hash_str) = *PASSWORDS_AND_HASHES_LIST.choose(&mut rng).unwrap(); + + print(format!("SHA256 value: {hash_str}",)).await; + newline().await; + csleep(500).await; + + // Wait for "extraction" with a rainbow progress bar + { + let message = "Extracting Rainbow Table"; + let width = 30; + let millis_wait = 2500; + let fill_char = "="; + + let mut spinner_statuses = ["|", "/", "-", "\\"].iter().cycle(); + + for i in 0..width { + let spinner = if i == (width - 1) { + // Make sure to get a fill_char at the end of our cycle when done. + fill_char + } else { + spinner_statuses.next().unwrap() + }; + + let progress = fill_char.repeat(i); + let spaces = " ".repeat(width - i - 1); + let progress_content = rainbow(&format!("{progress}{spinner}{spaces}")); + + print(format!("\r{message} [{progress_content}]",)).await; + + csleep((millis_wait / width) as u64).await; + + if app_config.should_exit() { + return; + } + } + + newline().await; + } + + print("Begin matching").await; + newline().await; + csleep(500).await; + + // Show the progress of "decryption" + { + let mut progress: usize = 0; + + let hash_bytes = hash_str.bytes().collect::>(); + let l = hash_bytes.len(); + + while progress < l { + let guesses: Vec<_> = gen_hex_string(&mut rng, l as u64).bytes().collect(); + + while progress < l && guesses[progress] == hash_bytes[progress] { + progress += 1; + } + + let (done, undone) = if progress < l { + let done = from_utf8(&hash_bytes[0..progress]).unwrap(); + let undone = from_utf8(&guesses[progress..]).unwrap(); + (done, undone) + } else { + (hash_str, "") + }; + + let (done, undone) = (Paint::green(done), Paint::red(undone)); + + print(format!("\r :: {done}{undone} ::")).await; + csleep(10).await; + + if app_config.should_exit() { + return; + } + } + newline().await; + } + + print(format!("+ Match found -- the password is \"{password}\"")).await; + newline().await; + } +} + +// color a string rainbow +fn rainbow(s: &str) -> String { + use std::fmt::Write; + + // Need to split chars by bytes + debug_assert!(s.is_ascii()); + + static RAINBOW_COLORS: &[yansi::Color] = &[ + yansi::Color::Red, + yansi::Color::Yellow, + yansi::Color::Green, + yansi::Color::Cyan, + yansi::Color::Blue, + yansi::Color::Magenta, + ]; + + let len = s.len(); + let colors = RAINBOW_COLORS.len(); + + let bytes: Vec<_> = s.bytes().collect(); + let mut ret = String::new(); + + // split the string and apply colors + for (i, c) in RAINBOW_COLORS.iter().enumerate() { + let start = i * len / colors; + let end = (i + 1) * len / colors; + let s = from_utf8(&bytes[start..end]).unwrap(); + write!(ret, "{}", Paint::new(s).fg(*c)).unwrap(); + } + + ret +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index f6f79e645..664e710f7 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -1,6 +1,7 @@ pub mod ansible; pub mod bootlog; pub mod botnet; +pub mod bruteforce; pub mod cargo; pub mod cc; pub mod composer; @@ -34,12 +35,13 @@ lazy_static::lazy_static! { all_modules.insert("ansible", Box::new(ansible::Ansible)); all_modules.insert("bootlog", Box::new(bootlog::Bootlog)); all_modules.insert("botnet", Box::new(botnet::Botnet)); + all_modules.insert("bruteforce", Box::new(bruteforce::Bruteforce)); all_modules.insert("cargo", Box::new(cargo::Cargo)); all_modules.insert("cc", Box::new(cc::Cc)); all_modules.insert("composer", Box::new(composer::Composer)); all_modules.insert("cryptomining", Box::new(cryptomining::Crytomining)); - all_modules.insert("docker_image_rm", Box::new(docker_image_rm::DockerImageRm)); all_modules.insert("docker_build", Box::new(docker_build::DockerBuild)); + all_modules.insert("docker_image_rm", Box::new(docker_image_rm::DockerImageRm)); all_modules.insert("download", Box::new(download::Download)); all_modules.insert("julia", Box::new(julia::Julia)); all_modules.insert("kernel_compile", Box::new(kernel_compile::KernelCompile)); From b3d8fcb1f18744081d56aebbb2c6c8b35da065b5 Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Fri, 7 Oct 2022 11:59:17 +0900 Subject: [PATCH 2/5] Insert empty lines between methods Co-authored-by: Sven-Hendrik Haase --- src/modules/bruteforce.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/bruteforce.rs b/src/modules/bruteforce.rs index eb859380e..cee96d671 100644 --- a/src/modules/bruteforce.rs +++ b/src/modules/bruteforce.rs @@ -18,9 +18,11 @@ impl Module for Bruteforce { fn name(&self) -> &'static str { "bruteforce" } + fn signature(&self) -> String { "./bruteforce.sh".to_string() } + async fn run(&self, app_config: &AppConfig) { let mut rng = rand::thread_rng(); let (password, hash_str) = *PASSWORDS_AND_HASHES_LIST.choose(&mut rng).unwrap(); From 849dd659234bd4df0b72816cc78b9de62cb4be1a Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Fri, 7 Oct 2022 18:35:56 +0900 Subject: [PATCH 3/5] Get password from faker and compute the hash on runtime --- Cargo.lock | 66 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/data.rs | 39 ----------------------- src/modules/bruteforce.rs | 19 ++++++++--- 4 files changed, 81 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58ff78672..329cbfee9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,6 +178,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + [[package]] name = "blocking" version = "1.2.0" @@ -295,6 +304,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam-utils" version = "0.8.11" @@ -305,6 +323,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "ctor" version = "0.1.23" @@ -325,6 +353,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "digest" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "errno" version = "0.2.8" @@ -438,6 +476,7 @@ dependencies = [ "rand", "rand_distr", "regex", + "sha2", "terminal_size", "url", "wasm-bindgen", @@ -446,6 +485,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.7" @@ -824,6 +873,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "slab" version = "0.4.7" @@ -903,6 +963,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-bidi" version = "0.3.8" diff --git a/Cargo.toml b/Cargo.toml index 29e05df92..a42e318b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ progress_string = "0.2" rand = "0.8" rand_distr = "0.4" regex = "1.5" +sha2 = "0.10.6" yansi = "0.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/src/data.rs b/src/data.rs index c09f9dee2..74693c419 100644 --- a/src/data.rs +++ b/src/data.rs @@ -49,42 +49,3 @@ pub static EXTENSIONS_LIST: &[&str] = &[ pub static COMPRESSION_FORMATS_LIST: &[&str] = &["gzip", "bzip2", "lzma", "xz", "lzop", "lz4", "zstd"]; - -pub static PASSWORDS_AND_HASHES_LIST: &[(&str, &str)] = &[ - ( - "password", - "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", - ), - ( - "welcome", - "280d44ab1e9f79b5cce2dd4f58f5fe91f0fbacdac9f7447dffc318ceb79f2d02", - ), - ( - "qwerty", - "65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5", - ), - ( - "monkey", - "000c285457fc971f862a79b786476c78812c8897063c6fa9c045f579a3b2d63f", - ), - ( - "jesus", - "a54e71f0e17f5aaf7946e66ab42cf3b1fd4e61d60581736c9f0eb1c3f794eb7c", - ), - ( - "love", - "686f746a95b6f836d7d70567c302c3f9ebb5ee0def3d1220ee9d4e9f34f5e131", - ), - ( - "money", - "8d2ac8b58ead9744d77286de9b0bcb7a894f238c3149fc9f3b1e3caff36330fe", - ), - ( - "freedom", - "13b1f7ec5beaefc781e43a3b344371cd49923a8a05edd71844b92f56f6a08d38", - ), - ( - "ninja", - "54482595177116e6103b076dbf30648e5d0537dd1ed9cf5ae4562fa8a700d47b", - ), -]; diff --git a/src/modules/bruteforce.rs b/src/modules/bruteforce.rs index cee96d671..3fefdcadd 100644 --- a/src/modules/bruteforce.rs +++ b/src/modules/bruteforce.rs @@ -2,11 +2,11 @@ use std::str::from_utf8; use async_trait::async_trait; -use rand::seq::SliceRandom; +use fake::{faker::name::raw::FirstName, locales::EN, Fake}; +use sha2::{Digest, Sha256}; use yansi::Paint; use crate::args::AppConfig; -use crate::data::PASSWORDS_AND_HASHES_LIST; use crate::generators::gen_hex_string; use crate::io::{csleep, newline, print}; use crate::modules::Module; @@ -18,14 +18,15 @@ impl Module for Bruteforce { fn name(&self) -> &'static str { "bruteforce" } - + fn signature(&self) -> String { "./bruteforce.sh".to_string() } - + async fn run(&self, app_config: &AppConfig) { let mut rng = rand::thread_rng(); - let (password, hash_str) = *PASSWORDS_AND_HASHES_LIST.choose(&mut rng).unwrap(); + let password = &FirstName(EN).fake::<&str>().to_lowercase(); + let hash_str: &str = &sha256(password); print(format!("SHA256 value: {hash_str}",)).await; newline().await; @@ -107,6 +108,14 @@ impl Module for Bruteforce { } } +// get the SHA256 string for a str +fn sha256(s: &str) -> String { + let mut hasher = Sha256::new(); + hasher.update(&s); + let result_bytes = hasher.finalize(); + format!("{:x}", result_bytes) +} + // color a string rainbow fn rainbow(s: &str) -> String { use std::fmt::Write; From addb76cd4c0dc9e410fded48891b390a248cc61f Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Fri, 7 Oct 2022 18:41:27 +0900 Subject: [PATCH 4/5] Append 2-digit number to passwords --- src/modules/bruteforce.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/bruteforce.rs b/src/modules/bruteforce.rs index 3fefdcadd..7efc9aa47 100644 --- a/src/modules/bruteforce.rs +++ b/src/modules/bruteforce.rs @@ -3,6 +3,7 @@ use std::str::from_utf8; use async_trait::async_trait; use fake::{faker::name::raw::FirstName, locales::EN, Fake}; +use rand::Rng; use sha2::{Digest, Sha256}; use yansi::Paint; @@ -25,7 +26,11 @@ impl Module for Bruteforce { async fn run(&self, app_config: &AppConfig) { let mut rng = rand::thread_rng(); - let password = &FirstName(EN).fake::<&str>().to_lowercase(); + let password = &format!( + "{}{:02}", + FirstName(EN).fake::<&str>().to_lowercase(), + rng.gen_range(0..99) + ); let hash_str: &str = &sha256(password); print(format!("SHA256 value: {hash_str}",)).await; From 098bfd16a14a1f5489d94b30ec380493d1dfc5d7 Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Sat, 8 Oct 2022 12:41:06 +0900 Subject: [PATCH 5/5] Use colorgrad to generate rainbow colors --- Cargo.lock | 67 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/modules/bruteforce.rs | 41 +++++++++++------------- 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 329cbfee9..011875050 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,6 +279,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "colorgrad" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a2d16665305bc62a863baa4005b1074f77e7f2f65e0805734b4df6b854cd66e" +dependencies = [ + "csscolorparser", +] + [[package]] name = "concurrent-queue" version = "1.2.4" @@ -333,6 +342,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "phf", +] + [[package]] name = "ctor" version = "0.1.23" @@ -463,6 +481,7 @@ dependencies = [ "async-trait", "chrono", "clap", + "colorgrad", "console_error_panic_hook", "ctrlc", "fake", @@ -722,6 +741,48 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "phf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -884,6 +945,12 @@ dependencies = [ "digest", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slab" version = "0.4.7" diff --git a/Cargo.toml b/Cargo.toml index a42e318b3..26cb254eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ anyhow = "1" async-std = { version = "1", features = ["attributes"] } async-trait = "0.1" chrono = { version = "0.4", features = ["clock", "wasmbind"], default-features = false } +colorgrad = "0.6.1" fake = { version = "2.4", features = ["chrono"] } getrandom = { version = "0.2", features = ["js"] } humansize = "2" diff --git a/src/modules/bruteforce.rs b/src/modules/bruteforce.rs index 7efc9aa47..3d77d92f7 100644 --- a/src/modules/bruteforce.rs +++ b/src/modules/bruteforce.rs @@ -113,7 +113,7 @@ impl Module for Bruteforce { } } -// get the SHA256 string for a str +// Get the SHA256 string for a str fn sha256(s: &str) -> String { let mut hasher = Sha256::new(); hasher.update(&s); @@ -121,35 +121,30 @@ fn sha256(s: &str) -> String { format!("{:x}", result_bytes) } -// color a string rainbow +// Color a string rainbow fn rainbow(s: &str) -> String { use std::fmt::Write; - // Need to split chars by bytes - debug_assert!(s.is_ascii()); - - static RAINBOW_COLORS: &[yansi::Color] = &[ - yansi::Color::Red, - yansi::Color::Yellow, - yansi::Color::Green, - yansi::Color::Cyan, - yansi::Color::Blue, - yansi::Color::Magenta, - ]; - let len = s.len(); - let colors = RAINBOW_COLORS.len(); - - let bytes: Vec<_> = s.bytes().collect(); + let colors = colorgrad::sinebow().colors(len); let mut ret = String::new(); - // split the string and apply colors - for (i, c) in RAINBOW_COLORS.iter().enumerate() { - let start = i * len / colors; - let end = (i + 1) * len / colors; - let s = from_utf8(&bytes[start..end]).unwrap(); - write!(ret, "{}", Paint::new(s).fg(*c)).unwrap(); + // apply colors to each characters + for (color, ch) in colors.into_iter().zip(s.chars()) { + let approx = approx_color(color); + write!(ret, "{}", Paint::new(ch).fg(approx)).unwrap(); } ret } + +// Approximate RGB with ANSI 216 colors +fn approx_color(c: colorgrad::Color) -> yansi::Color { + // 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) + + let r = (c.r * 5.).round() as u8; + let g = (c.g * 5.).round() as u8; + let b = (c.b * 5.).round() as u8; + + yansi::Color::Fixed(16 + 36 * r + 6 * g + b) +}