//! Configuration management for the Ghost detection engine. //! //! This module provides configuration structures for customizing detection //! behavior, process filtering, and performance tuning. use crate::GhostError; use serde::{Deserialize, Serialize}; use std::fs; use std::path::Path; /// Configuration options for the detection engine. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DetectionConfig { /// Enable shellcode pattern detection. pub shellcode_detection: bool, /// Enable process hollowing detection. pub hollowing_detection: bool, /// Enable Windows hook injection detection. pub hook_detection: bool, /// Minimum confidence threshold for suspicious classification (0.0 - 1.0). pub confidence_threshold: f32, /// Skip known safe system processes. pub skip_system_processes: bool, /// Maximum memory size to scan per process in bytes. pub max_memory_scan_size: usize, /// Enable thread behavior analysis. pub thread_analysis_enabled: bool, /// Enable evasion technique detection. pub evasion_detection: bool, /// Enable MITRE ATT&CK mapping. pub mitre_mapping: bool, /// Scan interval in milliseconds for continuous monitoring. pub scan_interval_ms: u64, /// Process filter configuration. pub process_filter: Option, } impl Default for DetectionConfig { fn default() -> Self { Self { shellcode_detection: true, hollowing_detection: true, hook_detection: true, confidence_threshold: 0.3, skip_system_processes: true, max_memory_scan_size: 100 * 1024 * 1024, // 100MB thread_analysis_enabled: true, evasion_detection: true, mitre_mapping: true, scan_interval_ms: 2000, process_filter: None, } } } impl DetectionConfig { /// Loads configuration from a TOML file. /// /// # Errors /// /// Returns an error if the file cannot be read or parsed. pub fn load>(path: P) -> Result { let content = fs::read_to_string(path)?; let config: DetectionConfig = toml::from_str(&content)?; config.validate()?; Ok(config) } /// Loads configuration from a file, returning default on error. pub fn load_or_default>(path: P) -> Self { Self::load(path).unwrap_or_default() } /// Saves configuration to a TOML file. /// /// # Errors /// /// Returns an error if the file cannot be written. pub fn save>(&self, path: P) -> Result<(), GhostError> { let content = toml::to_string_pretty(self).map_err(|e| GhostError::Configuration { message: e.to_string(), })?; fs::write(path, content)?; Ok(()) } /// Validates the configuration values. pub fn validate(&self) -> Result<(), GhostError> { if self.confidence_threshold < 0.0 || self.confidence_threshold > 1.0 { return Err(GhostError::Configuration { message: "confidence_threshold must be between 0.0 and 1.0".into(), }); } if self.max_memory_scan_size == 0 { return Err(GhostError::Configuration { message: "max_memory_scan_size must be greater than 0".into(), }); } Ok(()) } /// Creates a configuration optimized for high performance (less thorough). pub fn performance_mode() -> Self { Self { shellcode_detection: true, hollowing_detection: false, hook_detection: false, confidence_threshold: 0.5, skip_system_processes: true, max_memory_scan_size: 10 * 1024 * 1024, // 10MB thread_analysis_enabled: false, evasion_detection: false, mitre_mapping: false, scan_interval_ms: 5000, process_filter: None, } } /// Creates a configuration optimized for thorough detection (slower). pub fn thorough_mode() -> Self { Self { shellcode_detection: true, hollowing_detection: true, hook_detection: true, confidence_threshold: 0.2, skip_system_processes: false, max_memory_scan_size: 500 * 1024 * 1024, // 500MB thread_analysis_enabled: true, evasion_detection: true, mitre_mapping: true, scan_interval_ms: 1000, process_filter: None, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProcessFilter { pub whitelist: Vec, pub blacklist: Vec, pub system_processes: Vec, } impl Default for ProcessFilter { fn default() -> Self { Self { whitelist: vec![], blacklist: vec![], system_processes: vec![ "csrss.exe".to_string(), "wininit.exe".to_string(), "winlogon.exe".to_string(), "dwm.exe".to_string(), "explorer.exe".to_string(), ], } } } impl ProcessFilter { pub fn should_scan(&self, process_name: &str) -> bool { // If whitelist is not empty, only scan whitelisted processes if !self.whitelist.is_empty() { return self .whitelist .iter() .any(|name| process_name.contains(name)); } // Skip blacklisted processes if self .blacklist .iter() .any(|name| process_name.contains(name)) { return false; } // Skip system processes if configured if self .system_processes .iter() .any(|name| process_name == name) { return false; } true } } #[cfg(test)] mod tests { use super::*; #[test] fn test_default_config() { let config = DetectionConfig::default(); assert!(config.shellcode_detection); assert_eq!(config.confidence_threshold, 0.3); } #[test] fn test_process_filter() { let filter = ProcessFilter::default(); assert!(!filter.should_scan("csrss.exe")); assert!(filter.should_scan("notepad.exe")); } #[test] fn test_whitelist_filter() { let filter = ProcessFilter { whitelist: vec!["notepad.exe".to_string()], blacklist: vec![], system_processes: vec![], }; assert!(filter.should_scan("notepad.exe")); assert!(!filter.should_scan("malware.exe")); } }