Skip to main content

attack/domain/
software.rs

1use serde::{Deserialize, Serialize};
2use stix_rs::{CommonProperties, StixObject};
3use crate::domain::AttackObject;
4
5/// Represents MITRE ATT&CK Malware.
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct Malware {
8    #[serde(flatten)]
9    pub common: CommonProperties,
10    pub name: String,
11    pub description: Option<String>,
12    #[serde(default)]
13    pub aliases: Vec<String>,
14    #[serde(default, rename = "x_mitre_platforms")]
15    pub platforms: Vec<String>,
16    #[serde(default)]
17    pub is_family: bool,
18
19    // Extended ATT&CK fields
20    #[serde(default, rename = "x_mitre_version")]
21    pub version: Option<String>,
22
23    #[serde(default, rename = "x_mitre_contributors")]
24    pub contributors: Vec<String>,
25
26    #[serde(default, rename = "x_mitre_domains")]
27    pub domains: Vec<String>,
28
29    #[serde(default, rename = "x_mitre_aliases")]
30    pub mitre_aliases: Vec<String>,
31}
32
33/// Represents MITRE ATT&CK Tool.
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub struct Tool {
36    #[serde(flatten)]
37    pub common: CommonProperties,
38    pub name: String,
39    pub description: Option<String>,
40    #[serde(default)]
41    pub aliases: Vec<String>,
42    #[serde(default, rename = "x_mitre_platforms")]
43    pub platforms: Vec<String>,
44
45    // Extended ATT&CK fields
46    #[serde(default, rename = "x_mitre_version")]
47    pub version: Option<String>,
48
49    #[serde(default, rename = "x_mitre_contributors")]
50    pub contributors: Vec<String>,
51
52    #[serde(default, rename = "x_mitre_domains")]
53    pub domains: Vec<String>,
54
55    #[serde(default, rename = "x_mitre_aliases")]
56    pub mitre_aliases: Vec<String>,
57}
58
59/// Combined type for software (either malware or tool).
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub enum Software {
62    Malware(Malware),
63    Tool(Tool),
64}
65
66impl StixObject for Malware {
67    fn id(&self) -> &str {
68        &self.common.id
69    }
70
71    fn type_(&self) -> &str {
72        &self.common.r#type
73    }
74
75    fn created(&self) -> chrono::DateTime<chrono::Utc> {
76        self.common.created
77    }
78}
79
80impl AttackObject for Malware {
81    fn name(&self) -> &str {
82        &self.name
83    }
84
85    fn description(&self) -> Option<&str> {
86        self.description.as_deref()
87    }
88
89    fn revoked(&self) -> bool {
90        self.common.revoked.unwrap_or(false)
91    }
92
93    fn deprecated(&self) -> bool {
94        self.common.custom_properties.get("x_mitre_deprecated").and_then(|v| v.as_bool()).unwrap_or(false)
95    }
96}
97
98impl StixObject for Tool {
99    fn id(&self) -> &str {
100        &self.common.id
101    }
102
103    fn type_(&self) -> &str {
104        &self.common.r#type
105    }
106
107    fn created(&self) -> chrono::DateTime<chrono::Utc> {
108        self.common.created
109    }
110}
111
112impl AttackObject for Tool {
113    fn name(&self) -> &str {
114        &self.name
115    }
116
117    fn description(&self) -> Option<&str> {
118        self.description.as_deref()
119    }
120
121    fn revoked(&self) -> bool {
122        self.common.revoked.unwrap_or(false)
123    }
124
125    fn deprecated(&self) -> bool {
126        self.common.custom_properties.get("x_mitre_deprecated").and_then(|v| v.as_bool()).unwrap_or(false)
127    }
128}
129
130impl StixObject for Software {
131    fn id(&self) -> &str {
132        match self {
133            Software::Malware(m) => m.id(),
134            Software::Tool(t) => t.id(),
135        }
136    }
137
138    fn type_(&self) -> &str {
139        match self {
140            Software::Malware(m) => m.type_(),
141            Software::Tool(t) => t.type_(),
142        }
143    }
144
145    fn created(&self) -> chrono::DateTime<chrono::Utc> {
146        match self {
147            Software::Malware(m) => m.created(),
148            Software::Tool(t) => t.created(),
149        }
150    }
151}
152
153impl AttackObject for Software {
154    fn name(&self) -> &str {
155        match self {
156            Software::Malware(m) => m.name(),
157            Software::Tool(t) => t.name(),
158        }
159    }
160
161    fn description(&self) -> Option<&str> {
162        match self {
163            Software::Malware(m) => m.description(),
164            Software::Tool(t) => t.description(),
165        }
166    }
167
168    fn revoked(&self) -> bool {
169        match self {
170            Software::Malware(m) => m.revoked(),
171            Software::Tool(t) => t.revoked(),
172        }
173    }
174
175    fn deprecated(&self) -> bool {
176        match self {
177            Software::Malware(m) => m.deprecated(),
178            Software::Tool(t) => t.deprecated(),
179        }
180    }
181}