pub fn collect_executable_files(
dir: &PathBuf,
options: &ScanOptions,
) -> Result<Vec<PathBuf>>Expand description
Collect all executable files from a directory
This function walks through a directory and identifies executable files based on their magic bytes and the specified file filter. It can operate recursively or just scan the top level, and can respect filesystem boundaries.
§Arguments
dir- Directory path to scanoptions- Scan options including recursion, filtering, and filesystem boundaries
§Returns
Returns a vector of paths to executable files found in the directory.
Examples found in repository?
examples/custom_filter.rs (line 16)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 // Collect executable files from a directory
11 let scan_path = PathBuf::from("/usr/bin");
12 let options = ScanOptions {
13 recursive: false,
14 ..Default::default()
15 };
16 let files = collect_executable_files(&scan_path, &options)?;
17
18 println!("Found {} executable files in {}", files.len(), scan_path.display());
19
20 // Analyze files with the same options
21 let report = analyze_files(files, &options)?;
22
23 // Custom filtering: find files missing stack canaries
24 let files_without_canary: Vec<&SecurityCheck> = report.files
25 .iter()
26 .filter(|check| {
27 check.checks.get("canary").map_or(false, |v| v.contains("No Canary"))
28 })
29 .collect();
30
31 println!("\n=== Files Missing Stack Canaries ===");
32 if files_without_canary.is_empty() {
33 println!("All files have stack canary protection! ✓");
34 } else {
35 for check in files_without_canary {
36 println!("⚠️ {} ({})", check.file_path, check.file_type);
37 }
38 }
39
40 // Custom filtering: find files with RPATH issues
41 let files_with_rpath: Vec<&SecurityCheck> = report.files
42 .iter()
43 .filter(|check| {
44 check.checks.get("rpath").map_or(false, |v| v == "RPATH") ||
45 check.checks.get("runpath").map_or(false, |v| v == "RUNPATH")
46 })
47 .collect();
48
49 println!("\n=== Files with RPATH/RUNPATH Issues ===");
50 if files_with_rpath.is_empty() {
51 println!("No RPATH/RUNPATH issues found! ✓");
52 } else {
53 for check in files_with_rpath {
54 println!("⚠️ {} ({})", check.file_path, check.file_type);
55 if let Some(rpath) = check.checks.get("rpath") {
56 if rpath == "RPATH" {
57 println!(" - Has RPATH");
58 }
59 }
60 if let Some(runpath) = check.checks.get("runpath") {
61 if runpath == "RUNPATH" {
62 println!(" - Has RUNPATH");
63 }
64 }
65 }
66 }
67
68 // Security score calculation
69 let total_checks = report.files.len();
70 let security_score = if total_checks > 0 {
71 (report.summary.secure_files as f64 / total_checks as f64) * 100.0
72 } else {
73 0.0
74 };
75
76 println!("\n=== Security Score ===");
77 println!("Overall security score: {:.1}%", security_score);
78 println!("({}/{} files are secure)", report.summary.secure_files, total_checks);
79
80 Ok(())
81}More examples
examples/advanced_filtering.rs (line 25)
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("=== ExeCheck Advanced Filtering Example ===\n");
14
15 // Example 1: Filter only Windows executables (.exe)
16 println!("1. Scanning for Windows executables (.exe files only):");
17 let exe_options = ScanOptions {
18 recursive: false,
19 issues_only: false,
20 strict: false,
21 file_filter: FileFilter::WindowsExecutables,
22 one_filesystem: false,
23 };
24
25 if let Ok(exe_files) = collect_executable_files(&PathBuf::from("."), &exe_options) {
26 println!(" Found {} .exe files", exe_files.len());
27 for file in exe_files.iter().take(3) {
28 println!(" - {}", file.display());
29 }
30 } else {
31 println!(" No .exe files found or error occurred");
32 }
33
34 // Example 2: Filter only Windows DLLs (.dll)
35 println!("\n2. Scanning for Windows DLLs (.dll files only):");
36 let dll_options = ScanOptions {
37 recursive: false,
38 issues_only: false,
39 strict: false,
40 file_filter: FileFilter::WindowsDlls,
41 one_filesystem: false,
42 };
43
44 if let Ok(dll_files) = collect_executable_files(&PathBuf::from("."), &dll_options) {
45 println!(" Found {} .dll files", dll_files.len());
46 for file in dll_files.iter().take(3) {
47 println!(" - {}", file.display());
48 }
49 } else {
50 println!(" No .dll files found or error occurred");
51 }
52
53 // Example 3: Custom extension filtering
54 println!("\n3. Custom extension filtering (exe, dll, so, dylib):");
55 let custom_extensions = vec![
56 "exe".to_string(),
57 "dll".to_string(),
58 "so".to_string(),
59 "dylib".to_string(),
60 ];
61
62 let custom_options = ScanOptions {
63 recursive: true,
64 issues_only: false,
65 strict: false,
66 file_filter: FileFilter::Extensions(custom_extensions),
67 one_filesystem: false,
68 };
69
70 if let Ok(custom_files) = collect_executable_files(&PathBuf::from("."), &custom_options) {
71 println!(" Found {} files with custom extensions", custom_files.len());
72 for file in custom_files.iter().take(5) {
73 println!(" - {}", file.display());
74 }
75 } else {
76 println!(" No files with custom extensions found or error occurred");
77 }
78
79 // Example 4: Custom predicate filtering
80 println!("\n4. Custom predicate filtering (files containing 'lib' in name):");
81 let lib_filter = |path: &std::path::Path| {
82 path.file_name()
83 .and_then(|name| name.to_str())
84 .map_or(false, |name| name.to_lowercase().contains("lib"))
85 };
86
87 let predicate_options = ScanOptions {
88 recursive: true,
89 issues_only: false,
90 strict: false,
91 file_filter: FileFilter::Custom(lib_filter),
92 one_filesystem: false,
93 };
94
95 if let Ok(lib_files) = collect_executable_files(&PathBuf::from("/usr/lib"), &predicate_options) {
96 println!(" Found {} library files", lib_files.len());
97 for file in lib_files.iter().take(5) {
98 println!(" - {}", file.display());
99 }
100 } else {
101 println!(" Error scanning /usr/lib or no library files found");
102 }
103
104 // Example 5: Filesystem boundary demonstration (Unix only)
105 #[cfg(unix)]
106 {
107 println!("\n5. Filesystem boundary scanning (Unix only):");
108 let boundary_options = ScanOptions {
109 recursive: true,
110 issues_only: false,
111 strict: false,
112 file_filter: FileFilter::All,
113 one_filesystem: true, // Stay within single filesystem
114 };
115
116 if let Ok(boundary_files) = collect_executable_files(&PathBuf::from("/"), &boundary_options) {
117 println!(" Found {} files within root filesystem", boundary_files.len());
118 println!(" (This prevents crossing into /proc, /sys, mounted drives, etc.)");
119 } else {
120 println!(" Error scanning root filesystem with boundary restrictions");
121 }
122 }
123
124 #[cfg(not(unix))]
125 {
126 println!("\n5. Filesystem boundary scanning:");
127 println!(" (Not supported on this platform - Unix-like systems only)");
128 }
129
130 // Example 6: Practical use case - analyze only PE files in a directory
131 println!("\n6. Practical example - Analyze Windows executables and DLLs with JSON output:");
132
133 let analysis_options = ScanOptions {
134 recursive: true,
135 issues_only: true, // Only show files with security issues
136 strict: false,
137 file_filter: FileFilter::WindowsExecutablesAndDlls,
138 one_filesystem: false,
139 };
140
141 // Try to analyze current directory for demo purposes
142 if let Ok(files) = collect_executable_files(&PathBuf::from("."), &analysis_options) {
143 if !files.is_empty() {
144 let report = analyze_files(files, &analysis_options)?;
145
146 if !report.files.is_empty() {
147 println!(" Analysis results (JSON format):");
148 print_report(&report, &OutputFormat::Json, None)?;
149 } else {
150 println!(" No security issues found in Windows executables/DLLs!");
151 }
152 } else {
153 println!(" No Windows executables or DLLs found in current directory");
154 }
155 }
156
157 println!("\n=== Advanced Filtering Example Complete ===");
158 Ok(())
159}