2 Commits
1.1 ... 1.2.1

Author SHA1 Message Date
pyro57000
ec23b722f1 added some basic filtering 2025-10-20 13:10:55 -05:00
pyro57000
c97e05008d added ascii art 2025-10-17 10:51:07 -05:00
4 changed files with 164 additions and 42 deletions

2
Cargo.lock generated
View File

@@ -257,7 +257,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "snaferrous"
version = "0.1.0"
version = "1.2.0"
dependencies = [
"clap",
"colored",

View File

@@ -1,6 +1,6 @@
[package]
name = "snaferrous"
version = "0.1.0"
version = "1.2.0"
edition = "2024"
[dependencies]

View File

@@ -22,6 +22,12 @@ Options:
-t, --targets <TARGETS> specific targets. should be comma separated.
-f, --filter_targets <targets> specific targets that should be ingored. Comma separated.
-l, --local scan the current hot's file system (defaults to false)
-d --disable_network disable network file discovery
-v, --verbose echo all found files to the console, regardless of keyword matching. (all files will still be saved to the log file)
-h, --help Print help (see more with '--help')

View File

@@ -23,7 +23,7 @@ struct Args{
#[arg(short, long, help = "path to save output file Defaults to not saving output.")]
outfile: Option<PathBuf>,
#[arg(short, long, help = "number of threads to use, default to 10. \nNote thre thread count will be doubled, one set for share finder tasks, and one set for file and infor finding tasks.")]
#[arg(short, long, help = "number of threads to use, default to 10. \\nNote thre thread count will be doubled, one set for share finder tasks, and one set for file and infor finding tasks.")]
threads: Option<usize>,
#[arg(short, long, help = "specific targets. should be comma separated.")]
@@ -42,8 +42,17 @@ struct Args{
#[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>,
#[arg(short, long, help = "specific targets that should be ignored. comma separated.")]
filter_targets: Option<String>,
#[arg(short, long, help = "echo all found files to the console, regardless of keyword matching. (all files will still be saved to the log file)")]
verbose: bool,
#[arg(short, long, help = "scan only the current host's files")]
local: bool,
#[arg(short, long, help = "disable network discovery")]
diable_network: bool
}
#[derive(Clone)]
@@ -151,6 +160,8 @@ async fn task_handler(id: usize, current_task: FinderTask, tx: Sender<Message>){
"it",
"identified",
"username",
"admin",
"administrator",
];
let mut file_content = String::new();
for extension in &files_to_read{
@@ -197,11 +208,87 @@ async fn task_handler(id: usize, current_task: FinderTask, tx: Sender<Message>){
#[tokio::main]
async fn main(){
print!{
"
██▒▒
▒▒████ ▓▓████████▓▓
▒▒██████████ ██████████████
██████████████ ▒▒██████████████
████████████████ ████████████████
████████████████▓▓ ▓▓████████████████
██████████████████▓▓██████████████████████
██████████████████████████████████████████ ▓▓██
██████████████████████████████████████████ ▒▒████████
▒▒████ ██████████████████████████████████████████████ ██████████████
████████▓▓ ▒▒██████████████████████████████████████████████████████████████████
████████████████▓▓████████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████████████████████████████▓▓
████████████████████████████████████████▓▓ ▓▓██████████████████████████████████
██████████████████████████████████▓▓ ████████████████████████████▒▒
██████████████████████████████ ████████████████████████
████████████████████████▓▓ ▓▓██████████████████
▒▒████████████████████▒▒ ████████████████
▒▒████████████████▒▒ /----------------------------------\\ ██████████████
██████████████▓▓ / \\ ████████████▓▓
██████████████ / \\ ▓▓████████████████████▓▓▓▓
▓▓████████████░░ / \\ ████████████████████████
░░██████████████ / |-| |-| \\ ▓▓██████████████████████▓▓
████████████████████████░░ / | | | | \\ ████████████████████████
▓▓██████████████████████████ / | | | | \\ ████████████████████████
██████████████████████████▒▒ / | | | | \\ ▒▒██████████████████████
██████████████████████████ / | | | | \\ ██████████████████████
░░██████████████████████████ / | | | | \\ ████████████████████▓▓
▒▒██████████████████████████ / | | | | \\ ████████████████▓▓
▓▓██████████████████████████ \\ | | | | / ██████████████
▓▓██████████████████████ \\ | | | | / ████████████
▓▓████████████████ \\ | | | | / ████████████
▓▓████████████ \\ | | | | / ████████████
████████████ \\ | | | | / ████████████
████████████▒▒ \\ | | | | / ██████████████▒▒
██████████████ \\ |-| |-| / ▓▓████████████████▓▓
██████████████ \\ / ██████████████████████
▒▒██████████████████ \\ / ▒▒████████████████████████
██████████████████████ \\ / ████████████████████████
██████████████████████████ \\----------------------------------/ ▓▓████████████████████████
██████████████████████████████ ░░████████████████████████▓▓
██████████████████████████████▒▒ ██████████████████████████
░░██████████████████████████████░░ ██████████████░░ ▒▒██████
████████████████████████████████ ████████████████
▒▒████████████████████████████████░░ ▒▒████████████████
██████▓▓▒▒ ██████████████████ ████████████████████
████████████████████▒▒ ▒▒████████████████████████
██████████████████████████▓▓▓▓▓▓████████████████████████████████▒▒
██████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████
▓▓████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████ ░░██████████████████
░░████████████████▒▒ ▒▒██████████████████ ████████████▒▒
▒▒██████████████ ████████████████ ██████
▓▓████████ ▓▓██████████████ ▒▒
▒▒████▒▒ ██████████████
██████████████
██████████████
__ __
/ _\\_ __ __ _ / _| ___ _ __ _ __ ___ _ _ ___
\\ \\| '_ \\ / _` | |_ / _ \\ '__| '__/ _ \\| | | / __|
_\\ \\ | | | (_| | _| __/ | | | | (_) | |_| \\__ \\
\\__/_| |_|\\__,_|_| \\___|_| |_| \\___/ \\__,_|___/
"
}
let args = Args::parse();
let mut outfile = PathBuf::new();
let mut threads = 10;
let mut save = false;
let mut computers = Vec::new();
let mut filter_computers = Vec::new();
let mut network = true;
let file_filter = vec![
String::from("ADMIN$")
];
if args.outfile.is_some(){
outfile = args.outfile.unwrap();
save = true;
@@ -209,26 +296,49 @@ async fn main(){
if args.threads.is_some(){
threads = args.threads.unwrap();
}
if args.diable_network{
network = false;
}
if args.targets.is_some(){
println!("gathering the targets you gave me.");
let targets = args.targets.unwrap();
if targets.contains(","){
let split_targets: Vec<&str> = targets.split(",").collect();
for target in split_targets{
computers.push(target.to_string());
computers.push(target.trim().to_lowercase());
}
}
else{
computers.push(targets);
}
}
if args.filter_targets.is_some(){
println!("gathering the filter you specified!");
let given_filter = args.filter_targets.unwrap();
let filters: Vec<&str> = given_filter.split(",").collect();
for filter in filters{
filter_computers.push(filter.trim().to_lowercase());
}
}
let hostname_res = Command::new("hostname").output();
if hostname_res.is_ok(){
let hostname_output = hostname_res.unwrap();
if hostname_output.stdout.len() > 0{
let hostname_string = String::from_utf8_lossy(&hostname_output.stdout).to_string();
if args.local{
computers.push(hostname_string.trim().to_lowercase());
}
else{
filter_computers.push(hostname_string.trim().to_lowercase());
}
}
if network{
println!("no targets given, proceeding with domain computer enumeration...");
println!("finding computers...");
let command_string = String::from("net group \"domain computers\" /domain");
let mut temp_file = fs::File::create("./temp.bat").unwrap();
write!(temp_file, "{}", command_string).unwrap();
let computer_res = Command::new(".\\temp.bat").output();
let computer_res = Command::new(".\\\\temp.bat").output();
let mut error_string = String::new();
let mut success_string = String::new();
fs::remove_file("./temp.bat").unwrap();
@@ -256,12 +366,16 @@ async fn main(){
for word in words{
let mut computer_name = word.to_string();
computer_name.pop();
computers.push(computer_name);
computers.push(computer_name.trim().to_lowercase());
}
}
}
}
}
}
if filter_computers.len() > 0{
computers.retain(|x| !filter_computers.iter().any(|y| y==x));
}
let mut tasks = Vec::new();
let mut id_counter = 0;
for computer in &computers{
@@ -331,7 +445,7 @@ async fn main(){
}
else{
let mut save_file = open_res.unwrap();
let write_res = write!(save_file,"share found! {}\n", finding.path);
let write_res = write!(save_file,"share found! {}\\n", finding.path);
if write_res.is_err(){
if !continue_wihtout_save{
eprintln!("{}", "error writing to save file!".red());
@@ -352,10 +466,12 @@ async fn main(){
}
}
}
if !file_filter.contains(&finding.path){
let new_task = FinderTask{id: id_counter, tasktype: TaskType::File, target: finding.path};
tasks.push(new_task);
id_counter += 1;
}
}
TaskType::File => {
let new_task = FinderTask{id: id_counter, tasktype: TaskType::Info, target: finding.path};
tasks.push(new_task);
@@ -383,7 +499,7 @@ async fn main(){
}
else{
let mut save_file = open_res.unwrap();
let write_res = write!(save_file,"keyword match at {}\n", finding.path);
let write_res = write!(save_file,"keyword match at {}\\n", finding.path);
if write_res.is_err(){
if !continue_wihtout_save{
eprintln!("{}", "error writing to save file!".red());
@@ -428,7 +544,7 @@ async fn main(){
}
else{
let mut save_file = open_res.unwrap();
let write_res = write!(save_file,"file found! {}\n", finding.path);
let write_res = write!(save_file,"file found! {}\\n", finding.path);
if write_res.is_err(){
if !continue_wihtout_save{
eprintln!("{}", "error writing to save file!".red());