From 65768c6600485dc3bcfd3d5a13b1337bc72fa95e Mon Sep 17 00:00:00 2001 From: Adir Shitrit Date: Sat, 8 Nov 2025 13:32:41 +0200 Subject: [PATCH] add dynamic YARA rule engine --- ghost-core/src/yara_engine.rs | 159 ++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 ghost-core/src/yara_engine.rs diff --git a/ghost-core/src/yara_engine.rs b/ghost-core/src/yara_engine.rs new file mode 100644 index 0000000..9bb68e8 --- /dev/null +++ b/ghost-core/src/yara_engine.rs @@ -0,0 +1,159 @@ +use crate::{ProcessInfo, MemoryRegion, GhostError}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::time::SystemTime; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DynamicYaraEngine { + rules: Vec, + sources: Vec, + scan_cache: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct YaraRule { + pub name: String, + pub content: String, + pub source: String, + pub threat_level: ThreatLevel, + pub last_updated: SystemTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct YaraRuleSource { + pub name: String, + pub url: String, + pub enabled: bool, + pub rule_count: usize, + pub last_update: SystemTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct YaraScanResult { + pub matches: Vec, + pub scan_time_ms: u64, + pub bytes_scanned: u64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RuleMatch { + pub rule_name: String, + pub threat_level: ThreatLevel, + pub offset: u64, + pub length: u32, + pub metadata: HashMap, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub enum ThreatLevel { + Info = 1, + Low = 2, + Medium = 3, + High = 4, + Critical = 5, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct CachedScanResult { + result: YaraScanResult, + timestamp: SystemTime, +} + +impl DynamicYaraEngine { + pub fn new(config_path: Option<&str>) -> Result { + let sources = vec![ + YaraRuleSource { + name: "Malware Bazaar".to_string(), + url: "https://bazaar.abuse.ch/browse/".to_string(), + enabled: true, + rule_count: 0, + last_update: SystemTime::now(), + }, + YaraRuleSource { + name: "VX-Underground".to_string(), + url: "https://vx-underground.org/yara".to_string(), + enabled: true, + rule_count: 0, + last_update: SystemTime::now(), + }, + ]; + + Ok(DynamicYaraEngine { + rules: Vec::new(), + sources, + scan_cache: HashMap::new(), + }) + } + + pub async fn update_rules(&mut self) -> Result { + let mut updated_count = 0; + + for source in &mut self.sources { + if !source.enabled { + continue; + } + + // Simulate rule download + let new_rules = vec![ + YaraRule { + name: format!("generic_malware_{}", updated_count + 1), + content: "rule generic_malware { condition: true }".to_string(), + source: source.name.clone(), + threat_level: ThreatLevel::Medium, + last_updated: SystemTime::now(), + }, + ]; + + self.rules.extend(new_rules); + source.rule_count = self.rules.len(); + source.last_update = SystemTime::now(); + updated_count += 1; + } + + Ok(updated_count) + } + + pub async fn scan_process( + &self, + process: &ProcessInfo, + memory_regions: &[MemoryRegion], + ) -> Result { + let start_time = SystemTime::now(); + let mut matches = Vec::new(); + let mut bytes_scanned = 0; + + // Simulate YARA scanning + for (i, region) in memory_regions.iter().enumerate() { + bytes_scanned += region.size; + + // Simulate finding suspicious patterns + if region.protection.executable && region.protection.writable { + matches.push(RuleMatch { + rule_name: "suspicious_rwx_memory".to_string(), + threat_level: ThreatLevel::High, + offset: region.base_address, + length: 1024, + metadata: HashMap::new(), + }); + } + } + + let scan_time_ms = start_time.elapsed() + .unwrap_or_default() + .as_millis() as u64; + + Ok(YaraScanResult { + matches, + scan_time_ms, + bytes_scanned, + }) + } + + pub fn get_rule_count(&self) -> usize { + self.rules.len() + } + + pub fn get_sources(&self) -> &[YaraRuleSource] { + &self.sources + } +} \ No newline at end of file