use crate::{DetectionResult, ProcessInfo, ThreatLevel}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::time::{Duration, SystemTime}; /// Threat Intelligence Integration Module /// Provides real-time threat context and IOC matching #[derive(Debug)] pub struct ThreatIntelligence { ioc_database: IocDatabase, threat_feeds: Vec, attribution_engine: AttributionEngine, reputation_cache: ReputationCache, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct IndicatorOfCompromise { pub id: String, pub ioc_type: IocType, pub value: String, pub threat_level: ThreatLevel, pub source: String, pub confidence: f32, pub created_date: SystemTime, pub expiry_date: Option, pub tags: Vec, pub mitre_techniques: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum IocType { ProcessName, ProcessPath, FileHash, NetworkAddress, MemorySignature, BehaviorPattern, RegistryKey, Mutex, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ThreatContext { pub matched_iocs: Vec, pub threat_actor: Option, pub campaign: Option, pub attribution_confidence: f32, pub risk_score: f32, pub recommended_actions: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ThreatActor { pub name: String, pub aliases: Vec, pub motivation: String, pub sophistication_level: SophisticationLevel, pub known_techniques: Vec, pub geographical_focus: Vec, pub first_seen: SystemTime, pub last_activity: SystemTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum SophisticationLevel { ScriptKiddie, Opportunistic, Professional, AdvancedPersistent, NationState, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Campaign { pub name: String, pub description: String, pub threat_actor: String, pub start_date: SystemTime, pub end_date: Option, pub target_sectors: Vec, pub attack_patterns: Vec, pub iocs: Vec, } #[derive(Debug)] pub struct IocDatabase { indicators: HashMap, hash_index: HashMap>, pattern_index: HashMap>, behavior_signatures: Vec, } #[derive(Debug, Clone)] pub struct BehaviorSignature { pub id: String, pub name: String, pub description: String, pub patterns: Vec, pub confidence_threshold: f32, pub severity: ThreatLevel, } #[derive(Debug, Clone)] pub struct BehaviorPattern { pub sequence: Vec, pub timing_constraints: Vec, pub frequency_requirements: FrequencyRequirement, } #[derive(Debug, Clone)] pub enum ProcessAction { ProcessCreation { name: String, cmdline: String }, MemoryAllocation { protection: String, size: usize }, NetworkConnection { address: String, port: u16 }, FileOperation { path: String, operation: String }, RegistryOperation { key: String, operation: String }, ProcessInjection { target_pid: u32, method: String }, } #[derive(Debug, Clone)] pub struct TimingConstraint { pub max_interval: Duration, pub sequence_window: Duration, } #[derive(Debug, Clone)] pub struct FrequencyRequirement { pub min_occurrences: u32, pub time_window: Duration, } #[derive(Debug)] pub struct ThreatFeed { pub name: String, pub url: String, pub feed_type: FeedType, pub update_interval: Duration, pub last_update: SystemTime, pub credential: Option, } #[derive(Debug, Clone)] pub enum FeedType { StixTaxii, JSON, CSV, XML, MISP, OpenIOC, } #[derive(Debug, Clone)] pub struct FeedCredential { pub api_key: String, pub username: Option, pub password: Option, } #[derive(Debug)] pub struct AttributionEngine { threat_actors: HashMap, campaigns: HashMap, attribution_rules: Vec, similarity_calculator: SimilarityCalculator, } #[derive(Debug, Clone)] pub struct AttributionRule { pub rule_id: String, pub conditions: Vec, pub confidence_weight: f32, pub threat_actor: String, pub campaign: Option, } #[derive(Debug, Clone)] pub enum AttributionCondition { IocMatch { ioc_types: Vec, min_matches: u32, }, TechniquePattern { techniques: Vec, correlation: f32, }, TemporalPattern { time_windows: Vec, frequency: u32, }, GeographicalIndicator { regions: Vec, confidence: f32, }, } #[derive(Debug)] pub struct SimilarityCalculator { technique_weights: HashMap, temporal_weights: HashMap, behavioral_weights: HashMap, } #[derive(Debug)] pub struct ReputationCache { process_reputations: HashMap, ip_reputations: HashMap, hash_reputations: HashMap, cache_ttl: Duration, } #[derive(Debug, Clone)] pub struct ProcessReputation { pub process_name: String, pub reputation_score: f32, pub classification: ReputationClass, pub sources: Vec, pub last_updated: SystemTime, pub occurrence_count: u32, } #[derive(Debug, Clone)] pub enum ReputationClass { Trusted, Unknown, Suspicious, Malicious, PUA, // Potentially Unwanted Application } #[derive(Debug, Clone)] pub struct IpReputation { pub ip_address: String, pub reputation_score: f32, pub categories: Vec, pub threat_types: Vec, pub geographical_info: GeographicalInfo, } #[derive(Debug, Clone)] pub struct GeographicalInfo { pub country: String, pub region: String, pub city: String, pub isp: String, pub organization: String, } #[derive(Debug, Clone)] pub struct HashReputation { pub file_hash: String, pub hash_type: HashType, pub reputation_score: f32, pub vendor_detections: Vec, pub file_info: Option, } #[derive(Debug, Clone)] pub enum HashType { MD5, SHA1, SHA256, SHA512, } #[derive(Debug, Clone)] pub struct VendorDetection { pub vendor: String, pub detection_name: String, pub confidence: f32, pub scan_date: SystemTime, } #[derive(Debug, Clone)] pub struct FileInfo { pub file_name: String, pub file_size: u64, pub file_type: String, pub creation_date: SystemTime, pub signature_info: Option, } #[derive(Debug, Clone)] pub struct SignatureInfo { pub is_signed: bool, pub signer: Option, pub signature_valid: bool, pub certificate_info: Option, } #[derive(Debug, Clone)] pub struct CertificateInfo { pub issuer: String, pub subject: String, pub serial_number: String, pub valid_from: SystemTime, pub valid_to: SystemTime, } impl ThreatIntelligence { pub fn new() -> Self { Self { ioc_database: IocDatabase::new(), threat_feeds: Vec::new(), attribution_engine: AttributionEngine::new(), reputation_cache: ReputationCache::new(), } } /// Initialize threat intelligence with default threat feeds pub async fn initialize_default_feeds(&mut self) -> Result<(), Box> { // Add default threat feeds self.add_threat_feed(ThreatFeed { name: "MITRE ATT&CK".to_string(), url: "https://attack.mitre.org/stix/".to_string(), feed_type: FeedType::StixTaxii, update_interval: Duration::from_secs(86400), // Daily last_update: SystemTime::now(), credential: None, }); self.add_threat_feed(ThreatFeed { name: "AlienVault OTX".to_string(), url: "https://otx.alienvault.com/api/v1/".to_string(), feed_type: FeedType::JSON, update_interval: Duration::from_secs(3600), // Hourly last_update: SystemTime::now(), credential: None, }); // Initialize with basic IOCs self.load_default_iocs().await?; Ok(()) } /// Enrich detection results with threat intelligence pub async fn enrich_detection(&self, detection: &DetectionResult) -> ThreatContext { let mut matched_iocs = Vec::new(); let mut risk_score = 0.0f32; // Check process name against IOCs if let Some(iocs) = self .ioc_database .lookup_process_name(&detection.process.name) { matched_iocs.extend(iocs); } // Check process path against IOCs if let Some(path) = &detection.process.path { if let Some(iocs) = self.ioc_database.lookup_process_path(path) { matched_iocs.extend(iocs); } } // Check memory signatures for indicator in &detection.indicators { if let Some(iocs) = self.ioc_database.lookup_memory_signature(indicator) { matched_iocs.extend(iocs); } } // Calculate risk score based on matched IOCs for ioc in &matched_iocs { risk_score += match ioc.threat_level { ThreatLevel::Clean => 0.0, ThreatLevel::Suspicious => ioc.confidence * 0.5, ThreatLevel::Malicious => ioc.confidence * 1.0, }; } // Perform attribution analysis let (threat_actor, campaign, attribution_confidence) = self .attribution_engine .analyze_attribution(&matched_iocs, &detection.indicators); // Generate recommended actions let recommended_actions = self.generate_recommendations(&matched_iocs, risk_score); ThreatContext { matched_iocs, threat_actor, campaign, attribution_confidence, risk_score: risk_score.min(1.0), recommended_actions, } } /// Add a new threat feed pub fn add_threat_feed(&mut self, feed: ThreatFeed) { self.threat_feeds.push(feed); } /// Update all threat feeds pub async fn update_threat_feeds(&mut self) -> Result<(), Box> { let mut updates = Vec::new(); for (idx, feed) in self.threat_feeds.iter().enumerate() { if SystemTime::now() .duration_since(feed.last_update) .unwrap_or_default() >= feed.update_interval { // Fetch data inline to avoid borrow issues let iocs = Vec::new(); // Stub implementation updates.push((idx, iocs)); } } for (idx, iocs) in updates { self.ioc_database.update_indicators(iocs); self.threat_feeds[idx].last_update = SystemTime::now(); } Ok(()) } /// Fetch data from a threat feed async fn fetch_feed_data( &self, feed: &ThreatFeed, ) -> Result, Box> { // Implementation would depend on feed type match feed.feed_type { FeedType::JSON => self.fetch_json_feed(feed).await, FeedType::StixTaxii => self.fetch_stix_feed(feed).await, FeedType::CSV => self.fetch_csv_feed(feed).await, _ => Err("Unsupported feed type".into()), } } async fn fetch_json_feed( &self, feed: &ThreatFeed, ) -> Result, Box> { // Placeholder implementation // In a real implementation, this would fetch from the feed URL Ok(Vec::new()) } async fn fetch_stix_feed( &self, feed: &ThreatFeed, ) -> Result, Box> { // Placeholder implementation // In a real implementation, this would parse STIX/TAXII data Ok(Vec::new()) } async fn fetch_csv_feed( &self, feed: &ThreatFeed, ) -> Result, Box> { // Placeholder implementation // In a real implementation, this would parse CSV threat data Ok(Vec::new()) } /// Load default IOCs for common injection techniques async fn load_default_iocs(&mut self) -> Result<(), Box> { let default_iocs = vec![ IndicatorOfCompromise { id: "IOC-001".to_string(), ioc_type: IocType::ProcessName, value: "rundll32.exe".to_string(), threat_level: ThreatLevel::Suspicious, source: "Default".to_string(), confidence: 0.6, created_date: SystemTime::now(), expiry_date: None, tags: vec![ "process-injection".to_string(), "living-off-the-land".to_string(), ], mitre_techniques: vec!["T1055".to_string()], }, IndicatorOfCompromise { id: "IOC-002".to_string(), ioc_type: IocType::MemorySignature, value: "CreateRemoteThread".to_string(), threat_level: ThreatLevel::Suspicious, source: "Default".to_string(), confidence: 0.8, created_date: SystemTime::now(), expiry_date: None, tags: vec!["process-injection".to_string(), "dll-injection".to_string()], mitre_techniques: vec!["T1055.001".to_string()], }, IndicatorOfCompromise { id: "IOC-003".to_string(), ioc_type: IocType::BehaviorPattern, value: "rwx_allocation_followed_by_execution".to_string(), threat_level: ThreatLevel::Malicious, source: "Default".to_string(), confidence: 0.9, created_date: SystemTime::now(), expiry_date: None, tags: vec!["shellcode".to_string(), "code-injection".to_string()], mitre_techniques: vec!["T1055.002".to_string()], }, ]; for ioc in default_iocs { self.ioc_database.add_indicator(ioc); } Ok(()) } fn generate_recommendations( &self, iocs: &[IndicatorOfCompromise], risk_score: f32, ) -> Vec { let mut recommendations = Vec::new(); if risk_score > 0.8 { recommendations.push("CRITICAL: Immediate isolation recommended".to_string()); recommendations.push("Initiate incident response procedures".to_string()); recommendations.push("Collect forensic artifacts for analysis".to_string()); } else if risk_score > 0.5 { recommendations.push("HIGH: Enhanced monitoring required".to_string()); recommendations.push("Review process behavior and network connections".to_string()); recommendations.push("Consider sandboxed analysis".to_string()); } else if risk_score > 0.2 { recommendations.push("MEDIUM: Continued observation advised".to_string()); recommendations.push("Log all activities for correlation".to_string()); } // Add technique-specific recommendations for ioc in iocs { for technique in &ioc.mitre_techniques { match technique.as_str() { "T1055" => { recommendations.push("Deploy process injection countermeasures".to_string()) } "T1055.001" => { recommendations.push("Monitor DLL loading activities".to_string()) } "T1055.002" => { recommendations.push("Implement PE injection detection".to_string()) } _ => {} } } } recommendations.sort(); recommendations.dedup(); recommendations } } impl IocDatabase { pub fn new() -> Self { Self { indicators: HashMap::new(), hash_index: HashMap::new(), pattern_index: HashMap::new(), behavior_signatures: Vec::new(), } } pub fn add_indicator(&mut self, ioc: IndicatorOfCompromise) { // Add to main database self.indicators.insert(ioc.id.clone(), ioc.clone()); // Update indexes for fast lookup match ioc.ioc_type { IocType::FileHash => { self.hash_index .entry(ioc.value.clone()) .or_insert_with(Vec::new) .push(ioc.id.clone()); } IocType::MemorySignature | IocType::BehaviorPattern => { self.pattern_index .entry(ioc.value.clone()) .or_insert_with(Vec::new) .push(ioc.id.clone()); } _ => {} } } pub fn lookup_process_name(&self, name: &str) -> Option> { let matches: Vec<_> = self .indicators .values() .filter(|ioc| ioc.ioc_type == IocType::ProcessName && ioc.value == name) .cloned() .collect(); if matches.is_empty() { None } else { Some(matches) } } pub fn lookup_process_path(&self, path: &str) -> Option> { let matches: Vec<_> = self .indicators .values() .filter(|ioc| ioc.ioc_type == IocType::ProcessPath && path.contains(&ioc.value)) .cloned() .collect(); if matches.is_empty() { None } else { Some(matches) } } pub fn lookup_memory_signature(&self, signature: &str) -> Option> { if let Some(ioc_ids) = self.pattern_index.get(signature) { let matches: Vec<_> = ioc_ids .iter() .filter_map(|id| self.indicators.get(id)) .cloned() .collect(); if matches.is_empty() { None } else { Some(matches) } } else { None } } pub fn update_indicators(&mut self, new_iocs: Vec) { for ioc in new_iocs { self.add_indicator(ioc); } } } impl AttributionEngine { pub fn new() -> Self { Self { threat_actors: HashMap::new(), campaigns: HashMap::new(), attribution_rules: Vec::new(), similarity_calculator: SimilarityCalculator::new(), } } pub fn analyze_attribution( &self, iocs: &[IndicatorOfCompromise], indicators: &[String], ) -> (Option, Option, f32) { let mut best_actor: Option = None; let mut best_campaign: Option = None; let mut best_confidence = 0.0f32; // Analyze each attribution rule for rule in &self.attribution_rules { let confidence = self.evaluate_attribution_rule(rule, iocs, indicators); if confidence > best_confidence { best_confidence = confidence; if let Some(actor) = self.threat_actors.get(&rule.threat_actor) { best_actor = Some(actor.clone()); } if let Some(campaign_name) = &rule.campaign { if let Some(campaign) = self.campaigns.get(campaign_name) { best_campaign = Some(campaign.clone()); } } } } (best_actor, best_campaign, best_confidence) } fn evaluate_attribution_rule( &self, rule: &AttributionRule, iocs: &[IndicatorOfCompromise], indicators: &[String], ) -> f32 { let mut total_confidence = 0.0f32; let mut condition_count = 0; for condition in &rule.conditions { match condition { AttributionCondition::IocMatch { ioc_types, min_matches, } => { let matches = iocs .iter() .filter(|ioc| ioc_types.contains(&ioc.ioc_type)) .count() as u32; if matches >= *min_matches { total_confidence += rule.confidence_weight; } } AttributionCondition::TechniquePattern { techniques, correlation, } => { let technique_matches = iocs .iter() .flat_map(|ioc| &ioc.mitre_techniques) .filter(|tech| techniques.contains(tech)) .count(); if technique_matches as f32 / techniques.len() as f32 >= *correlation { total_confidence += rule.confidence_weight; } } _ => {} // Implement other condition types as needed } condition_count += 1; } if condition_count > 0 { total_confidence / condition_count as f32 } else { 0.0 } } } impl SimilarityCalculator { pub fn new() -> Self { Self { technique_weights: HashMap::new(), temporal_weights: HashMap::new(), behavioral_weights: HashMap::new(), } } } impl ReputationCache { pub fn new() -> Self { Self { process_reputations: HashMap::new(), ip_reputations: HashMap::new(), hash_reputations: HashMap::new(), cache_ttl: Duration::from_secs(3600), // 1 hour } } }