From 0ef453427b863083e57155fb9a329858ba03c945 Mon Sep 17 00:00:00 2001 From: pyro Date: Fri, 17 Jul 2026 17:14:37 -0500 Subject: [PATCH] changed the parsing logic to use proper iteraters intead of for loops, and refined the filters and keywords a bit. --- src/main.rs | 225 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 142 insertions(+), 83 deletions(-) diff --git a/src/main.rs b/src/main.rs index ddd023c..520130d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,7 +57,7 @@ struct Args { #[arg( long, - help = "specific folder paths that should be ignored. comma separated." + help = "specific folder paths or file names that should be ignored. comma separated." )] filter_data: Option, @@ -72,7 +72,7 @@ struct Args { local: bool, #[arg(short, long, help = "disable network discovery")] - diable_network: bool, + disable_network: bool, } struct AppState { @@ -136,87 +136,131 @@ impl FinderTask { } } TaskType::File => { - let mut sent_lines = Vec::new(); - for entry_res in walkdir::WalkDir::new(self.target.clone()) { - if entry_res.is_ok() { - let entry = entry_res.unwrap(); - let file_path = entry.into_path(); - if file_path.file_name().is_some() { - let file_path_string = file_path.display().to_string(); - if !sent_lines.contains(&file_path_string) { - sent_lines.push(file_path_string.clone()); - let finding = Finding { - path: file_path_string, + walkdir::WalkDir::new(self.target.clone()) + .into_iter() + .for_each(|e| { + if let Ok(entry) = e { + if self + .filter + .iter() + .any(|f| !entry.path().to_string_lossy().contains(f)) + { + let file_path = entry.into_path(); + let new_finding = Finding { + path: file_path.display().to_string(), }; - if self.verbose { - println!("file found: {}", finding.path); + if !self.findings.iter().any(|f| f.path == new_finding.path) { + if self.verbose { + println!("file found: {}", new_finding.path); + } + self.findings.push(new_finding); } - if let Some(outfile) = self.outfile.clone() { - if let Ok(mut lock) = outfile.lock() { - if let Err(e) = lock.write( - format!("file found: {}\r\n", finding.path).as_bytes(), - ) { - println!("error writing log file! {e}"); + } + } + }); + } + TaskType::Info => { + if !self.filter.iter().any(|f| self.target.contains(f)) { + let files_to_read = vec![ + ".txt", + ".ini", + ".xml", + ".json", + ".config", + ".conf", + ".bat", + ".cmd", + ".sql", + ".ps1", + ".py", + ".vbscript", + ]; + + let interesting_info = vec![ + "password", + "pass", + "user", + "api", + "key", + "credit card", + " cc ", + "_cc_", + "-cc-", + "ssn", + " ssn ", + "_ssn_", + "-ssn-", + "social Security", + "tax", + "i9", + " it ", + "_it_", + "-it-", + "identified", + "username", + "admin", + "administrator", + ]; + let file_path = PathBuf::from(self.target.clone()); + if file_path.is_file() { + if file_path.exists() { + let mut read = false; + if let Some(filename) = file_path.file_name() { + if files_to_read + .iter() + .any(|r| filename.to_string_lossy().contains(r)) + { + if let Ok(file_content) = read_to_string(&file_path) { + read = true; + if interesting_info.iter().any(|i| { + filename.to_string_lossy().contains(i) + || file_content.contains(i) + }) && !self + .filter + .iter() + .any(|f| file_path.to_string_lossy().contains(f)) + { + if !self.findings.iter().any(|f| f.path == self.target) + { + self.findings.push(Finding { + path: self.target.clone(), + }); + println!("keyword match: {}", self.target); + if let Some(outfile) = self.outfile.clone() { + if let Ok(mut file_lock) = outfile.lock() { + if let Err(e) = file_lock.write( + format!( + "keyword match: {}\n", + self.target.clone() + ) + .as_bytes(), + ) { + println!("error writing to log {e}"); + } + } + } + } } } } - self.findings.push(finding); - } - } - } - } - } - TaskType::Info => { - let files_to_read = vec![ - ".txt", - ".ini", - ".xml", - ".json", - ".config", - ".conf", - ".bat", - ".cmd", - ".sql", - ".ps1", - ".py", - ".vbscript", - ]; - - let interesting_info = vec![ - "password", - "pass", - "user", - "api", - "key", - "credit card", - "cc", - "ssn", - "social Security", - "tax", - "i9", - "it", - "identified", - "username", - "admin", - "administrator", - ]; - if files_to_read.iter().any(|e| self.target.contains(e)) { - if let Ok(file_content) = read_to_string(&self.target) { - if interesting_info.iter().any(|i| self.target.contains(i)) - || interesting_info.iter().any(|i| file_content.contains(i)) - { - if !self.filter.iter().any(|f| self.target.contains(f)) { - println!("keyword match: {}", self.target); - self.findings.push(Finding { - path: self.target.clone(), - }); - if let Some(outfile) = self.outfile.clone() { - if let Ok(mut file_lock) = outfile.lock() { - if let Err(e) = file_lock.write( - format!("keyword match: {}\r\n", self.target.clone()) - .as_bytes(), - ) { - println!("error writing log file, {e}"); + if !read { + if interesting_info + .iter() + .any(|i| filename.to_string_lossy().contains(i)) + { + println!("keyword match: {}", self.target); + if let Some(outfile) = self.outfile.clone() { + if let Ok(mut file_lock) = outfile.lock() { + if let Err(e) = file_lock.write( + format!( + "keyword match: {}\n", + self.target.clone() + ) + .as_bytes(), + ) { + println!("error writing to log {e}"); + } + } } } } @@ -317,7 +361,7 @@ fn main() { let mut computers = Vec::new(); let mut filter_computers = Vec::new(); let mut network = true; - if args.diable_network { + if args.disable_network { network = false; } if args.targets.is_some() { @@ -423,7 +467,7 @@ fn main() { "C$\\Windows.old".to_string(), "ADMIN$\\".to_string(), "ProgramData\\Microsoft".to_string(), - "\\AppData\\Local\\Microsoft\\Internet Explorer\\brndlog.txt".to_string(), + "AppData\\Local\\Microsoft\\Internet Explorer\\brndlog.txt".to_string(), "desktop.ini".to_string(), "AppData\\Local\\Packages\\Microsoft.Windows.Search".to_string(), "AppData\\Local\\Microsoft\\Windows\\Shell\\DefaultLayouts.xml".to_string(), @@ -436,9 +480,7 @@ fn main() { "ContentDirectory.xml".to_string(), "avtransport.xml".to_string(), "ThirdPartyNotices.txt".to_string(), - "Program Files\\Common Files\\microsoft shared\\ink\\fsdefinitions".to_string(), - "Program Files\\Common Files\\microsoft shared\\ink\\Content.xml".to_string(), - "Program Files\\Common Files\\microsoft shared\\ink\\Alphabet.xml".to_string(), + "Program Files\\Common Files\\microsoft shared".to_string(), "Diagnostics\\Simple\\Simple.Tests.ps1".to_string(), "Microsoft.PowerShell.Operation.Validation.Format.ps1xml".to_string(), "Test\\Microsoft.PowerShell.Operation.Validation.Tests.ps1".to_string(), @@ -454,6 +496,23 @@ fn main() { "Program Files (x86)\\WindowsPowerShell\\Modules\\PackageManagement".to_string(), "Program Files (x86)\\WindowsPowerShell\\Modules\\PowerShellGet".to_string(), "Program Files (x86)\\WindowsPowerShell\\Modules\\Pester".to_string(), + "Program Files\\Internet Explorer".to_string(), + "Program Files\\Windows Defender".to_string(), + "Program Files\\WindowsApps".to_string(), + "Program Files\\WindowsPowerShell\\Modules\\PackageManagement".to_string(), + "Program Files (x86)\\Internet Explorer".to_string(), + "Program Files (x86)\\Microsoft".to_string(), + "ProgramData\\ntuser.pol".to_string(), + "ProgramData\\USOShared".to_string(), + "AppData\\Local\\ConnectedDevicesPlatform".to_string(), + "AppData\\Local\\Microsoft\\Internet Explorer".to_string(), + "ntuser.dat".to_string(), + "ntuser.ini".to_string(), + "Program Files (x86)\\Windows Defender".to_string(), + "AppData\\Local\\Microsoft\\Windows\\WinX".to_string(), + "AppData\\Local\\Microsoft_Corporation".to_string(), + "AppData\\Roaming\\Microsoft\\Internet Explorer".to_string(), + ]; if let Some(user_filter) = args.filter_data { user_filter.split(",").into_iter().for_each(|p| {