added some basic filtering

This commit is contained in:
pyro57000
2025-10-20 13:10:55 -05:00
parent c97e05008d
commit ec23b722f1
4 changed files with 89 additions and 38 deletions

2
Cargo.lock generated
View File

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

View File

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

View File

@@ -22,6 +22,12 @@ Options:
-t, --targets <TARGETS> specific targets. should be comma separated. -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) -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') -h, --help Print help (see more with '--help')

View File

@@ -42,8 +42,17 @@ struct Args{
#[arg(short, long, help = "specific targets. should be comma separated.")] #[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>, 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)")] #[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, 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)] #[derive(Clone)]
@@ -151,6 +160,8 @@ async fn task_handler(id: usize, current_task: FinderTask, tx: Sender<Message>){
"it", "it",
"identified", "identified",
"username", "username",
"admin",
"administrator",
]; ];
let mut file_content = String::new(); let mut file_content = String::new();
for extension in &files_to_read{ for extension in &files_to_read{
@@ -273,6 +284,11 @@ print!{
let mut threads = 10; let mut threads = 10;
let mut save = false; let mut save = false;
let mut computers = Vec::new(); 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(){ if args.outfile.is_some(){
outfile = args.outfile.unwrap(); outfile = args.outfile.unwrap();
save = true; save = true;
@@ -280,59 +296,86 @@ print!{
if args.threads.is_some(){ if args.threads.is_some(){
threads = args.threads.unwrap(); threads = args.threads.unwrap();
} }
if args.diable_network{
network = false;
}
if args.targets.is_some(){ if args.targets.is_some(){
println!("gathering the targets you gave me."); println!("gathering the targets you gave me.");
let targets = args.targets.unwrap(); let targets = args.targets.unwrap();
if targets.contains(","){ if targets.contains(","){
let split_targets: Vec<&str> = targets.split(",").collect(); let split_targets: Vec<&str> = targets.split(",").collect();
for target in split_targets{ for target in split_targets{
computers.push(target.to_string()); computers.push(target.trim().to_lowercase());
} }
} }
else{ else{
computers.push(targets); computers.push(targets);
} }
} }
else{ if args.filter_targets.is_some(){
println!("no targets given, proceeding with domain computer enumeration..."); println!("gathering the filter you specified!");
println!("finding computers..."); let given_filter = args.filter_targets.unwrap();
let command_string = String::from("net group \"domain computers\" /domain"); let filters: Vec<&str> = given_filter.split(",").collect();
let mut temp_file = fs::File::create("./temp.bat").unwrap(); for filter in filters{
write!(temp_file, "{}", command_string).unwrap(); filter_computers.push(filter.trim().to_lowercase());
let computer_res = Command::new(".\\\\temp.bat").output(); }
let mut error_string = String::new(); }
let mut success_string = String::new(); let hostname_res = Command::new("hostname").output();
fs::remove_file("./temp.bat").unwrap(); if hostname_res.is_ok(){
if computer_res.is_ok(){ let hostname_output = hostname_res.unwrap();
let output = computer_res.unwrap(); if hostname_output.stdout.len() > 0{
if output.stdout.len() > 0{ let hostname_string = String::from_utf8_lossy(&hostname_output.stdout).to_string();
success_string = String::from_utf8_lossy(&output.stdout).to_string(); if args.local{
computers.push(hostname_string.trim().to_lowercase());
} }
else if output.stderr.len() > 0{ else{
error_string = String::from_utf8_lossy(&output.stderr).to_string(); filter_computers.push(hostname_string.trim().to_lowercase());
} }
} }
else{ if network{
error_string = computer_res.err().unwrap().to_string(); println!("no targets given, proceeding with domain computer enumeration...");
} println!("finding computers...");
if error_string.len() > 0{ let command_string = String::from("net group \"domain computers\" /domain");
eprintln!("{}", "error getting computers!".red()); let mut temp_file = fs::File::create("./temp.bat").unwrap();
eprintln!("{}", error_string.red()); write!(temp_file, "{}", command_string).unwrap();
exit(1); let computer_res = Command::new(".\\\\temp.bat").output();
} let mut error_string = String::new();
if success_string.len() > 0{ let mut success_string = String::new();
for line in success_string.lines(){ fs::remove_file("./temp.bat").unwrap();
if line.contains("$"){ if computer_res.is_ok(){
let words:Vec<&str> = line.split_whitespace().collect(); let output = computer_res.unwrap();
for word in words{ if output.stdout.len() > 0{
let mut computer_name = word.to_string(); success_string = String::from_utf8_lossy(&output.stdout).to_string();
computer_name.pop(); }
computers.push(computer_name); else if output.stderr.len() > 0{
error_string = String::from_utf8_lossy(&output.stderr).to_string();
}
}
else{
error_string = computer_res.err().unwrap().to_string();
}
if error_string.len() > 0{
eprintln!("{}", "error getting computers!".red());
eprintln!("{}", error_string.red());
exit(1);
}
if success_string.len() > 0{
for line in success_string.lines(){
if line.contains("$"){
let words:Vec<&str> = line.split_whitespace().collect();
for word in words{
let mut computer_name = word.to_string();
computer_name.pop();
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 tasks = Vec::new();
let mut id_counter = 0; let mut id_counter = 0;
for computer in &computers{ for computer in &computers{
@@ -423,9 +466,11 @@ print!{
} }
} }
} }
let new_task = FinderTask{id: id_counter, tasktype: TaskType::File, target: finding.path}; if !file_filter.contains(&finding.path){
tasks.push(new_task); let new_task = FinderTask{id: id_counter, tasktype: TaskType::File, target: finding.path};
id_counter += 1; tasks.push(new_task);
id_counter += 1;
}
} }
TaskType::File => { TaskType::File => {
let new_task = FinderTask{id: id_counter, tasktype: TaskType::Info, target: finding.path}; let new_task = FinderTask{id: id_counter, tasktype: TaskType::Info, target: finding.path};