ploit-malper 0.2.6

Post-exploitation analysis and vulnerability intelligence toolkit
Documentation
use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

pub const MODULE_EXPLOIT: &str = "exploit";
pub const MODULE_AUXILIARY: &str = "auxiliary";

/// A module option as described by the framework.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModuleOption {
    pub name: String,
    pub required: bool,
    pub default: Option<String>,
    pub description: String,
}

/// Strongly typed metadata returned by the framework for a module.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ModuleInfo {
    pub name: String,
    pub module_type: String,
    pub rank: String,
    pub description: String,
    pub platforms: Vec<String>,
    pub targets: Vec<String>,
    pub options: Vec<ModuleOption>,
    /// Names of options that must be supplied before the module can run.
    pub required_options: Vec<String>,
}

/// One planned exploitation step derived from a database finding.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExploitStep {
    pub module_type: String,
    pub module_name: String,
    /// CVE this module maps to, if the finding carried one.
    pub cve: Option<String>,
    /// Human-readable vulnerability (finding title).
    pub vulnerability: String,
    /// Framework rank for the module (excellent/great/good/...).
    pub rank: String,
    pub asset_id: String,
    pub finding_id: String,
    /// Host (IP or name) the module will be aimed at.
    pub host: String,
    pub service_port: Option<u16>,
    pub service_protocol: Option<String>,
    /// Options inferred automatically from database records.
    pub inferred_options: BTreeMap<String, String>,
    /// Options the module requires that we could not infer.
    pub missing_options: Vec<String>,
    /// Short payload compatibility hint.
    pub payload_compatibility: String,
    /// high / medium / low — how confident the mapping is.
    pub confidence: String,
    /// Whether the checklist defaults this module to selected.
    pub default_selected: bool,
}

impl ExploitStep {
    /// Fully resolved options: inferred plus any explicit overrides.
    pub fn resolved_options(&self) -> BTreeMap<String, String> {
        self.inferred_options.clone()
    }
}

/// Result of launching a module against the framework.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModuleRunResult {
    pub job_id: Option<String>,
    pub success: bool,
    pub message: String,
    pub raw: String,
}

/// Status of a background job.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobStatus {
    pub job_id: String,
    pub running: bool,
    pub status: String,
    pub error: Option<String>,
}

/// A framework session (shell / meterpreter).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionInfo {
    pub id: String,
    pub typ: String,
    pub target_host: String,
    pub platform: String,
    pub info: String,
}

/// A loot record.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LootInfo {
    pub id: String,
    pub name: String,
    pub content_type: String,
    pub host: String,
    pub path: String,
}

/// Lifecycle of a single module execution.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ExploitStatus {
    /// Planned but not executed (dry run or deselected).
    Planned,
    /// Currently executing.
    Running,
    /// Completed successfully (module returned without error).
    Completed,
    /// Module failed or errored.
    Failed,
    /// Skipped by the operator or because a required option was missing.
    Skipped,
    /// Preview run — no module was contacted.
    DryRun,
}

impl ExploitStatus {
    pub fn as_str(&self) -> &'static str {
        match self {
            ExploitStatus::Planned => "planned",
            ExploitStatus::Running => "running",
            ExploitStatus::Completed => "completed",
            ExploitStatus::Failed => "failed",
            ExploitStatus::Skipped => "skipped",
            ExploitStatus::DryRun => "dry_run",
        }
    }

    pub fn parse(value: &str) -> Self {
        match value {
            "running" => ExploitStatus::Running,
            "completed" => ExploitStatus::Completed,
            "failed" => ExploitStatus::Failed,
            "skipped" => ExploitStatus::Skipped,
            "dry_run" => ExploitStatus::DryRun,
            _ => ExploitStatus::Planned,
        }
    }
}

/// Outcome of executing one step, ready to be persisted.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExploitOutcome {
    pub step: ExploitStep,
    pub status: ExploitStatus,
    pub job_id: Option<String>,
    pub session_id: Option<String>,
    pub error: Option<String>,
    pub loot: Vec<String>,
    pub start_time: String,
    pub finish_time: Option<String>,
}

/// Options understood by the `exploit` CLI command.
#[derive(Debug, Clone, Default)]
pub struct ExploitOptions {
    pub dry_run: bool,
    pub yes: bool,
    pub module_filter: Option<String>,
    pub target_filter: Option<String>,
    pub payload_override: Option<String>,
    pub workspace: Option<String>,
    pub backend: Option<String>,
    pub pocketbase_url: Option<String>,
    pub sqlite_path: Option<String>,
    pub verbose: bool,
}