Skip to main content

ploit_malper/exploit/
models.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5pub const MODULE_EXPLOIT: &str = "exploit";
6pub const MODULE_AUXILIARY: &str = "auxiliary";
7
8/// A module option as described by the framework.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ModuleOption {
11    pub name: String,
12    pub required: bool,
13    pub default: Option<String>,
14    pub description: String,
15}
16
17/// Strongly typed metadata returned by the framework for a module.
18#[derive(Debug, Clone, Serialize, Deserialize, Default)]
19pub struct ModuleInfo {
20    pub name: String,
21    pub module_type: String,
22    pub rank: String,
23    pub description: String,
24    pub platforms: Vec<String>,
25    pub targets: Vec<String>,
26    pub options: Vec<ModuleOption>,
27    /// Names of options that must be supplied before the module can run.
28    pub required_options: Vec<String>,
29}
30
31/// One planned exploitation step derived from a database finding.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct ExploitStep {
34    pub module_type: String,
35    pub module_name: String,
36    /// CVE this module maps to, if the finding carried one.
37    pub cve: Option<String>,
38    /// Human-readable vulnerability (finding title).
39    pub vulnerability: String,
40    /// Framework rank for the module (excellent/great/good/...).
41    pub rank: String,
42    pub asset_id: String,
43    pub finding_id: String,
44    /// Host (IP or name) the module will be aimed at.
45    pub host: String,
46    pub service_port: Option<u16>,
47    pub service_protocol: Option<String>,
48    /// Options inferred automatically from database records.
49    pub inferred_options: BTreeMap<String, String>,
50    /// Options the module requires that we could not infer.
51    pub missing_options: Vec<String>,
52    /// Short payload compatibility hint.
53    pub payload_compatibility: String,
54    /// high / medium / low — how confident the mapping is.
55    pub confidence: String,
56    /// Whether the checklist defaults this module to selected.
57    pub default_selected: bool,
58}
59
60impl ExploitStep {
61    /// Fully resolved options: inferred plus any explicit overrides.
62    pub fn resolved_options(&self) -> BTreeMap<String, String> {
63        self.inferred_options.clone()
64    }
65}
66
67/// Result of launching a module against the framework.
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct ModuleRunResult {
70    pub job_id: Option<String>,
71    pub success: bool,
72    pub message: String,
73    pub raw: String,
74}
75
76/// Status of a background job.
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct JobStatus {
79    pub job_id: String,
80    pub running: bool,
81    pub status: String,
82    pub error: Option<String>,
83}
84
85/// A framework session (shell / meterpreter).
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct SessionInfo {
88    pub id: String,
89    pub typ: String,
90    pub target_host: String,
91    pub platform: String,
92    pub info: String,
93}
94
95/// A loot record.
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct LootInfo {
98    pub id: String,
99    pub name: String,
100    pub content_type: String,
101    pub host: String,
102    pub path: String,
103}
104
105/// Lifecycle of a single module execution.
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
107pub enum ExploitStatus {
108    /// Planned but not executed (dry run or deselected).
109    Planned,
110    /// Currently executing.
111    Running,
112    /// Completed successfully (module returned without error).
113    Completed,
114    /// Module failed or errored.
115    Failed,
116    /// Skipped by the operator or because a required option was missing.
117    Skipped,
118    /// Preview run — no module was contacted.
119    DryRun,
120}
121
122impl ExploitStatus {
123    pub fn as_str(&self) -> &'static str {
124        match self {
125            ExploitStatus::Planned => "planned",
126            ExploitStatus::Running => "running",
127            ExploitStatus::Completed => "completed",
128            ExploitStatus::Failed => "failed",
129            ExploitStatus::Skipped => "skipped",
130            ExploitStatus::DryRun => "dry_run",
131        }
132    }
133
134    pub fn parse(value: &str) -> Self {
135        match value {
136            "running" => ExploitStatus::Running,
137            "completed" => ExploitStatus::Completed,
138            "failed" => ExploitStatus::Failed,
139            "skipped" => ExploitStatus::Skipped,
140            "dry_run" => ExploitStatus::DryRun,
141            _ => ExploitStatus::Planned,
142        }
143    }
144}
145
146/// Outcome of executing one step, ready to be persisted.
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct ExploitOutcome {
149    pub step: ExploitStep,
150    pub status: ExploitStatus,
151    pub job_id: Option<String>,
152    pub session_id: Option<String>,
153    pub error: Option<String>,
154    pub loot: Vec<String>,
155    pub start_time: String,
156    pub finish_time: Option<String>,
157}
158
159/// Options understood by the `exploit` CLI command.
160#[derive(Debug, Clone, Default)]
161pub struct ExploitOptions {
162    pub dry_run: bool,
163    pub yes: bool,
164    pub module_filter: Option<String>,
165    pub target_filter: Option<String>,
166    pub payload_override: Option<String>,
167    pub workspace: Option<String>,
168    pub backend: Option<String>,
169    pub pocketbase_url: Option<String>,
170    pub sqlite_path: Option<String>,
171    pub verbose: bool,
172}