threatflux_string_analysis/
patterns.rs1use crate::types::AnalysisResult;
4use regex::Regex;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone)]
9pub struct Pattern {
10 pub name: String,
12 pub regex: Regex,
14 pub category: String,
16 pub description: String,
18 pub is_suspicious: bool,
20 pub severity: u8,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct PatternDef {
27 pub name: String,
29 pub regex: String,
31 pub category: String,
33 pub description: String,
35 pub is_suspicious: bool,
37 pub severity: u8,
39}
40
41impl PatternDef {
42 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
55pub trait PatternProvider: Send + Sync {
57 fn get_patterns(&self) -> Vec<Pattern>;
59
60 fn add_pattern(&mut self, pattern: PatternDef) -> AnalysisResult<()>;
62
63 fn remove_pattern(&mut self, name: &str) -> AnalysisResult<()>;
65
66 fn update_pattern(&mut self, pattern: PatternDef) -> AnalysisResult<()>;
68}
69
70pub struct DefaultPatternProvider {
72 patterns: Vec<Pattern>,
73}
74
75impl DefaultPatternProvider {
76 pub fn new() -> AnalysisResult<Self> {
78 let mut provider = Self {
79 patterns: Vec::new(),
80 };
81
82 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 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 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 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 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 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 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 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}