From 3fccc5a8f88412b0bfe8a68a02fd38f221620abd Mon Sep 17 00:00:00 2001 From: QuickTus <24503963+quicktus@users.noreply.github.com> Date: Sat, 3 Sep 2022 20:44:32 +0200 Subject: [PATCH] initial commit --- .gitignore | 1 + Cargo.lock | 521 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 12 ++ src/main.rs | 337 +++++++++++++++++++++++++++++++++ 4 files changed, 871 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c46e767 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,521 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cpufeatures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" +dependencies = [ + "libc", +] + +[[package]] +name = "crossterm" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[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 = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" + +[[package]] +name = "lock_api" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha256" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e84a7f596c081d359de5e06a83877138bc3c4483591e1af1916e1472e6e146e" +dependencies = [ + "hex", + "sha2", +] + +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + +[[package]] +name = "steghunt" +version = "0.1.0" +dependencies = [ + "clap", + "crossterm", + "sha256", + "which", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1544103 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "steghunt" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "3.0", features = ["derive"] } +sha256 = { version = "1.0.3" } +crossterm = { version = "0.23" } +which = { version = "4.2.5" } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..43b26a6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,337 @@ +#![allow(unused)] +use std::{fs, path, io, time, thread}; +use std::io::{stdout, Write, BufReader, BufRead}; +use std::process::{Command, Stdio}; +use std::time::Duration; +use std::path::{Path, PathBuf}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::fs::File; +use std::io::prelude::*; +use clap::{AppSettings, ArgEnum, Parser}; +use crossterm::{ + ExecutableCommand, execute, Result, + cursor::{Hide, Show, RestorePosition, SavePosition} +}; +use crate::time::Instant; +use sha256::digest_file; +use which::which; + + +/// run stegseek on every file in a directory +#[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] +#[clap(name = "steghunt")] +#[clap(author = "@quicktus")] +#[clap(version = "1.0")] +#[clap(about = "Automated bulk detection and cracking of files hidden using steghide.", long_about = None)] +#[clap(propagate_version = true)] + +struct Cli { + /// Mode to use + #[clap(arg_enum, value_parser)] + mode: Mode, + + /// Path to the directory containing the images that will be processed + #[clap(short = 'i', long = "input", parse(from_os_str))] + in_path: std::path::PathBuf, + + /// Path to the directory where cracked files will be stored (does not need to exist) + #[clap(short = 'o', long = "output", parse(from_os_str))] + out_path: std::path::PathBuf, + + /// Recursively search subdirectories + #[clap(short = 'r', long = "recursive", parse(from_occurrences))] + recursive: u8, + + /// Skip duplicate images + #[clap(short = 'd', long = "dupeskip", parse(from_occurrences))] + dupe_skip: u8, + + /// Skip images below this size in Bytes + #[clap(short = 'm', long = "minsize", default_value_t = 1024)] + min_size: u32, + + /// Path to the wordlist to use for cracking + #[clap(short = 'w', long = "wordlist", parse(from_os_str))] + wordlist_path: Option, + + /// Don't print stats + #[clap(short = 'q', long = "quiet", parse(from_occurrences))] + quiet: u8, + +} + + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)] +#[allow(non_camel_case_types)] +enum Mode { + seed, + crack, + seedcrack, +} + + +fn main() { + let args = Cli::parse(); + + let wordlist = match args.wordlist_path { + Some(x) => x, + None => PathBuf::new(), + }; + let dupe_skip: bool = (args.dupe_skip == 1); + let recursive: bool = (args.recursive == 1); + let quiet: bool = (args.quiet == 1); + + if which("stegseek").is_err() { + println!("stegseek is not installed. exiting."); + return; + } + + if ! quiet { + execute!( + stdout(), + SavePosition, + Hide + ); + println!("\nInitializing ..."); + execute!( + stdout(), + RestorePosition + ); + } + + let mut hashes = Vec::new(); + let file_list = get_files(&args.in_path, &mut hashes, args.min_size, dupe_skip, recursive); + + let mut files_total: i32 = file_list.len().try_into().unwrap(); + let mut files_processed = 0; + let mut files_found = 0; + let mut files_cracked = 0; + + let mut log_file = File::create("steghunt_log").unwrap(); + if args.mode != Mode::seed { + fs::create_dir_all(args.out_path.clone()); + } + + if ! quiet { + print_stats(0, files_processed, files_total, files_found, files_cracked, args.mode); + } + + let from_time = Instant::now(); + + for steg_file in file_list { + + let str_path = steg_file.clone().into_os_string().into_string().unwrap(); + + if args.mode == Mode::seed { + let mut cmd = Command::new("stegseek") + .arg("--seed") + .arg("-a") + .arg("-q") + .arg("-sf").arg(steg_file) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = cmd.stderr.as_mut().unwrap(); + let stderr_reader = BufReader::new(stderr); + let stderr_lines = stderr_reader.lines(); + let mut err_no_seed = false; + + for line in stderr_lines { + if line.unwrap().contains("error:") { // Could not find a valid seed. + err_no_seed = true; + } + } + if !err_no_seed { + files_found += 1; + write!(log_file, "{}", str_path); + } + + cmd.wait(); + } + + else if args.mode == Mode::crack { + let mut cmd = Command::new("stegseek") + .arg("--crack") + .arg("-a") + .arg("-f") + .arg("-q") + .arg("-wl").arg(&wordlist) + .arg("-sf").arg(steg_file.clone()) + .arg("-xf").arg(&args.out_path.join(steg_file.file_name().unwrap().to_str().unwrap().to_owned() + ".out")) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = cmd.stderr.as_mut().unwrap(); + let stderr_reader = BufReader::new(stderr); + let stderr_lines = stderr_reader.lines(); + let mut err_no_crack = false; + + for line in stderr_lines { + if line.unwrap().contains("error:") { // Could not find a valid passphrase. + err_no_crack = true; + } + } + if !err_no_crack { + files_cracked += 1; + } + + cmd.wait(); + } + + else if args.mode == Mode::seedcrack { + let mut cmd = Command::new("stegseek") + .arg("--seed") + .arg("-a") + .arg("-q") + .arg("-sf").arg(steg_file.clone()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = cmd.stderr.as_mut().unwrap(); + let stderr_reader = BufReader::new(stderr); + let stderr_lines = stderr_reader.lines(); + let mut err_no_seed = false; + + for line in stderr_lines { + if line.unwrap().contains("error:") { + err_no_seed = true; + } + } + if !err_no_seed { + files_found += 1; + write!(log_file, "{}", str_path); + + // crack + //{ + let mut cmd = Command::new("stegseek") + .arg("--crack") + .arg("-a") + .arg("-f") + .arg("-q") + .arg("-wl").arg(&wordlist) + .arg("-sf").arg(steg_file.clone()) + .arg("-xf").arg(&args.out_path.join(steg_file.file_name().unwrap().to_str().unwrap().to_owned() + ".out")) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = cmd.stderr.as_mut().unwrap(); + let stderr_reader = BufReader::new(stderr); + let stderr_lines = stderr_reader.lines(); + let mut err_no_crack = false; + + for line in stderr_lines { + if line.unwrap().contains("error:") { // Could not find a valid passphrase. + err_no_crack = true; + } + } + if !err_no_crack { + files_cracked += 1; + } + //} + + } + + cmd.wait(); + } + + files_processed += 1; + let time_diff = from_time.elapsed().as_secs(); + + if ! quiet { + execute!( + stdout(), + RestorePosition + ); + print_stats(time_diff, files_processed, files_total, files_found, files_cracked, args.mode); + } + + } + + if ! quiet { + if files_found == 0 && files_cracked == 0 { + println!("Encryption can break your heart sometimes."); + } + execute!( + stdout(), + Show + ); + } + +} + +fn get_files(dir_name: &path::PathBuf, hashes: &mut Vec, min_size: u32, dupe_skip: bool, recursive: bool) -> Vec { + + let mut file_list: Vec = Vec::new(); + + for entry in fs::read_dir(dir_name).unwrap() { + let entry = entry.unwrap(); + let meta = entry.metadata().unwrap(); + let path = entry.path(); + + if meta.is_file() { + // check file size + if meta.len() >= min_size.into() { + // check magic number + let mut b = Vec::::with_capacity(4); + let f = match File::open(&path) { + Ok(x) => x, + Err(_) => continue, + }; + f.take(4).read_to_end(&mut b); + if (b[0] == 0x42 && b[1] == 0x4d) || // bitmap + (b[0] == 0xFF && b[1] == 0xD8) || // jpeg + b == vec![0x2e, 0x73, 0x6e, 0x64] || // au + b == vec![0x52, 0x49, 0x46, 0x46] { // wav + // skip duplicates + if dupe_skip == true { + let hash = digest_file(&path).unwrap(); + if ! hashes.contains(&hash) { + file_list.push(path); + (*hashes).push(hash); + } + } + else { + file_list.push(path); + } + } + } + } + + else if meta.is_dir() && recursive == true { + file_list.append(&mut get_files(&path, hashes, min_size, dupe_skip, recursive)); + } + } + return file_list; +} + +fn print_stats (t: u64, fp: i32, ft: i32, ff: i32, fc: i32, mode: Mode) { + let divider = "-".repeat(42); + + let h = t / 3600; + let m = t % 3600 / 60; + let s = t % 60; + + println!("\n{}", divider); + println!("files processed: {} out of {} ({:.1}%)", fp, ft, (100 * fp / ft)); + println!("duration: {:02}:{:02}:{:02}", h, m, s); + + if mode == Mode::seed || mode == Mode::seedcrack { + println!("(possible) stegfiles detected: {}", ff); + } + + if mode == Mode::crack || mode == Mode::seedcrack { + println!("stegfiles cracked: {}", fc); + } + + println!("{}\n", divider); + io::stdout().flush().unwrap(); +} \ No newline at end of file