fat_binary_analysis/
fat_binary_analysis.rs1use execheck::{analyze_file, print_report, OutputFormat};
2use std::path::PathBuf;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
12 println!("=== ExeCheck Fat Binary Analysis Example ===");
13 println!();
14
15 let potential_fat_binaries = vec![
17 "/Applications/Xcode.app/Contents/MacOS/Xcode",
18 "/System/Applications/Calculator.app/Contents/MacOS/Calculator",
19 "/usr/bin/python3",
20 "/bin/bash",
21 ];
22
23 println!("Searching for fat binaries on the system...");
24 println!();
25
26 let mut found_examples = false;
27
28 for binary_path in potential_fat_binaries {
29 let path = PathBuf::from(binary_path);
30
31 if path.exists() {
32 println!("Analyzing: {}", binary_path);
33
34 match analyze_file(&path) {
35 Ok(result) => {
36 if result.file_type.contains("Fat") {
38 found_examples = true;
39
40 println!("✅ Found fat binary!");
41 println!(" File Type: {}", result.file_type);
42 println!(" Status: {}", result.overall_status);
43
44 if let Some(arch_count) = result.checks.get("architectures") {
45 println!(" Architectures: {}", arch_count);
46 }
47
48 if let Some(total_archs) = result.checks.get("total_architectures") {
50 println!(" Total Architectures: {}", total_archs);
51 }
52 if let Some(secure_archs) = result.checks.get("secure_architectures") {
53 println!(" Secure Architectures: {}", secure_archs);
54 }
55 if let Some(arch_list) = result.checks.get("architectures") {
56 println!(" Architecture List: {}", arch_list);
57 }
58
59 println!(" Per-Architecture Security:");
61 for (key, value) in &result.checks {
62 if key.contains("_pie") || key.contains("_canary") || key.contains("_nx") {
63 println!(" {}: {}", key, value);
64 }
65 }
66
67 println!();
68
69 println!("Detailed JSON Report:");
71 print_report(&execheck::SecurityReport {
72 files: vec![result],
73 summary: execheck::ReportSummary {
74 total_files: 1,
75 secure_files: 0,
76 insecure_files: 0,
77 unsupported_files: 1,
78 },
79 }, &OutputFormat::Json, None)?;
80
81 println!("\n{}\n", "=".repeat(60));
82 } else {
83 println!(" Not a fat binary ({})", result.file_type);
84 }
85 }
86 Err(e) => {
87 println!(" Error analyzing: {}", e);
88 }
89 }
90 } else {
91 println!("Skipping: {} (not found)", binary_path);
92 }
93 }
94
95 if !found_examples {
96 println!("No fat binaries found on system. Showing example output:");
98 println!();
99
100 demonstrate_fat_binary_output()?;
101 }
102
103 println!("=== Fat Binary Analysis Notes ===");
104 println!();
105 println!("Current Status:");
106 println!("• ✅ Fat binary detection and architecture counting");
107 println!("• ✅ Per-architecture security analysis");
108 println!("• ✅ Architecture-specific security checks (e.g., 'x86_64_pie', 'arm64_canary')");
109 println!("• ✅ Combined security status (Secure/Mixed/Insecure)");
110 println!();
111 println!("Fat binaries now show detailed architecture-specific security analysis,");
112 println!("allowing you to see security features for each architecture independently.");
113
114 Ok(())
115}
116
117fn demonstrate_fat_binary_output() -> Result<(), Box<dyn std::error::Error>> {
119 use std::collections::HashMap;
120
121 println!("Example Fat Binary Analysis (Mock Data):");
122 println!();
123
124 let mut checks = HashMap::new();
126 checks.insert("total_architectures".to_string(), "2".to_string());
127 checks.insert("secure_architectures".to_string(), "1".to_string());
128 checks.insert("architectures".to_string(), "x86_64, arm64".to_string());
129
130 checks.insert("x86_64_pie".to_string(), "PIE Enabled".to_string());
132 checks.insert("arm64_pie".to_string(), "PIE Enabled".to_string());
133 checks.insert("x86_64_canary".to_string(), "Canary Found".to_string());
134 checks.insert("arm64_canary".to_string(), "No Canary Found".to_string());
135 checks.insert("x86_64_nx".to_string(), "NX enabled".to_string());
136 checks.insert("arm64_nx".to_string(), "NX enabled".to_string());
137
138 let mock_result = execheck::SecurityCheck {
139 file_path: "/example/universal_app".to_string(),
140 file_type: "Mach-O Fat (2 archs)".to_string(),
141 checks,
142 overall_status: "Mixed".to_string(),
143 };
144
145 let report = execheck::SecurityReport {
146 files: vec![mock_result],
147 summary: execheck::ReportSummary {
148 total_files: 1,
149 secure_files: 0,
150 insecure_files: 1,
151 unsupported_files: 0,
152 },
153 };
154
155 println!("Current Output (Human Format):");
157 print_report(&report, &OutputFormat::Human, None)?;
158
159 println!("\nFuture Enhanced Output (When Fully Implemented):");
160 println!("File: /example/universal_app");
161 println!("Type: Mach-O Fat (2 archs)");
162 println!("Status: ⚠ Mixed");
163 println!("Security Checks:");
164 println!(" X86_64 Architecture:");
165 println!(" PIE : ✓ PIE Enabled");
166 println!(" Stack Canary : ✓ Canary Found");
167 println!(" NX : ✓ NX enabled");
168 println!();
169 println!(" ARM64 Architecture:");
170 println!(" PIE : ✓ PIE Enabled");
171 println!(" Stack Canary : ✗ No Canary Found");
172 println!(" NX : ✓ NX enabled");
173
174 Ok(())
175}