threatflux_string_analysis/
patterns.rs

1//! Pattern matching and pattern provider functionality
2
3use crate::types::AnalysisResult;
4use regex::Regex;
5use serde::{Deserialize, Serialize};
6
7/// Represents a pattern used for string matching and categorization
8#[derive(Debug, Clone)]
9pub struct Pattern {
10    /// Unique name for the pattern
11    pub name: String,
12    /// Regular expression
13    pub regex: Regex,
14    /// Category this pattern belongs to
15    pub category: String,
16    /// Description of what this pattern matches
17    pub description: String,
18    /// Whether matches are considered suspicious
19    pub is_suspicious: bool,
20    /// Severity level (0-10) if suspicious
21    pub severity: u8,
22}
23
24/// Serializable pattern definition
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct PatternDef {
27    /// Unique identifier for the pattern
28    pub name: String,
29    /// Regular expression pattern string
30    pub regex: String,
31    /// Category this pattern belongs to
32    pub category: String,
33    /// Human-readable description of what this pattern matches
34    pub description: String,
35    /// Whether matches should be flagged as suspicious
36    pub is_suspicious: bool,
37    /// Severity level (0-10) if suspicious
38    pub severity: u8,
39}
40
41impl PatternDef {
42    /// Convert to a compiled Pattern
43    pub fn compile(self) -> AnalysisResult<Pattern> {
44        Ok(Pattern {
45            name: self.name,
46            regex: Regex::new(&self.regex)?,
47            category: self.category,
48            description: self.description,
49            is_suspicious: self.is_suspicious,
50            severity: self.severity,
51        })
52    }
53}
54
55/// Trait for providing patterns
56pub trait PatternProvider: Send + Sync {
57    /// Get all patterns
58    fn get_patterns(&self) -> Vec<Pattern>;
59
60    /// Add a new pattern
61    fn add_pattern(&mut self, pattern: PatternDef) -> AnalysisResult<()>;
62
63    /// Remove a pattern by name
64    fn remove_pattern(&mut self, name: &str) -> AnalysisResult<()>;
65
66    /// Update an existing pattern
67    fn update_pattern(&mut self, pattern: PatternDef) -> AnalysisResult<()>;
68}
69
70/// Default pattern provider with built-in security patterns
71pub struct DefaultPatternProvider {
72    patterns: Vec<Pattern>,
73}
74
75impl DefaultPatternProvider {
76    /// Create a new provider with default security patterns
77    pub fn new() -> AnalysisResult<Self> {
78        let mut provider = Self {
79            patterns: Vec::new(),
80        };
81
82        // Network indicators
83        provider.add_pattern(PatternDef {
84            name: "url_pattern".to_string(),
85            regex: r"(?i)(https?|ftp|ssh|telnet|rdp)://".to_string(),
86            category: "network".to_string(),
87            description: "URL or network protocol".to_string(),
88            is_suspicious: true,
89            severity: 3,
90        })?;
91
92        provider.add_pattern(PatternDef {
93            name: "ip_address".to_string(),
94            regex: r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b".to_string(),
95            category: "network".to_string(),
96            description: "IP address pattern".to_string(),
97            is_suspicious: true,
98            severity: 4,
99        })?;
100
101        // Command execution
102        provider.add_pattern(PatternDef {
103            name: "shell_command".to_string(),
104            regex: r"(?i)(cmd\.exe|powershell|bash|sh)".to_string(),
105            category: "command".to_string(),
106            description: "Shell command interpreter".to_string(),
107            is_suspicious: true,
108            severity: 6,
109        })?;
110
111        provider.add_pattern(PatternDef {
112            name: "code_execution".to_string(),
113            regex: r"(?i)(eval|exec|system|shell)".to_string(),
114            category: "execution".to_string(),
115            description: "Code execution function".to_string(),
116            is_suspicious: true,
117            severity: 7,
118        })?;
119
120        // Crypto/encoding
121        provider.add_pattern(PatternDef {
122            name: "crypto_algorithm".to_string(),
123            regex: r"(?i)(base64|rot13|xor|aes|des|rsa)".to_string(),
124            category: "crypto".to_string(),
125            description: "Cryptographic or encoding algorithm".to_string(),
126            is_suspicious: true,
127            severity: 5,
128        })?;
129
130        provider.add_pattern(PatternDef {
131            name: "base64_string".to_string(),
132            regex: r"^[A-Za-z0-9+/]{20,}={0,2}$".to_string(),
133            category: "encoding".to_string(),
134            description: "Potential Base64 encoded string".to_string(),
135            is_suspicious: true,
136            severity: 4,
137        })?;
138
139        // File paths
140        provider.add_pattern(PatternDef {
141            name: "suspicious_path".to_string(),
142            regex: r"(?i)(\\temp\\|\/tmp\/|\\windows\\system32)".to_string(),
143            category: "path".to_string(),
144            description: "Suspicious file path".to_string(),
145            is_suspicious: true,
146            severity: 5,
147        })?;
148
149        // Credentials
150        provider.add_pattern(PatternDef {
151            name: "credential_keyword".to_string(),
152            regex: r"(?i)(passwords?|credential|secret|token|api[_-]?key)".to_string(),
153            category: "credential".to_string(),
154            description: "Credential-related keyword".to_string(),
155            is_suspicious: true,
156            severity: 8,
157        })?;
158
159        // Registry
160        provider.add_pattern(PatternDef {
161            name: "registry_key".to_string(),
162            regex: r"(?i)(HKEY_|SOFTWARE\\Microsoft\\Windows)".to_string(),
163            category: "registry".to_string(),
164            description: "Windows registry key".to_string(),
165            is_suspicious: true,
166            severity: 5,
167        })?;
168
169        // Malware indicators
170        provider.add_pattern(PatternDef {
171            name: "malware_keyword".to_string(),
172            regex: r"(?i)(dropper|payload|inject|hook|rootkit)".to_string(),
173            category: "malware".to_string(),
174            description: "Common malware terminology".to_string(),
175            is_suspicious: true,
176            severity: 9,
177        })?;
178
179        provider.add_pattern(PatternDef {
180            name: "surveillance_keyword".to_string(),
181            regex: r"(?i)(keylog|screenshot|webcam|microphone)".to_string(),
182            category: "surveillance".to_string(),
183            description: "Surveillance/spyware functionality".to_string(),
184            is_suspicious: true,
185            severity: 8,
186        })?;
187
188        Ok(provider)
189    }
190
191    /// Create an empty provider
192    pub fn empty() -> Self {
193        Self {
194            patterns: Vec::new(),
195        }
196    }
197}
198
199impl PatternProvider for DefaultPatternProvider {
200    fn get_patterns(&self) -> Vec<Pattern> {
201        self.patterns.clone()
202    }
203
204    fn add_pattern(&mut self, pattern_def: PatternDef) -> AnalysisResult<()> {
205        let pattern = pattern_def.compile()?;
206        self.patterns.push(pattern);
207        Ok(())
208    }
209
210    fn remove_pattern(&mut self, name: &str) -> AnalysisResult<()> {
211        self.patterns.retain(|p| p.name != name);
212        Ok(())
213    }
214
215    fn update_pattern(&mut self, pattern_def: PatternDef) -> AnalysisResult<()> {
216        self.remove_pattern(&pattern_def.name)?;
217        self.add_pattern(pattern_def)?;
218        Ok(())
219    }
220}
221
222impl Default for DefaultPatternProvider {
223    fn default() -> Self {
224        Self::new().expect("Failed to create default pattern provider")
225    }
226}