Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -33,6 +34,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]
Expand Down
150 changes: 150 additions & 0 deletions src/modules/bruteforce.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//! Choose a password, hash it, and pretend to decrypt that hash
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;

use crate::args::AppConfig;
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 = &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;
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::<Vec<_>>();
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;
}
}

// 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;

let len = s.len();
let colors = colorgrad::sinebow().colors(len);
let mut ret = String::new();

// 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)
}
4 changes: 3 additions & 1 deletion src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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));
Expand Down