Files
ghost/ghost-core/src/yara_engine.rs
2025-11-20 14:25:44 +02:00

156 lines
4.3 KiB
Rust

use crate::{GhostError, MemoryRegion, ProcessInfo};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::SystemTime;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DynamicYaraEngine {
rules: Vec<YaraRule>,
sources: Vec<YaraRuleSource>,
scan_cache: HashMap<String, CachedScanResult>,
}
#[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<RuleMatch>,
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<String, String>,
}
#[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<Self, GhostError> {
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<usize, GhostError> {
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<YaraScanResult, GhostError> {
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.is_executable() && region.protection.is_writable() {
matches.push(RuleMatch {
rule_name: "suspicious_rwx_memory".to_string(),
threat_level: ThreatLevel::High,
offset: region.base_address as u64,
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: bytes_scanned as u64,
})
}
pub fn get_rule_count(&self) -> usize {
self.rules.len()
}
pub fn get_sources(&self) -> &[YaraRuleSource] {
&self.sources
}
}