Skip to content

Commit

Permalink
Merge pull request #26 from danielpclark/reporting
Browse files Browse the repository at this point in the history
Reporting
  • Loading branch information
danielpclark committed Dec 19, 2017
2 parents ac3cefe + 7d06855 commit d95a761
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 23 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "abrute"
version = "0.1.6"
version = "0.1.7"
authors = ["Daniel P. Clark <[email protected]>"]
description = "AESCrypt Brute force attempter."
documentation = "http:https://danielpclark.github.io/abrute/index.html"
Expand All @@ -18,3 +18,6 @@ clap = "~2.26"
digits = "~1.1.0"
rayon = "~0.8.2"
num_cpus = "~1.7"
serde = "1.0.24"
serde_json = "1.0.8"
tiny_http = "~0.5"
64 changes: 54 additions & 10 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
// http:https://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::sync::Mutex;
use digits::Digits;
use std::io::{self, Write, Read};
use std::io::{Read};
use std::process::{Command, Output};
use rayon::prelude::*;
use super::result::Error;
Expand All @@ -17,12 +16,22 @@ use resume::{ResumeKey,ResumeFile};
use self::tempdir::TempDir;
use std::{fs,path,env};
use std::time::{Duration, Instant};
use ::WorkLoad;
use ::{WorkLoad,ITERATIONS,SUCCESS};
use std::sync::{Arc, Mutex};
use reporter::CliReporter;
use std::sync::atomic::Ordering;

fn has_five_minutes_passed(t: Instant) -> bool {
Instant::now().duration_since(t) > Duration::new(300,0)
}

fn update_report_data(five_min_iters: usize, last: &Digits, fmp: &Arc<Mutex<(usize, String)>>) {
let mut lock = fmp.try_lock();
if let Ok(ref mut mutex) = lock {
**mutex = (five_min_iters, last.to_s());
}
}

fn chunk_sequence(d: &mut Digits, adj: Option<String>, chunk: usize, step: Option<usize>) -> Vec<String> {
let qty: usize = num_cpus::get() * chunk;
let mut counter = 0;
Expand Down Expand Up @@ -71,9 +80,8 @@ fn unzip_command(value: &str, target: &str) -> Output {
unwrap()
}

fn progress_report<'a>(sequencer: &Digits) {
print!("{}..", sequencer.to_s()); // Verbose
io::stdout().flush().unwrap();
fn progress_report<'a>(reporter: &CliReporter, sequencer: &Digits) {
reporter.report(sequencer);
}

fn has_reached_end<'a>(sequencer: &Digits, max: usize) -> Result<(), Error> {
Expand All @@ -85,11 +93,22 @@ fn has_reached_end<'a>(sequencer: &Digits, max: usize) -> Result<(), Error> {
}

pub fn aescrypt_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
let WorkLoad(characters, max, mut sequencer, target, adj, chunk_size, cluster_step) = work_load;
let WorkLoad(
characters,
max,
mut sequencer,
target,
adj,
chunk_size,
cluster_step,
reporter_handler,
cli_reporter
) = work_load;
let mut time_keeper = Instant::now();
let mut five_minute_iterations: usize = 0;
loop {
has_reached_end(&sequencer, max)?;
progress_report(&sequencer);
progress_report(&cli_reporter, &sequencer);

let chunk = chunk_sequence(
&mut sequencer,
Expand All @@ -103,9 +122,12 @@ pub fn aescrypt_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
{
let output = aes_command(&value, &target);

ITERATIONS.fetch_add(1, Ordering::SeqCst);

if output.status.success() {
let mut code_mutex = code.lock().unwrap();
code_mutex.push(value.clone().to_string());
SUCCESS.store(true, Ordering::SeqCst);
println!("Success!\nPassword is: {}", value);
}
}
Expand All @@ -125,6 +147,8 @@ pub fn aescrypt_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
}

if has_five_minutes_passed(time_keeper) {
let global_iterations = ITERATIONS.load(Ordering::SeqCst);
five_minute_iterations = global_iterations - five_minute_iterations;
ResumeFile::save(
ResumeKey::new(
characters.clone(),
Expand All @@ -134,6 +158,8 @@ pub fn aescrypt_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
)
);

update_report_data(five_minute_iterations, &sequencer, &reporter_handler.five_min_progress);
five_minute_iterations = global_iterations;
time_keeper = Instant::now();
}
}
Expand All @@ -158,8 +184,19 @@ fn any_file_contents(dir: &TempDir, omit: &str) -> bool {
}

pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
let WorkLoad(characters, max, mut sequencer, target, adj, chunk_size, cluster_step) = work_load;
let WorkLoad(
characters,
max,
mut sequencer,
target,
adj,
chunk_size,
cluster_step,
reporter_handler,
cli_reporter
) = work_load;
let mut time_keeper = Instant::now();
let mut five_minute_iterations: usize = 0;
if let Ok(dir) = TempDir::new("abrute") {
let cwd = env::current_dir().unwrap();
let working = path::Path::new(&dir.path().as_os_str()).join(&target);
Expand All @@ -169,7 +206,7 @@ pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {

loop {
has_reached_end(&sequencer, max)?;
progress_report(&sequencer);
progress_report(&cli_reporter, &sequencer);

let chunk = chunk_sequence(
&mut sequencer,
Expand All @@ -183,6 +220,8 @@ pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
{
let output = unzip_command(&value, &target);

ITERATIONS.fetch_add(1, Ordering::SeqCst);

if output.status.success() {
if any_file_contents(&dir, &target) {
fs::read_dir(&dir).
Expand All @@ -198,6 +237,7 @@ pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
});
let mut code_mutex = code.lock().unwrap();
code_mutex.push(Ok(()));
SUCCESS.store(true, Ordering::SeqCst);
println!("Success!\nPassword is: {}", value);
}
}
Expand All @@ -212,6 +252,8 @@ pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {


if has_five_minutes_passed(time_keeper) {
let global_iterations = ITERATIONS.load(Ordering::SeqCst);
five_minute_iterations = global_iterations - five_minute_iterations;
ResumeFile::save(
ResumeKey::new(
characters.clone(),
Expand All @@ -221,6 +263,8 @@ pub fn unzip_core_loop<'a>(work_load: WorkLoad) -> Result<(), Error> {
)
);

update_report_data(five_minute_iterations, &sequencer, &reporter_handler.five_min_progress);
five_minute_iterations = global_iterations;
time_keeper = Instant::now();
}
}
Expand Down
88 changes: 81 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// copied, modified, or distributed except according to those terms.

#![feature(try_from)]
#![feature(libc)]
extern crate digits;
extern crate rayon;
use digits::Digits;
Expand All @@ -14,6 +15,7 @@ mod resume;
mod result;
use result::Error;
use std::error::Error as StdError;
mod reporter;
mod process_input;
use process_input::*;
mod validators;
Expand All @@ -23,6 +25,22 @@ use core::*;
#[macro_use]
extern crate clap;
use clap::{Arg, App};
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT};
extern crate serde_json;
use std::time::SystemTime;
use std::sync::{Arc, Mutex};
extern crate num_cpus;
extern crate tiny_http;
mod web;
use web::ReportData;
use std::thread;
use reporter::CliReporter;
extern crate libc;
use libc::pthread_cancel;
use std::os::unix::thread::{RawPthread,JoinHandleExt};

static ITERATIONS: AtomicUsize = ATOMIC_USIZE_INIT;
static SUCCESS: AtomicBool = ATOMIC_BOOL_INIT;

pub struct WorkLoad(
pub String, // characters: String,
Expand All @@ -31,7 +49,9 @@ pub struct WorkLoad(
pub String, // target: String,
pub Option<String>, // adj: Option<String>
pub Option<String>, // chunk: Option<String>
pub Option<usize> // cluster_step: Option<(usize,usize)>
pub Option<usize>, // cluster_step: Option<(usize,usize)>
pub ReportData, // cloned ReportData for web JSON results and other reporters
pub CliReporter, // cli Reporter chosen
);

fn run_app() -> Result<(), Error> {
Expand Down Expand Up @@ -72,6 +92,11 @@ fn run_app() -> Result<(), Error> {
long("cluster").
takes_value(true)
).
arg(Arg::with_name("reporter").
short("r").
long("reporter").
takes_value(true)
).
arg(Arg::with_name("TARGET").
required(true).
last(true)
Expand Down Expand Up @@ -99,6 +124,7 @@ fn run_app() -> Result<(), Error> {
--cluster Takes an offset and cluster size such as 1:4 for the
first system in a cluster of 4. Helps different systems
split the workload without trying the same passwords.
-r, --reporter Use `spinner` for different command line reporter.
<TARGET> Target file to decrypt. The target must be preceeded
by a double dash: -- target.aes
-h, --help Prints help information.
Expand Down Expand Up @@ -142,6 +168,18 @@ USE OF THIS BINARY FALLS UNDER THE MIT LICENSE (c) 2017").
sequencer.mut_add(additive);
}

let reporter =
verify_reporter_name(
matches.
value_of("reporter").
unwrap_or("ticker").
to_string()
);

// JSON URI
println!("JSON endpoint available on Port 3838");
// END JSON URI

// Begin Resume Feature
let starting = sequencer.to_s();
use ::resume::{ResumeKey,ResumeFile};
Expand All @@ -158,27 +196,63 @@ USE OF THIS BINARY FALLS UNDER THE MIT LICENSE (c) 2017").
}
// End Resume Feature

// DATA for JSON web end point
let reporter_handler = ReportData {
cores: num_cpus::get() as u8,
chunk: chunk.clone().unwrap_or("").parse::<usize>().unwrap_or(32),
cluster: {
if matches.is_present("cluster") {
Some(derive_cluster(matches.value_of("cluster").unwrap()).ok().unwrap())
} else { None }
},
character_set: resume_key_chars.clone(),
start_time: SystemTime::now(),
start_at: sequencer.to_s(),
adjacent_limit: adjacent.map(|ref s| u8::from_str_radix(&s,10).ok().unwrap()),
five_min_progress: Arc::new(Mutex::new((0, "".to_string()))),
};

let web_reporter = reporter_handler.clone();

let web_runner: thread::JoinHandle<_> = thread::spawn(move || {
web::host_data(&web_reporter)
});

let work_load = WorkLoad(
resume_key_chars,
max,
sequencer,
target.to_string(),
adjacent.map(str::to_string),
chunk.map(str::to_string),
cluster_step
cluster_step,
reporter_handler,
reporter
);

if matches.is_present("zip") {
return unzip_core_loop(work_load);
}
let mtchs = matches.clone();

let crypt_runner = thread::spawn(move || {
if mtchs.is_present("zip") {
unzip_core_loop(work_load)
} else {
aescrypt_core_loop(work_load)
}
});

aescrypt_core_loop(work_load)
let wr: RawPthread = web_runner.as_pthread_t();
let cr = crypt_runner.join().unwrap();
unsafe { pthread_cancel(wr); }
cr
}

fn main() {
::std::process::exit(
match run_app() {
Ok(_) => 0,
Ok(_) => {
println!("Exiting…");
0
},
Err(err) => {
writeln!(
io::stderr(),
Expand Down
9 changes: 9 additions & 0 deletions src/process_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

use digits::BaseCustom;
use super::result::Error;
use reporter::CliReporter;

pub fn verify_reporter_name(rn: String) -> CliReporter {
match &rn[..] {
"spinner" => CliReporter::Spinner,
"ticker" => CliReporter::TickerTape,
_ => CliReporter::TickerTape,
}
}

pub fn derive_min_max(range: &str) -> Result<(usize, usize), Error> {
let rvals = range.split(':').collect::<Vec<&str>>();
Expand Down
19 changes: 19 additions & 0 deletions src/reporter/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pub mod ticker_tape;
pub mod spinner;
use ::Digits;

#[derive(Debug)]
pub enum CliReporter {
TickerTape,
Spinner,
}

impl CliReporter {
#[inline]
pub fn report(&self, data: &Digits) {
match *self {
ref _thingy @ CliReporter::TickerTape => ticker_tape::report(data),
ref _thingy @ CliReporter::Spinner => spinner::report(data),
}
}
}
16 changes: 16 additions & 0 deletions src/reporter/spinner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use ::{Digits,ITERATIONS};
use std::sync::atomic::Ordering;
use std::io::{self, Write};

const SPINNER: [char; 10] = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];

pub fn report(data: &Digits) {
let global_iterations = ITERATIONS.load(Ordering::SeqCst);
print!(
"\x1b[1000D {} Iterations: {} String: {}",
SPINNER[global_iterations % 10],
global_iterations,
data.to_s()
);
io::stdout().flush().unwrap();
}
Loading

0 comments on commit d95a761

Please sign in to comment.