1 Commits
main ... 3.1.8

Author SHA1 Message Date
pyro57000
2ebb29828b added a function to parse net view output to find
shares.
2025-07-16 11:22:04 -05:00
15 changed files with 1154 additions and 4061 deletions

3548
pentest_tool/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,9 +11,8 @@ directories = "5.0.1"
dns-lookup = "2.0.4" dns-lookup = "2.0.4"
fs_extra = "1.3.0" fs_extra = "1.3.0"
futures-io = { version = "0.2.0-beta" } futures-io = { version = "0.2.0-beta" }
iced = "0.13.1"
reqwest = {version = "0.12.12", features = ["blocking", "json"]} reqwest = {version = "0.12.12", features = ["blocking", "json"]}
rfd = "0.15.3"
rodio = "0.20.1" rodio = "0.20.1"
ssh-rs = "0.5.0"
term_size = "0.3.2" term_size = "0.3.2"
walkdir = "2.5.0" walkdir = "2.5.0"

View File

@@ -1,7 +0,0 @@
default:default:/home/pyro/syncs/work_folder/FRSecure/notes/Hack_Notes/pentest_notes/:/home/pyro/syncs/work_folder/FRSecure/pentests/:no:atarchbox:current
altimate_medical:2025_internal_pentest:/home/pyro/syncs/work_folder/FRSecure/notes/Hack_Notes/pentest_notes/current/altimate_medical:/home/pyro/syncs/work_folder/FRSecure/pentests/current/altimate_medical/2025_internal_pentest:yes:atarchbox_altimate_medical:current
fennemore_law:2025_vishing_test:/home/pyro/syncs/work_folder/FRSecure/notes/Hack_Notes/pentest_notes/current/fennemore_law/2025_vishing_test:/home/pyro/syncs/work_folder/FRSecure/pentests/current/fennemore_law/2025_vishing_test:no:atarchbox_fennemore_law:current
horizontal:2025_internal_pentest:/home/pyro/syncs/work_folder/FRSecure/notes/Hack_Notes/pentest_notes/current/horizontal/2025_internal_pentest:/home/pyro/syncs/work_folder/FRSecure/pentests/current/horizontal/2025_internal_pentest:no:atarchbox_horizontal:current
NDSU_Foundation:2025_internal_pentest:/home/pyro/syncs/work_folder/FRSecure/notes/Hack_Notes/pentest_notes/current/NDSU_Foundation/2025_internal_pentest:/home/pyro/syncs/work_folder/FRSecure/pentests/current/horizontal/2025_internal_pentest:no:atarchbox_NDSU_Foundation:current
offsec:osed:/home/pyro/syncs/personal_folder/2nd-brain:/home/pyro/syncs/personal_folder/tech-hacking-stuff/active_projects/offsec/osed:no:atarchbox_offsec:current
frsecure:2025_external_pentest:/var/home/pyro/syncs/work_notes/Hack_Notes/pentest_notes/current/frsecure/2025_external_pentest:/var/home/pyro/syncs/work_folder/FRSecure/pentests/current/frsecure/2025_external_pentest:no:atarchbox_frsecure:current

View File

@@ -1,4 +1,3 @@
use std::os::unix::process::CommandExt;
use std::process::Command; use std::process::Command;
use std::{path::PathBuf, process}; use std::{path::PathBuf, process};
use std::env; use std::env;
@@ -7,7 +6,6 @@ use std::io::Write;
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use std::time::Duration; use std::time::Duration;
use colored::Colorize; use colored::Colorize;
use iced::theme::palette::Success;
use crate::{get_user_input, Project}; use crate::{get_user_input, Project};
@@ -41,8 +39,7 @@ pub fn stop_all_boxes(projects: &Vec<Project>){
} }
} }
pub fn project_standalone_terminal(project: Project, mut terminal: String, display: &bool) -> Option<String>{ pub fn project_standalone_terminal(project: Project, mut terminal: String){
let mut return_data = String::new();
terminal = terminal.trim_end().to_owned(); terminal = terminal.trim_end().to_owned();
let mut profile = false; let mut profile = false;
if terminal.contains("profile"){ if terminal.contains("profile"){
@@ -69,69 +66,18 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String, displ
print!("{}", terminal); print!("{}", terminal);
let start = terminal_start.spawn(); let start = terminal_start.spawn();
match start{ match start{
Ok(_child) => { Ok(_child) => println!("New Terminal Started, you can retun to the menu now!"),
if *display{ Err(_error) => println!("error starting new terminanl, something may be wrong with the terminal part of your config!\nCheck ~/.conf/pyro_pentest_tool/conf for errors")
println!("New Terminal Started!");
return None;
}
else{
return_data.push_str("string New Terminal Started!");
return Some(return_data);
}},
Err(_error) => {
if *display{
println!("error starting new terminanl, something may be wrong with the terminal part of your config!\nCheck ~/.conf/pyro_pentest_tool/conf for errors");
return None;
}
else{
return_data.push_str("error starting new terminanl, something may be wrong with the terminal part of your config!\nCheck ~/.conf/pyro_pentest_tool/conf for errors");
return Some(return_data);
}}
} }
//process::Command::new("konsole").arg("--profile").arg("attack").arg(project.boxname).spawn().expect("error opeing konsole"); //process::Command::new("konsole").arg("--profile").arg("attack").arg(project.boxname).spawn().expect("error opeing konsole");
} }
pub fn project_inline_terminal(project: Project, given_command: Option<String>) -> Option<String>{ pub fn project_inline_terminal(project: Project){
let mut return_data = String::new(); process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
if given_command.is_none(){
process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
return None;
}
else{
let command_string = given_command.unwrap();
let command_vec: Vec<&str> = command_string.split(" ").collect();
let mut command = process::Command::new("distrobox");
command.arg("enter");
command.arg("--root");
command.arg(project.boxname);
command.arg("--");
for arg in command_vec{
command.arg(arg);
}
let com_res = command.output();
if com_res.is_err(){
let error = com_res.err().unwrap().to_string();
return_data.push_str("\nerror running command!");
return_data.push_str(&error);
return Some(return_data);
}
let output = com_res.unwrap();
let success_out = output.stdout;
let fail_out = output.stderr;
if success_out.len() > 0{
let out_string = format!("\n{}", String::from_utf8_lossy(&success_out));
return_data.push_str(&out_string);
}
if fail_out.len() > 0 {
let out_string = format!("\n{}", String::from_utf8_lossy(&fail_out));
return_data.push_str(&out_string);
}
return Some(return_data);
}
} }
fn make_box_cli(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool){ #[allow(unused)]
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool){
println!("stopping template box to ensure we can clone it!"); println!("stopping template box to ensure we can clone it!");
let stop_result = Command::new("distrobox").arg("stop").arg("--root").arg(boxtemplate).status(); let stop_result = Command::new("distrobox").arg("stop").arg("--root").arg(boxtemplate).status();
if stop_result.is_err(){ if stop_result.is_err(){
@@ -217,104 +163,6 @@ fn make_box_cli(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, ne
} }
} }
fn make_box_gui(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool, terminal: String) -> Option<String>{
terminal.replace("!!!", "");
println!("{}", terminal);
let terminal_vec: Vec<&str> = terminal.split(" ").collect();
let terminal_command = terminal_vec[0].to_owned();
println!("term_command = {}", terminal_command);
let mut terminal_args: Vec<String> = Vec::new();
if terminal.contains("konsole"){
terminal_args.push(String::from("-e"));
}
else{
for arg in &terminal_vec[1..]{
terminal_args.push(format!("{}", arg));
}
}
for arg in &terminal_args{
println!("{}", arg);
}
let mut terminal_launch_cmd = process::Command::new(&terminal_command);
for arg in &terminal_args{
terminal_launch_cmd.arg(arg);
}
let _status = terminal_launch_cmd.arg("distrobox").arg("stop").arg("--root").arg(boxtemplate).status().unwrap();
if new{
let mut terminal_launch_cmd = process::Command::new(&terminal_command);
for arg in &terminal_args{
terminal_launch_cmd.arg(arg);
}
let _status = terminal_launch_cmd.arg("distrobox")
.arg("stop").arg("--root")
.arg(&project.boxname)
.arg("&&")
.arg("distrobox")
.arg("rm")
.arg("--root")
.arg("-f")
.arg(&project.boxname)
.status()
.unwrap();
}
let mut new_box_cmd = process::Command::new(&terminal_command);
for arg in &terminal_args{
new_box_cmd.arg(arg);
}
let tools_line = format!("{}:/tools:rw", project.files_folder.display());
let files_line = format!("{}:/pentest:rw", tools_dir.display());
let _status = new_box_cmd.arg("distrobox")
.arg("create")
.arg("--root")
.arg("--clone")
.arg(boxtemplate)
.arg("--volume")
.arg(files_line)
.arg("--volume")
.arg(tools_line)
.arg("--name")
.arg(&project.boxname)
.arg("--init")
.status()
.unwrap();
let mut boxname_cmd = process::Command::new(&terminal_command);
for arg in &terminal_args{
boxname_cmd.arg(arg);
}
let _status = boxname_cmd.arg("distrobox")
.arg("enter")
.arg("--root")
.arg(&project.boxname)
.arg("--")
.arg("echo")
.arg(&project.boxname)
.arg(">")
.arg("/pentest/boxname")
.arg("&&")
.arg("sudo")
.arg("ln")
.arg("ln")
.arg("-sf")
.arg("/pentest/boxname")
.arg("/etc/boxname")
.status()
.unwrap();
return Some(String::from("Distrobox created successfull!"));
}
#[allow(unused)]
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool, terminal: Option<String>, display: &bool) -> Option<String>{
if *display{
make_box_cli(project, tools_dir, boxtemplate, new, fingerprint);
return None;
}
else{
let output = make_box_gui(project, tools_dir, boxtemplate, new, fingerprint, terminal.expect("this should only be called when the terminal is set!"));
return output;
}
}
pub fn clean_unused_boxes(projects: &Vec<Project>, boxtemplate: &String) -> Option<JoinHandle<()>>{ pub fn clean_unused_boxes(projects: &Vec<Project>, boxtemplate: &String) -> Option<JoinHandle<()>>{
println!("starting template box: {}", boxtemplate); println!("starting template box: {}", boxtemplate);

View File

@@ -1,7 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::process::Termination;
use rfd::FileDialog;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::path::PathBuf; use std::path::PathBuf;
@@ -23,12 +21,14 @@ use crate::box_controls;
use crate::info_controls; use crate::info_controls;
use crate::start_pentest; use crate::start_pentest;
use crate::get_user_input; use crate::get_user_input;
use crate::menu;
use crate::portscan_controls; use crate::portscan_controls;
use crate::victim_commands; use crate::victim_commands;
use crate::enumeration; use crate::enumeration;
use crate:: tool_controls; use crate:: tool_controls;
use crate::configuration; use crate::configuration;
use crate::tableize; use crate::tableize;
use crate::exploit;
fn help(command: Option<String>){ fn help(command: Option<String>){
@@ -77,9 +77,10 @@ fn help(command: Option<String>){
"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => lines.push("separate work and personal||swpp, separate projects, seppro||This command lets you separate work and personal projects into separate config files. This allows you to load personal and work projects separately!".to_owned()), "separate work and personal projects" | "swpp" | "separate projects" | "seppro" => lines.push("separate work and personal||swpp, separate projects, seppro||This command lets you separate work and personal projects into separate config files. This allows you to load personal and work projects separately!".to_owned()),
"switch to personal projects" | "switch personal" => lines.push("switch to personal projects||switch personal||This command lets you switch which config file is loaded to the personal config file.".to_owned()), "switch to personal projects" | "switch personal" => lines.push("switch to personal projects||switch personal||This command lets you switch which config file is loaded to the personal config file.".to_owned()),
"switch to work projects" | "switch work" => lines.push("switch to work projects||switch work||This command lets you switch to load the work projects.".to_owned()), "switch to work projects" | "switch work" => lines.push("switch to work projects||switch work||This command lets you switch to load the work projects.".to_owned()),
"parse net view" | "pnv" => lines.push("parse net view||pnv||This command takes a text file of netview output and parses it into share paths".to_owned()),
_ => () _ => ()
} }
tableize(lines, &true); tableize(lines);
} }
else{ else{
println!("Welcom to Pyro's pentest command line!"); println!("Welcom to Pyro's pentest command line!");
@@ -124,9 +125,10 @@ fn help(command: Option<String>){
"separate work and personal projects||swpp, separate projects, seppro".to_owned(), "separate work and personal projects||swpp, separate projects, seppro".to_owned(),
"switch to personal projects||switch personal".to_owned(), "switch to personal projects||switch personal".to_owned(),
"switch to work projects||switch work".to_owned(), "switch to work projects||switch work".to_owned(),
"parse net view||pnv".to_owned(),
"help||?, -h".to_owned()]; "help||?, -h".to_owned()];
println!("available commands:"); println!("available commands:");
tableize(lines, &true); tableize(lines);
} }
} }
@@ -159,9 +161,7 @@ pub fn next_project_id(config_path: &PathBuf) -> Option<i32>{
pub fn run_command(cmd: String, pub fn run_command(cmd: String,
settings: &HashMap<&str, String>, settings: &HashMap<&str, String>,
config_path: &PathBuf, config_path: &PathBuf,
mut projects: &mut Vec<Project>, mut projects: &mut Vec<Project>) -> Option<JoinHandle<()>> {
display: bool,
given_data: Option<String>) -> (Option<Option<JoinHandle<()>>>, Option<String>) {
let base_files = PathBuf::from(settings["project_files"].clone()); let base_files = PathBuf::from(settings["project_files"].clone());
let base_notes = PathBuf::from(settings["project_notes"].clone()); let base_notes = PathBuf::from(settings["project_notes"].clone());
let tools_dir = PathBuf::from(settings["tools_folder"].clone()); let tools_dir = PathBuf::from(settings["tools_folder"].clone());
@@ -178,13 +178,13 @@ pub fn run_command(cmd: String,
let new_id_res = next_project_id(&config_path); let new_id_res = next_project_id(&config_path);
if new_id_res.is_none(){ if new_id_res.is_none(){
println!("{}", "failed to get new project ID!".red()); println!("{}", "failed to get new project ID!".red());
return (None, None); return None;
} }
let mut new_id = new_id_res.unwrap(); let mut new_id = new_id_res.unwrap();
let active_project_res = get_active_project(&projects); let active_project_res = get_active_project(&projects);
if active_project_res.is_none(){ if active_project_res.is_none(){
println!("{}", "failed to get active project!".red()); println!("{}", "failed to get active project!".red());
return (None, None); return None;
} }
let active_project = active_project_res.unwrap(); let active_project = active_project_res.unwrap();
let mut notes_folder_string = format!("{}", &active_project.notes_folder.display()); let mut notes_folder_string = format!("{}", &active_project.notes_folder.display());
@@ -223,51 +223,52 @@ pub fn run_command(cmd: String,
else{ else{
help(None); help(None);
} }
return (None, None); return None;
} }
//change for stuff, one sec.
match cmd.as_str(){ match cmd.as_str(){
"list projects" | "lp" | "listp" | "list p" => {project_controls::list_projects(&projects, &display); return (None, None)}, "list projects" | "lp" | "listp" | "list p" => {project_controls::list_projects(&projects); return None},
"switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return (None, None)}, "switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return None},
"show active project" | "show active" | "sa" | "show a" => {let output = format!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()); return (None, Some(output))}, "show active project" | "show active" | "sa" | "show a" => {println!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()); return None},
"create new project" | "cnp" | "new project" | "np" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, &upcoming_files, &upcoming_notes, &boxtemplate, &password_spray_file); return (None, None)}, "create new project" | "cnp" | "new project" | "np" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, &upcoming_files, &upcoming_notes, &boxtemplate, &password_spray_file); return None},
"save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path, &display); return (None, None)}, "save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path); return None},
"import project" | "ip" | "import" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint, Some(terminal), &display); return (None, None)}, "import project" | "ip" | "import" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint); return None},
"remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path, None); return (None, None)}, "remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path); return None},
"show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects, &display); return (None, None)}, "show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects); return None},
"promote project" | "pp" | "promote" => {project_controls::promote_project(&mut projects.clone(), &config_path, &active_project.files_folder, &active_project.notes_folder, &tools_dir, &boxtemplate, fingerprint, given_data, terminal); return (None, None)}, "promote project" | "pp" | "promote" => {project_controls::promote_project(&mut projects, &config_path, &base_files, &base_notes, &tools_dir, &boxtemplate, fingerprint); return None},
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone(), &display); return (None, None)}, "new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()); return None},
"inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone(), given_data); return (None, None)}, "inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone()); return None},
//"cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone(), &display); return (Some(cs_thread), None)}, "cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); return cs_thread},
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint, Some(terminal), &display); return (None, None)}, "recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint); return None},
//"generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project, &display); return (None, None)}, "generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project); return None},
//"inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project, &display); return (None, None)}, "inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project); return None},
//"build attack notes" | "ban" | "attack notes" | "hn" => {portscan_controls::build_cmd_for_host_discovery(&active_project, &display); return (None, None);} "build attack notes" | "ban" | "attack notes" | "hn" => {portscan_controls::build_cmd_for_host_discovery(&active_project); return None;}
//"host discovery" | "build host discovery" | "hd" | "bhd" => {portscan_controls::build_cmd_for_host_discovery(&active_project, &display); return (None, None)}, "host discovery" | "build host discovery" | "hd" | "bhd" => {portscan_controls::build_cmd_for_host_discovery(&active_project); return None},
//"cobaltstrike port scan" | "cs port scan" | "csps" => {portscan_controls::build_cs_portscan_cmd(&active_project, &display); return (None, None)}, "cobaltstrike port scan" | "cs port scan" | "csps" => {portscan_controls::build_cs_portscan_cmd(&active_project); return None},
//"parse port scan" | "pps" | "parse scan" => {portscan_controls::parse_csportscan(&active_project, None, None, &display); return (None, None)}, "parse port scan" | "pps" | "parse scan" => {portscan_controls::parse_csportscan(&active_project); return None},
//"stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects, &display); return (None, None)}, "stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects); return None},
//"password spray" | "pass spray" | "pas" => {info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path, &display); return (None, None)}, "password spray" | "pass spray" | "pas" => {info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path); return None},
//"bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone(), &display); return (Some(bloodhound_handle), None);}, "bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); return Some(bloodhound_handle);},
//"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project, &display); return (None, None)}, "parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project); return None},
//"prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate, &display); return (Some(prune_thread), None)}, "prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); return prune_thread},
//"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {portscan_controls::parse_normal_nmap_output(&active_project, &display); return (None, None);}, "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, &display); if scope_res.is_some(){for host in scope_res.unwrap(){println!("{}", host)}}return (None, 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},
//"update git tools" | "ugt" | "update git" | "ug" => {tool_controls::update_git_tools(&tools_dir, &display); return (None, None)}, "update git tools" | "ugt" | "update git" | "ug" => {tool_controls::update_git_tools(&tools_dir); return None},
//"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project, &display); return (None, None);}, "port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project); return None;},
//"port scan command" | "psc" | "nmap command" | "nmc" => {portscan_controls::build_nmap_command(&active_project, &display); return (None, None);} "port scan command" | "psc" | "nmap command" | "nmc" => {portscan_controls::build_nmap_command(&active_project); return None;}
//"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir, &display); return (None, None);}, "sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir); return None;},
//"dns records" | "dr" => {let dns_handle = enumeration::run_dns_enumeration(&active_project, None, true, , &display); return (Some(dns_handle), None);}, "dns records" | "dr" => {let dns_handle = enumeration::run_dns_enumeration(&active_project, None, true); return dns_handle;},
//"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => {let gobuster_handle = enumeration::bruteforce_subs(&active_project, None,None, true, &display); return (Some(gobuster_handle), None)}, "brute force subdomains"| "bsd" | "gobuster dns" | "gd" => {let gobuster_handle = enumeration::bruteforce_subs(&active_project, None,None, true); return gobuster_handle},
//"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => {let all_dns_handle = enumeration::do_all_dns_enumeration(&active_project, &display); return (Some(all_dns_handle), None)}, "dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => {let all_dns_handle = enumeration::do_all_dns_enumeration(&active_project); return all_dns_handle},
//"dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true, &display); return (Some(twist_handle), None)}, "dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true); return twist_handle},
//"print report information" | "pri" => {info_controls::print_report_information(&active_project, &display); return (None, None);}, "print report information" | "pri" => {info_controls::print_report_information(&active_project); return None;},
//"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path, &display); return (None, None);}, "modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path); return None;},
//"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => {project_controls::separate_personal_work_projects(&config_path, &display); return (None, None);} "separate work and personal projects" | "swpp" | "separate projects" | "seppro" => {project_controls::separate_personal_work_projects(&config_path); return None;}
//"switch to personal projects" | "switch personal" => {let mut project_load_res = project_controls::swith_to_personal(&config_path, &display); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return (None, None);}, "switch to personal projects" | "switch personal" => {let mut project_load_res = project_controls::swith_to_personal(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;},
//"switch to work projects" | "switch work" => {let mut project_load_res = project_controls::swith_to_work(&config_path, &display); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return (None, None);}, "switch to work projects" | "switch work" => {let mut project_load_res = project_controls::swith_to_work(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;},
//"show settings" | "print settings" | "shset" | "pset" => {configuration::print_settings(&settings, &display); return (None, None)}, "ssh spray" | "sshs" | "spray ssh" => {exploit::ssh_spray(None, None, None, get_user_input("spraying with an ssh key?").contains("y")); return None;},
_ => {help(None); println!("\n\n unknown command."); return (None, None);} "show settings" | "print settings" | "shset" | "pset" => {configuration::print_settings(&settings); return None},
"parse net view" | "pnv" => {info_controls::parse_net_view(&active_project); return None;},
_ => {help(None); println!("\n\n unknown command."); return None;}
} }
} }
@@ -343,7 +344,7 @@ pub fn cli(mut projects: &mut Vec<Project>, config_path: &PathBuf) {
print_banner(banner); print_banner(banner);
while loopize{ while loopize{
let settings = configuration::load_config(config_path); let settings = configuration::load_config(config_path);
project_controls::save_projects(&projects, &config_path, &true); project_controls::save_projects(&projects, &config_path);
let active_project_res = get_active_project(&projects); let active_project_res = get_active_project(&projects);
if active_project_res.is_none(){ if active_project_res.is_none(){
println!("{}", "failed to get active project!".red()); println!("{}", "failed to get active project!".red());
@@ -374,16 +375,16 @@ for help enter help or ?. for information about a specific command enter help (c
} }
match command.as_str(){ match command.as_str(){
"exit" => loopize = false, "exit" => loopize = false,
"menu" | "main menu" | "mm" => {let menu_thread_option = menu::main_menu(&mut projects, config_path.clone(), &settings);},
"print banner" | "banner" => print_banner(banner), "print banner" | "banner" => print_banner(banner),
"clear" | "clear screen" | "cls" => {clear().unwrap(); print_banner(banner);}, "clear" | "clear screen" | "cls" => {clear().unwrap(); print_banner(banner);},
"list threads" | "threads" | "lst" => println!("There are {} threads still running.", threads.len()), "list threads" | "threads" | "lst" => println!("There are {} threads still running.", threads.len()),
"info" => println!("{}", current_information), "info" => println!("{}", current_information),
"test_open" => {let file = FileDialog::new().set_directory(active_project.files_folder.clone()).pick_file(); println!("{}", file.unwrap().display())}, "test_table" => {let mut lines = Vec::new(); lines.push("column1||column2||column3||column4".to_owned()); lines.push("thing1||thing2||thing3||thing4".to_owned()); lines.push("ttttttttttttttttthing5||thing6||thing7||thing8".to_owned()); tableize(lines);}
"test_table" => {let mut lines = Vec::new(); lines.push("column1||column2||column3||column4".to_owned()); lines.push("thing1||thing2||thing3||thing4".to_owned()); lines.push("ttttttttttttttttthing5||thing6||thing7||thing8".to_owned()); tableize(lines, &true);} _ => {let thread_option = run_command(command, &settings, config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
_ => {let (thread_option, output) = run_command(command, &settings, config_path, &mut projects, true, None); if thread_option.is_some(){threads.push(thread_option.unwrap());} if output.is_some(){print_success(output.unwrap());};},
} }
} }
project_controls::save_projects(&projects, &config_path, &true); project_controls::save_projects(&projects, &config_path);
if get_user_input("do you want to stop all the boxes?").contains("y"){ if get_user_input("do you want to stop all the boxes?").contains("y"){
box_controls::stop_all_boxes(&projects); box_controls::stop_all_boxes(&projects);
} }
@@ -440,9 +441,7 @@ for help enter help or ?. for information about a specific command enter help (c
println!("note this will hang until all threads have completed"); println!("note this will hang until all threads have completed");
println!("please make sure to close all spawned programs such as cobalt strike and bloodhound."); println!("please make sure to close all spawned programs such as cobalt strike and bloodhound.");
for thread in threads{ for thread in threads{
if thread.is_some(){ let _ = thread.join();
thread.unwrap().join().unwrap();
}
} }
} }
if worksapces_in_use{ if worksapces_in_use{

View File

@@ -184,5 +184,5 @@ pub fn print_settings(settings: &HashMap<&str, String>){
let new_line = format!("{}||{}", setting, settings[setting]); let new_line = format!("{}||{}", setting, settings[setting]);
lines.push(new_line); lines.push(new_line);
} }
tableize(lines, &true); tableize(lines);
} }

177
pentest_tool/src/exploit.rs Normal file
View File

@@ -0,0 +1,177 @@
use std::fs::read_to_string;
use std::path::PathBuf;
use ssh;
use crate::Project;
use crate::print_error;
use crate::print_success;
use crate::print_informational;
use crate::get_user_input;
pub fn ssh_spray(user_path: Option<&PathBuf>,
target_path: Option<&PathBuf>,
given_data: Option<String>,
key: bool)
-> Option<String>{
let mut display = true;
//if given_data.is_some(){
// display = false;
// }
let mut return_data = String::new();
let mut targets = Vec::new();
let mut users = Vec::new();
let mut ports = Vec::new();
let mut spray_data = String::new();
let mut success = Vec::new();
print_informational("getting paths to data files...");
match display{
true => {
print_informational("getting paths to data files...");
let users_read_res = read_to_string(get_user_input("path to the username file?"));
let target_read_res = read_to_string(get_user_input("path to targets file?"));
if users_read_res.is_err(){
print_error("error reading users file!", users_read_res.err().unwrap().to_string());
return None;
}
let users_string = users_read_res.unwrap();
if target_read_res.is_err(){
print_error("error reading target file!", target_read_res.err().unwrap().to_string());
return None;
}
let target_string = target_read_res.unwrap();
let temp_users: Vec<&str> = users_string.split("\n").collect();
let temp_targets: Vec<&str> = target_string.split("\n").collect();
for user in temp_users{
users.push(String::from(user));
print_informational(format!("{} loaded!", user));
}
print_informational("the default ports to try are 22 and 2222.");
if get_user_input("continue with the defaults?").contains("y"){
ports.push(String::from("22"));
ports.push(String::from("2222"));
}
else{
loop{
let new_port = get_user_input("new port to add? enter END in all caps when done.");
if new_port.contains("END"){
break;
}
else{
ports.push(new_port);
}
}
}
for target in temp_targets{
for port in &ports{
let new_target = format!("{}:{}", target, port);
targets.push(String::from(new_target));
}
}
if key{
spray_data = get_user_input("path to key file?");
}
else {
spray_data = get_user_input("password to spray?");
}
}
false => {
if user_path.is_none(){
return_data.push_str("\nno username file provided!\nExiting...");
return Some(return_data);
}
if target_path.is_none(){
return_data.push_str("\nno target file provided!\nExiting...");
return Some(return_data);
}
if given_data.is_none(){
return_data.push_str("\nno password or key file provided!\nexiting...");
return Some(return_data);
}
let users_read_res = read_to_string(user_path.unwrap());
let target_read_res = read_to_string(target_path.unwrap());
spray_data = given_data.unwrap();
if users_read_res.is_err(){
return_data.push_str("\nerror reading user file!\nExiting...");
return Some(return_data);
}
if target_read_res.is_err(){
return_data.push_str("\nerror reading target file!\nExiting...");
return Some(return_data);
}
let users_string = users_read_res.unwrap();
let targets_string = target_read_res.unwrap();
let temp_users: Vec<&str> = users_string.split("\n").collect();
let temp_targets: Vec<&str> = targets_string.split("\n").collect();
for user in temp_users{
users.push(String::from(user));
}
for target in temp_targets{
targets.push(String::from(target));
}
}
}
if display{
print_informational("spraying useers...");
}
match key{
true => {
for target in targets{
for user in &users{
let session_res = ssh::create_session().username(user.as_str()).private_key_path(&spray_data).connect(&target);
if session_res.is_err(){
let error_text = format!("Error opening ssh session for {} on {}", user, target);
if display{
print_error(&error_text, format!("{}",session_res.err().unwrap()));
}
else{
return_data.push_str(format!("\n{}", error_text).as_str());
}
break;
}
let session = session_res.unwrap();
let out_string = format!("{}@{}", user, target);
success.push(out_string.clone());
if display{
print_success(out_string);
}
session.close();
}
}
},
false => {
for target in targets{
for user in &users{
let information_text = format!("testing {} on {}", user, target);
print_informational(information_text);
let session_res = ssh::create_session().username(user.as_str()).password(&spray_data).connect(&target);
if session_res.is_err(){
let error_text = format!("Error opening ssh session for {} on {}", user, target);
if display{
print_error(&error_text, format!("{}",session_res.err().unwrap()));
}
else{
return_data.push_str(format!("\n{}", error_text).as_str());
}
}
else{
let session = session_res.unwrap();
let out_string = format!("{}@{}", user, target);
success.push(out_string.clone());
if display{
print_success(out_string);
}
session.close();
}
}
}
}
}
let return_data = success.join("\n");
if display{
println!("these are the successful sprays!");
print_success(return_data);
return None;
}
else{
return Some(return_data);
}
}

View File

@@ -1,498 +0,0 @@
use iced::Length::Fill;
use iced::Renderer;
use iced::widget::{button, center, column, pick_list, row, scrollable, text, text_input, Column};
use iced::Theme;
use rfd::FileDialog;
use std::collections::HashMap;
use std::time::Duration;
use std::{fs, thread};
use std::path::PathBuf;
use std::process::Command;
use directories::UserDirs;
use std::io::Write;
use crate::{box_controls, open_overwrite};
use crate::cli::{self, get_active_project};
use crate::project_controls;
use crate::Project;
use crate::configuration;
use crate::portscan_controls;
use crate::start_pentest;
#[derive(Default)]
struct CmdResult{
config_path: PathBuf,
output: String,
projects: Vec<Project>,
base_files: PathBuf,
base_notes: PathBuf,
tools_dir: PathBuf,
boxtemplate: String,
terminal: String,
cracking_rig: String,
rockyou: String,
rule: String,
upcoming_files: PathBuf,
upcoming_notes: PathBuf,
password_spray_file: PathBuf,
fingerprint: bool,
vault_name: String,
command_to_run: String,
initialized: bool,
active_project: String,
value_to_set: String,
setting_value: bool,
next_id: i32,
}
#[derive(Debug, Clone)]
enum Message {
Init,
ListProjects,
SwicthProject,
ManualCommand,
CommandInput(String),
UnknownCommand,
NewTerminal,
ClearCommand,
ProjectSelected(String),
ShowActiveProject,
ShowSettings,
CommandSelected(String),
ParseCsPortscan,
InputValue(String),
ClearValue,
PromoteProject,
}
impl CmdResult{
fn set_active_project(&mut self) -> Option<Project>{
let get_active_res = cli::get_active_project(&self.projects);
if get_active_res.is_none(){
self.output = String::from("Failed to get active projects!");
return None;
}
else{
return Some(get_active_res.unwrap().clone());
}
}
fn update(&mut self, message: Message){
let mut opt_active_project = None;
let mut settings = HashMap::new();
if self.initialized{
let acitve_res = self.set_active_project();
if acitve_res.is_some(){
opt_active_project = acitve_res;
}
settings = configuration::load_config(&self.config_path);
}
match message{
Message::Init => {
self.init(true);
}
Message::ShowSettings => {
let out_string = format!("
config_path = {}
base_files = {}
base_notes = {}
tools_dir = {}
boxtemplate = {}
cracking_rig = {}
rockyou = {}
rule = {}
upcoming_files = {}
upcoming_notes = {}
password_spray_file = {}
fingerprint = {}
vault_name = {}
initialized = {}
active_project = {}
", self.config_path.display(), self.base_files.display(), self.base_notes.display(), self.tools_dir.display(), self.boxtemplate, self.cracking_rig, self.rockyou, self.rule, self.upcoming_files.display(), self.upcoming_notes.display(), self.password_spray_file.display(), self.fingerprint, self.vault_name, self.initialized, self.active_project);
self.output.push_str(&out_string);
}
Message::ListProjects =>{
self.output.push_str(format!("\n{}", project_controls::list_projects(&self.projects, &false)).as_str());
}
Message::ShowActiveProject => {
for project in &self.projects{
let project_name = format!("{}:{}", project.customer, project.project_name);
if project_name == self.active_project{
self.output = format!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", project.customer ,project.project_name, project.boxname, project.files_folder.display(), project.notes_folder.display());
}
}
}
Message::ProjectSelected(project) => {
self.active_project = project;
let outline = format!("\nproject {} selected!", self.active_project);
self.output.push_str(&outline);
self.update(Message::SwicthProject);
}
Message::SwicthProject =>{
let mut out_string = String::from("Current Loaded Projects Config File\n");
let print_text = format!("\nswitching to {}", self.active_project);
self.output.push_str(&print_text);
for project in &mut self.projects{
let project_name = format!("{}:{}", project.customer, project.project_name);
let mut _outline = String::new();
if project_name == self.active_project {
_outline = format!("{}:{}:{}:{}:yes:{}:{}\n", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display(), project.boxname, project.stage);
project.active = true;
out_string.push_str(&_outline);
}
else {
_outline = format!("{}:{}:{}:{}:no:{}:{}\n", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display(), project.boxname, project.stage);
project.active = false;
out_string.push_str(&_outline);
}
}
let mut projects_path = self.config_path.clone();
projects_path.pop();
projects_path.push("projects.conf");
let projects_file_res = open_overwrite(&projects_path);
if projects_file_res.is_some(){
let mut projects_file = projects_file_res.unwrap();
let write_res = write!(projects_file, "{}", out_string);
if write_res.is_err(){
self.output.push_str("Error writing projects file!");
}
}
self.init(false);
}
Message::CommandInput(cmd) => {
self.command_to_run = cmd;
}
Message::CommandSelected(cmd) => {
self.command_to_run = cmd;
self.update(Message::ManualCommand);
}
Message::ClearCommand => {
self.command_to_run = String::from("");
}
Message::UnknownCommand => {
self.output.push_str("\n");
let words: Vec<&str> = self.command_to_run.split(" ").collect();
let command = words[0];
let mut new_cmd = Command::new(command);
for arg in words[1..].to_owned(){
new_cmd.arg(arg);
}
let cmd_rs = new_cmd.output();
if cmd_rs.is_err(){
self.output.push_str(format!("\n{} is an unknown command!", self.command_to_run).as_str());
return;
}
let output = cmd_rs.unwrap();
let success_out = output.stdout;
let fail_out = output.stderr;
if success_out.len() > 1{
self.output.push_str(format!("\n{}", String::from_utf8_lossy(&success_out).to_string()).as_str());
}
else if fail_out.len() > 0 {
self.output.push_str(format!("\n{}", String::from_utf8_lossy(&fail_out).to_string()).as_str());
}
else{
self.output.push_str(format!("\n{}", String::from("unknown tool or system command!")).as_str());
}
self.update(Message::ClearCommand);
}
Message::NewTerminal => {
self.output.push_str("\n");
self.output.push_str(format!("\n{}", String::from("launching termainl!")).as_str());
box_controls::project_standalone_terminal(opt_active_project.unwrap().clone(), self.terminal.clone(), &false);
}
Message::ManualCommand =>{
self.output.push_str("\n");
if self.setting_value{
match self.command_to_run.as_str(){
"new project" => {
if self.value_to_set.len() > 1{
let value_vec: Vec<&str> = self.value_to_set.split(" ").collect();
let client = String::from(value_vec[0]);
let project = String::from(value_vec[1]);
self.update(Message::ClearValue);
self.new_project(client, project);
self.setting_value = false;
self.update(Message::ClearCommand);
}
}
"promote project" => {
if self.value_to_set.len() > 1{
let id = self.value_to_set.clone();
self.update(Message::ClearCommand);
let settings = configuration::load_config(&self.config_path);
self.output.push_str("promoting project and setting up distrobox please wait...");
self.output.push_str("\nPlease follow terminal prompts");
self.output.push_str("\nNote this window will hang during distrobox creation.");
self.output.push_str("\nyour system may think it is not responding, just wait until the box createion is complete.");
self.view();
let (_handle, output) = cli::run_command(String::from("promote project"), &settings, &self.config_path, &mut self.projects, false, Some(id));
if output.is_some(){
self.output.push_str(&output.unwrap());
}
self.update(Message::ClearValue);
self.setting_value = false;
}
}
_ => self.update(Message::UnknownCommand),
}
}
else{
match self.command_to_run.as_str(){
"list projects" => {self.update(Message::ListProjects); self.update(Message::ClearCommand)},
"new terminal" => {self.update(Message::NewTerminal); self.update(Message::ClearCommand);},
"show active" => {self.update(Message::ShowActiveProject); self.update(Message::ClearCommand);},
"show settings" => {self.update(Message::ShowSettings); self.update(Message::ClearCommand);},
"initialize" => {self.init(true); self.update(Message::ClearCommand);},
"parse cs portscan" => {self.update(Message::ParseCsPortscan); self.update(Message::ClearCommand)},
"create new project" => {
self.setting_value = true;
self.output.push_str("Enter the client and project name, space separated:");
self.command_to_run = String::from("new project");
},
"promote project" => {
self.setting_value = true;
for project in &self.projects{
let select_line = format!("\n{}.) {} {}", project.id, project.customer, project.project_name);
self.output.push_str(&select_line);
self.command_to_run = String::from("promote project");
}
},
"recreate distrobox" => {
let (_handle, output) = cli::run_command(String::from("recreate distrobox"), &settings, &self.config_path, &mut self.projects, false, None);
if output.is_some(){
let outline = format!("\n{}", output.unwrap());
self.output.push_str(&outline);
}
self.output.push_str("Distrobox recreation successful!");
}
_ => self.update(Message::UnknownCommand),
};
if !self.setting_value {
self.update(Message::ClearCommand);
self.update(Message::ClearValue);
}
}
}
Message::ParseCsPortscan => {
self.output.push_str("\n");
let projec = opt_active_project.unwrap();
let open_file = FileDialog::new().set_directory(&projec.files_folder).pick_file();
let save_folder = FileDialog::new().set_directory(&projec.files_folder).pick_folder();
portscan_controls::parse_csportscan(&projec, open_file.clone(), save_folder.clone());
let out_string = format!("parsing cobalt strike port scan file: {}\nand saving to {}", open_file.unwrap().display(), save_folder.unwrap().display());
self.output.push_str(&out_string);
}
Message::InputValue(value) => {
self.value_to_set = value;
}
Message::ClearValue => {
self.value_to_set.clear();
}
Message::PromoteProject => {
let settings = configuration::load_config(&self.config_path);
let (handle, output) = cli::run_command(String::from("promote project"), &settings, &self.config_path, &mut self.projects, false, Some(self.value_to_set.clone()));
}
}
}
fn init(&mut self, display: bool){
let mut config_path = PathBuf::new();
let user_dirs_res = UserDirs::new();
if user_dirs_res.is_none(){
println!("oof couldn't get the config directory the right way, falling back to the stpuid way...");
let get_home_res = Command::new("echo").arg("$HOME").output();
if get_home_res.is_err(){
println!("ooof the stupid way didn't work... this is a bruh moment, gotta fix your environment variabls!!!");
return;
}
let get_home_output = get_home_res.unwrap().stdout;
let home_string = String::from_utf8_lossy(&get_home_output);
config_path.push(home_string.trim());
}
else{
let user_dirs = user_dirs_res.unwrap();
config_path.push(user_dirs.home_dir());
}
config_path.push(".config/pyro_pentest_tool/conf");
let settings = configuration::load_config(&config_path);
self.config_path = config_path.clone();
self.base_files = PathBuf::from(settings["project_files"].clone());
self.base_notes = PathBuf::from(settings["project_notes"].clone());
self.tools_dir = PathBuf::from(settings["tools_folder"].clone());
self.boxtemplate= settings["box_template"].clone();
self.terminal = settings["terminal_command"].clone();
self.cracking_rig = settings["cracking_rig"].clone();
self.rockyou = settings["rockyou"].clone();
self.rule = settings["rule"].clone();
self.upcoming_files = PathBuf::from(settings["upcoming_files"].clone());
self.upcoming_notes = PathBuf::from(settings["upcoming_notes"].clone());
self.password_spray_file = PathBuf::from(settings["pass_spray_file"].clone());
self.fingerprint = settings["fingerprint"].to_lowercase().contains("y");
self.vault_name = settings["vault_name"].clone();
self.projects = project_controls::get_projects(&config_path, false).unwrap();
self.setting_value = false;
self.initialized = true;
let active = get_active_project(&self.projects);
if active.is_some(){
let act_project = active.unwrap();
self.active_project = format!("{}:{}", act_project.customer, act_project.project_name);
}
self.next_id = 0;
for project in &self.projects{
let id = project.id.clone();
if id > self.next_id{
self.next_id = id;
self.next_id += 1;
}
}
let display_string = String::from("
*@@@##%@@@=
+@@#- =@@#
-@@@@@@# -@@%
:@@@@@@=%* -@@:
-@@@@%: #%*= +@@@@%- #@:
:@@@@@@@@#- %@@@@@=@@:#@:
%@ :@@%+%% =@@@@@@::@-%%:
%@@%%#+-:: %@@#- :#-=@#
:%@- :--+#@@@@%#=::--=: :@@+
#@= ---=- +@@
*@* @@+
=@# #@@:
:@@ =- -@@:
:@# =@-:@+ %@- :==:
:@+ #% *@- +@+ -@%::#@:
:@= @--@+ :@% :%@+ =@:
:@= +# %# *@+ *@#: -@:
:@= @-#@ #@#%@@@@@@@*- -@#: *%:
:@* =*=@: *@: *#: :*@@% +@#
@% -% +# :-=###*+#%: -@@+
+@= -+: :-% :====+*#@@%- -%@#:
:%% =#@-%@#%: : :@@# -@*
*@# :#+ ** #@* :###*
+@%: = =@% -@:
#@%: += -@#: %=
=: :@@%@#- :%- -@%+####-
-#=@- :@# :%#%@@@*-: -: +@%:
:@: *@@- ## :+%%@@@: ++=-::::=%@*
+* *@: +*+:#@+ +@:-+%@@%=
+#:*@- :@%#@@- @-
:%= *@= @=
*@= #*
=@@@+
LOADING SETTINGS...
");
if display{
self.output.push_str(&display_string);
self.update(Message::ShowSettings);
self.output.push_str("SETTINGS LOADED!");
}
}
fn view(&self) -> Column<Message>{
let mut project_name_vec = Vec::new();
for project in &self.projects{
let project_line = format!("{}:{}", project.customer, project.project_name);
project_name_vec.push(project_line);
}
let tool_commands = vec![
String::from("list projects"),
String::from("new terminal"),
String::from("show active"),
String::from("show settings"),
String::from("parse cs portscan"),
String::from("promote project"),
];
let command_list = pick_list(tool_commands, Some(&self.command_to_run), Message::CommandSelected);
let project_list = pick_list(project_name_vec, Some(&self.active_project), Message::ProjectSelected).placeholder("select the active project");
let intialize_button = button("Get Hacking☢").on_press(Message::Init);
let command_list_title = text("Select a command");
let output_box = scrollable(text(&self.output)).height(300).width(Fill).anchor_bottom();
let input_box = text_input::<_, Theme, Renderer>("Command to run", &self.command_to_run).on_input(Message::CommandInput).on_submit(Message::ManualCommand);
let value_input_box = text_input::<_, Theme, Renderer>("Command to run", &self.value_to_set).on_input(Message::InputValue).on_submit(Message::ManualCommand);
let project_list_title = text("Current Active Project");
let project_select_column = column![project_list_title, project_list];
let command_select_column = column![command_list_title, command_list];
if self.setting_value{
let interface = column![output_box, value_input_box].spacing(10).padding(10);
return interface;
}
let main_row = row![command_select_column, project_select_column].spacing(10).padding(10);
if self.initialized{
let interface = column![main_row, output_box, input_box].spacing(30);
return interface;
}
else{
let interface = column![center(intialize_button)];
return interface;
}
}
fn new_project(&mut self, client: String, project: String){
let out_string = format!("\nClient:{}\nProject:{}", client, project);
self.output.push_str(&out_string);
let customer_name = client;
let project_name = project;
let mut starting_project_files = self.upcoming_files.clone();
starting_project_files.push(&customer_name);
starting_project_files.push(&project_name);
let mut starting_notes_files = self.upcoming_notes.clone();
starting_notes_files.push(&customer_name);
starting_notes_files.push(&project_name);
fs::create_dir_all(&starting_project_files).expect("error creating directory! the file dialog will let you create it manually");
fs::create_dir_all(&starting_notes_files).expect("error creating notes directory! the file dialog will let you create it manually.");
thread::sleep(Duration::from_secs(2));
let selected_files = FileDialog::new().set_directory(starting_project_files.clone()).set_can_create_directories(true).set_title("Project Files Folder").pick_folder();
if selected_files.is_none(){
self.output = String::from("error picking files folder");
return;
}
let project_files = selected_files.unwrap();
if &project_files != &starting_project_files{
fs::remove_dir_all(&starting_project_files).expect("error removing default directory!");
starting_project_files.pop();
fs::remove_dir_all(&starting_project_files).expect("error removing default directory!");
}
let selected_notes = FileDialog::new().set_directory(starting_notes_files.clone()).set_can_create_directories(true).set_title("Project Notes Folder").pick_folder();
if selected_notes.is_none(){
self.output = String::from("error picking notes folder");
}
let project_notes = selected_notes.unwrap();
if &project_notes != &starting_notes_files{
fs::remove_dir_all(&starting_notes_files).expect("error removing default folder");
starting_notes_files.pop();
fs::remove_dir_all(&starting_notes_files).expect("error removing default folder!");
}
let project_boxname = format!("{}_{}", self.boxtemplate, customer_name);
let id = self.next_id.clone();
self.next_id += 1;
let new_prject = Project{customer:customer_name.clone(), project_name:project_name.clone(), notes_folder:project_notes.clone(), files_folder:project_files.clone(),active:false, boxname:project_boxname.clone(),stage:"upcoming".to_owned(), id};
if project_name.to_lowercase().contains("external"){
start_pentest::external(&self.password_spray_file, &new_prject);
}
else if project_name.to_lowercase().contains("internal"){
start_pentest::internal(&self.password_spray_file, &new_prject);
}
else if project_name.to_lowercase().contains("vishing"){
start_pentest::vishing(&new_prject);
}
self.projects.push(new_prject);
project_controls::save_projects(&self.projects, &self.config_path, &false);
println!("project created and saved to the projects config file!");
}
}
fn theme(_state: &CmdResult) -> Theme{
return Theme::Dark;
}
pub fn gui() -> iced::Result{
let app = iced::application("Pyro Pentest Tool", CmdResult::update, CmdResult::view);
let res = app.theme(theme).run();
return res;
}

View File

@@ -1,4 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::write;
use std::fs; use std::fs;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::fs::OpenOptions; use std::fs::OpenOptions;
@@ -14,6 +15,10 @@ use clearscreen::clear;
use clearscreen; use clearscreen;
use rodio::{Decoder, OutputStream, Sink}; use rodio::{Decoder, OutputStream, Sink};
use crate::get_user_input; use crate::get_user_input;
use crate::open_append;
use crate::print_error;
use crate::print_informational;
use crate::print_success;
use crate::Project; use crate::Project;
#[allow(unused)] #[allow(unused)]
@@ -928,4 +933,50 @@ pub fn get_scope_entries(project: &Project) -> Option<Vec<String>>{
return Some(hosts); return Some(hosts);
} }
pub fn parse_net_view(project: &Project){
let mut share_paths = Vec::new();
let mut note_path = project.notes_folder.clone();
let netview_output_path = PathBuf::from(get_user_input("path to the net view output file"));
let netview_read_res = read_to_string(netview_output_path);
if netview_read_res.is_err(){
print_error("error reading netview output file!", netview_read_res.err().unwrap().to_string());
return;
}
let netview_text = netview_read_res.unwrap();
let netview_sections: Vec<&str> = netview_text.split("shared resources at ").collect();
for section in netview_sections{
let mut server = String::new();
let lines: Vec<&str> = section.lines().collect();
for line in lines{
if line.contains("\\\\"){
server.push_str(line.trim());
}
else if line.contains("Disk"){
let share_name = line.split_whitespace().collect::<Vec<&str>>()[0];
let share_path = format!("{}\\{}", server, share_name);
share_paths.push(share_path);
}
}
}
print_success("data gathered!");
print_informational("writing notes");
note_path.push("initial enum.md");
let open_res = open_append(&note_path);
if open_res.is_none(){
print_error("error opening enum notes!", String::from("can't open file"));
return;
}
let mut note_file = open_res.unwrap();
let write_res = write!(note_file, "\n\n# Shares\n");
if write_res.is_err(){
print_error("error writing to note file!", write_res.err().unwrap().to_string());
return;
}
write_res.unwrap();
for share_path in share_paths{
write!(note_file, "- [ ] {}\n\n", share_path).unwrap();
}
print_success("shares parsed, and saved to initial enum in your obsidian vault!");
}

View File

@@ -222,7 +222,7 @@ vault_name:{}"
exit(1); exit(1);
} }
let mut project_conf_file = project_conf_res.unwrap(); let mut project_conf_file = project_conf_res.unwrap();
let project_write_res = write!(project_conf_file, "Projects Config File"); let project_write_res = write!(project_conf_file, "Projects Config File\ndefault:default:{}:{}:yes:{}:current", &current_notes.display(), &current_projects.display(), &template_box_name);
if project_write_res.is_err(){ if project_write_res.is_err(){
println!("error writing project config file."); println!("error writing project config file.");
exit(1); exit(1);

View File

@@ -1,12 +1,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::env::args;
use std::{io::stdin, path::PathBuf, process::Command}; use std::{io::stdin, path::PathBuf, process::Command};
use directories::UserDirs; use directories::UserDirs;
use std::process::exit; use std::process::exit;
use std::fs::{self, File}; use std::fs::{self, File};
use colored::Colorize; use colored::Colorize;
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct Project{ pub struct Project{
pub customer: String, pub customer: String,
pub project_name: String, pub project_name: String,
@@ -24,12 +23,13 @@ mod box_controls;
mod info_controls; mod info_controls;
mod start_pentest; mod start_pentest;
mod cli; mod cli;
mod menu;
mod portscan_controls; mod portscan_controls;
mod victim_commands; mod victim_commands;
mod enumeration; mod enumeration;
mod tool_controls; mod tool_controls;
mod configuration; mod configuration;
mod gui; mod exploit;
pub fn print_error(message: &str ,error: String){ pub fn print_error(message: &str ,error: String){
println!("{}", message.red()); println!("{}", message.red());
@@ -44,7 +44,7 @@ pub fn print_informational<T>(message: T) where T: AsRef<str>{
println!("{}", message.as_ref().custom_color((255,165,0))); println!("{}", message.as_ref().custom_color((255,165,0)));
} }
pub fn tableize(given_lines: Vec<String>, display: &bool) -> String{ pub fn tableize(given_lines: Vec<String>) {
let column_count = given_lines[0].split("||").collect::<Vec<&str>>().len(); let column_count = given_lines[0].split("||").collect::<Vec<&str>>().len();
// the following code just adds a junk line in at index 1 because that gets eaten for some reason... // the following code just adds a junk line in at index 1 because that gets eaten for some reason...
// I want to try to figure out why its getten eaten, but just needed to get it working for now. // I want to try to figure out why its getten eaten, but just needed to get it working for now.
@@ -76,25 +76,18 @@ pub fn tableize(given_lines: Vec<String>, display: &bool) -> String{
} }
current_cell += 1; current_cell += 1;
} }
if *display{
let longest_line = (column_count*2) - 1; let longest_line = (column_count*2) - 1;
if longest_line > terminal_width{ if longest_line > terminal_width{
let difference = longest_line - terminal_width - 3; let difference = longest_line - terminal_width - 3;
column_sizes.insert(longest_column, column_sizes[&longest_column] - difference); column_sizes.insert(longest_column, column_sizes[&longest_column] - difference);
} }
}
} }
let mut header = String::new(); let mut header = String::new();
let mut outdata = String::new(); let mut outdata = String::new();
let mut count = 0; let mut count = 0;
let mut separater = String::new(); let mut separater = String::new();
let mut ending = String::new(); let ending = format!("{}\n", "|".green());
if *display{
ending = format!("{}\n", "|".green());
}
else{
ending = format!("{}\n", "|");
}
for line in lines{ for line in lines{
count += 1; count += 1;
//println!("{}", line); //println!("{}", line);
@@ -105,49 +98,29 @@ pub fn tableize(given_lines: Vec<String>, display: &bool) -> String{
for column in column_numbers{ for column in column_numbers{
let mut data_to_add = String::new(); let mut data_to_add = String::new();
let mut data_vec_len = data_vec[*column].len(); let mut data_vec_len = data_vec[*column].len();
if *display{ if data_vec_len > column_sizes[&longest_column]{
if data_vec_len > column_sizes[&longest_column]{ while data_vec_len > column_sizes[&longest_column]{
while data_vec_len > column_sizes[&longest_column]{ data_vec_len = data_vec_len / 2;
data_vec_len = data_vec_len / 2; let (data_vec_start, data_vec_end) = data_vec[*column].split_at(data_vec_len);
let (data_vec_start, data_vec_end) = data_vec[*column].split_at(data_vec_len); data_to_add = format!("{}\n{}", data_vec_start, data_vec_end);
data_to_add = format!("{}\n{}", data_vec_start, data_vec_end);
}
} }
} }
else{ else{
data_to_add = String::from(data_vec[*column]); data_to_add = String::from(data_vec[*column]);
} }
let padding = column_sizes[column] - data_vec_len; let padding = column_sizes[column] - data_vec_len;
if *display{ if count == 1{
if count == 1{ let formatted_cell = format!("{} {}{}", "|".green(), data_vec[*column].bold().green(), " ".repeat(padding));
let formatted_cell = format!("{} {}{}", "|".green(), data_vec[*column].bold().green(), " ".repeat(padding)); header.push_str(&formatted_cell);
header.push_str(&formatted_cell);
}
else if count == 2 {
let formatted_cell = format!("{} {} ", "|".green(), "-".repeat(column_sizes[column] - 1).green());
separater.push_str(&formatted_cell);
}
else {
let formatted_cell = format!("{} {}{}", "|".green(), data_to_add, " ".repeat(padding));
outdata.push_str(&formatted_cell);
add_ending = true;
}
} }
else{ else if count == 2 {
println!("no display"); let formatted_cell = format!("{} {} ", "|".green(), "-".repeat(column_sizes[column] - 1).green());
if count == 1{ separater.push_str(&formatted_cell);
let formatted_cell = format!("{} {}{}", "|", data_vec[*column], " ".repeat(padding)); }
header.push_str(&formatted_cell); else {
} let formatted_cell = format!("{} {}{}", "|".green(), data_to_add, " ".repeat(padding));
else if count == 2 { outdata.push_str(&formatted_cell);
let formatted_cell = format!("{} {} ", "|", "-".repeat(column_sizes[column] - 1)); add_ending = true;
separater.push_str(&formatted_cell);
}
else {
let formatted_cell = format!("{} {}{}", "|", data_to_add, " ".repeat(padding));
outdata.push_str(&formatted_cell);
add_ending = true;
}
} }
} }
if add_ending{ if add_ending{
@@ -157,7 +130,7 @@ pub fn tableize(given_lines: Vec<String>, display: &bool) -> String{
outdata.push_str(&separater); outdata.push_str(&separater);
outdata.push_str(&ending); outdata.push_str(&ending);
let print_output = format!("{}{}{}{}{}", header, ending, separater, ending, outdata); let print_output = format!("{}{}{}{}{}", header, ending, separater, ending, outdata);
return print_output; println!("{}", print_output);
} }
pub fn open_overwrite(path: &PathBuf) -> Option<File>{ pub fn open_overwrite(path: &PathBuf) -> Option<File>{
@@ -260,25 +233,6 @@ fn main() {
return; return;
} }
let mut projects = projects_res.unwrap(); let mut projects = projects_res.unwrap();
let help_text = format!(" let _continue = get_user_input("press enter to load Command Line Interface");
pentest_tool -> launch cli cli::cli(&mut projects, &config_path);
pentest_tool gui -> launch gui
pentest_tool anything else -> display this help
");
let args: Vec<String> = args().collect();
if args.len() == 1{
cli::cli(&mut projects, &config_path);
}
else if args[1] == String::from("gui"){
let res = gui::gui();
if res.is_err(){
print_error("error lanching gui!", res.err().unwrap().to_string());
}
else{
res.unwrap();
}
}
else {
println!("{}", help_text);
}
} }

296
pentest_tool/src/menu.rs Normal file
View File

@@ -0,0 +1,296 @@
use std::path::PathBuf;
use std::thread::JoinHandle;
use std::collections::HashMap;
use clearscreen::clear;
use clearscreen;
use colored::Colorize;
use crate::get_user_input;
use crate::Project;
use crate::cli;
pub fn main_menu(given_projects: &mut Vec<Project>,
config_path: PathBuf,
settings: &HashMap<&str, String>
) -> Option<Vec<JoinHandle<()>>>{
let mut loopize = true;
let mut threads = Vec::new();
let mut projects = given_projects.clone();
let banner = "
,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,''''
,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,''
,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,'
,;;:::c::ccc::cc::::::::cclollllllolllllccccc::cc:::::;;;;;;;;;;;;;;;;;;,,,,,,,,,,'''''''''''..'',,,
,;::::::ccc::cc::::::ccloodollooooollllcccccc:llc::::::;;;;;;:;;;;;;;;;;;,,,,,,,,,,''''''''''''''',,
,;:::::c:::c::::ccccloddxxddxxddddodollllccclclcccccc:::::::::::::::;;;;;;;;,,,,,,,,,'''''''''''''',
;;:::::::c::c::clllodxxO0OKX0kkOkkxxxxxdooooolcccccccc:::::::cllc::::::::;;;;;,,,,,,,,,,'''''''''',,
;:::::c:cc::cclolclokO0KXNNX00KKK0O0KOxdxxdooccccclllccccccccdkdlcccccllcc::;;;;;;;;,,,,,,,,,,,',,,,
::::::cc::::coxdlllok00KNWNXXX0KXKOKNOkO0kddocccllllllccccclx0Kkodddoodddoollc::;;;;;;;;;,,,,,,,,,,,
:::::::c:::clkkodooxxkO0KX0xookKKkkKNKO0KkdoodolcllllollolldKNNXKKXKKKKKK0Okxdocc:cc:::;;;;;,,,,,,,,
::cc::cc::cldxllolodxxdoddc'.,okkxOXXOdxkxolkOdlllllllldkdokXNNNNNNNNX0kxollcc:::::cclc::;;;;;;,,,,,
:::::::cccldko:,.';cc:;:;....;clllOXOxxOkocoK0xooddollx0Odd0XNNNNNX0Oxdolcccc::;;;;;;:cllc:;;:;,,,,,
;;::c:::ccldkl;'...,''''....',;,';dxdkkdc;cONKxxOOOxddOXOdx0XXNNWNOdddxkOOOOkdllc:;,,,;cool:;;;;;,,;
,;;::;;::llco:,'..''..,.......''.';:ldl;,,:xXNOOXXX0xdkOOddkXNNWWWX00KXNNX0kxddddol:,''';lol:;;:;;,;
,,,;;;;;:coc;;'..;;. .,,;'.......':dxdc;ldc,l00xkXNKxodkkkkk0XNWWMWWWNXKOxdooolooool:;'..,lol::::;;;
',,,;;;;:cllc;,..',. ','. .....;odoo:;co:.'ldldOOx::x0KXX0kk0XNWWWXOxdoooollllllllcc:'..':lc:::;;;
',,,;;;;;:cccc:,. . ..;cccccc:,,''.',,:l:;;:oOXXKOOOkxOXNNNXOxddooooollllllllc,....:c:::;;;
''',,,;;;;;;;cll,.. .. .':lc:c:;,,......,,;:;;:cokkxxO00O0KXNNN0kxkkkxddoollllllll:'...':::::::
.''',,,,,,,,,;:c:,.. ..'. ..','',;;'........',,;:;:::cdxxxddkKXXXKKKKXXXXXX0kdoloolllol;....,;:::::
..'''',,'',,,;;:::;..... ............... .'.....,;,',:ldc;:ldOKKK00KNWWWNNXK0xoooodooooo:'...';;;:;;
....'''''',,;;::cll:,''...... . ..........'...,;;l:,,;oddkOOKNWWWWNX0kdodxxxxdddooc,...',;;;;,
......''''',;::cloodddol;. ...........',.;;,,',:cxdd0KXXKKKXKOkxxkkkxdddooc,...';;,,,,
........''',;:clloddxxdo:'. .. ...........''.'',;c:;cccodddk0KX0OOkxddddddo:...';;;;,,'
..........',;:cclodxxkxdl:,.. ... ......'....'..':c,..'.,c,,,.,cxkO00Okxdddddc'..';:;;;,,'
..........',;;:cloodxkkkdol:'. . ... ...... ......';c'.'...:;',;,'..,lxO00Oxxxo:'...,::;;,,,,
...........',;;:clodxkOOkxdol;. .. .. ... ....',::'.''.',.........'oxdxxxdl;...';::;;;,,''
............',;:clodxkkOOOxddo;. ...... ........',,',................';:clc;,...';::;;,,,'''
............',;:cldxkkOkkkxdddo;. ..... .........,'...........'''','.',,'''....,cc:;;,,'''..
.............';:cldxxkkkkxddddxl,. .... .;c;'...................',;;cc;'...';clolc:;,,'''...
............'';clodxkkkkkxddddddl' ... .:lc;'................. ....',,''';lxkxdlc:;,'''....
........',,;:;coddxkOOOOOkxxddddd:. ... ..,''.................. . ..;cdkkkkxoc:;,'''.....
......',;::cllodxkkOOOOOOkxxxddddc. ... ..,;,'................... .. .':odO0Okdl:;,'''......
.....',;:cloddxxkOOOOOOOkkxxdoooo;. .. ......................... .';cokOOxlc:;,''.......
....,;:clodxxkkOOOkO0OOOOxdlcc;;,...... .';,................. ...',:ldxxxdlc;,''.......
...,:clodooxkkkO0OxO00OOxo:;;,. ........ .''.......... .. .. ..,,,;:codxxdlc:;,'.......
'',;clodolokOkxkOkkO00Oko:;;;. ..... .. .,,........'. .. .. .. ..........;:codocclc:,,'......
";
while loopize {
let _enter_to_clear = get_user_input("press enter to display main menu.");
clear().expect("error clearing screen");
print!("
{}
{}
\n", banner.custom_color((255,165,0)), "
___ ___ _ ___ ___
| \\/ | (_) | \\/ | _
| . . | __ _ _ _ __ | . . | ___ _ __ _ _(_)
| |\\/| |/ _` | | '_ \\ | |\\/| |/ _ \\ '_ \\| | | |
| | | | (_| | | | | | | | | | __/ | | | |_| |_
\\_| |_/\\__,_|_|_| |_| \\_| |_/\\___|_| |_|\\__,_(_)
1 .) Show Active Project
2 .) List Projects
3 .) Switch Active Project
4 .) create new project with Pyro's default layout
5 .) Save Project Information
6 .) Import New Project to Current projects list - and setup new Distrobox
7 .) Remove Project
8 .) Print upcoming projects
9. ) promote project from upcoming to current
10.) Open A New Terminal in Current Active Project
11.) Open A Terminal In this windows for the current active project
12.) open current project's cobalt strike
13.) re-create the distrobox for the current active project
14.) generate userpass file from your obsidian notes
15.) run pyro's initail enum script on a nessus csv for the current project
16.) build external attack notes from host notes
17.) Build host discovery cmd command from scope in notes
18.) build portscan command from scope in notes
19.) parse a cs portscan services.tsv file
20.) Stop All Distroboxes
21.) Password Spray (will print password to spray, and wait the obervation window time)
22.) Launch bloodhound with the current project's distrobox
23.) Parse GatherContacts output file
24.) prune unused distroboxes (free up system storage)
25.) Gather DNS Records
26.) Bruteforce Subdomains
27.) Do all DNS enumeration
28.) enter external only menu
29.) enter internal only menu
30.) exit menu
".custom_color((255,165,0)));
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"2" => {let thread_option = cli::run_command("list &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"3" => {let thread_option = cli::run_command("switch project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"5" => {let thread_option = cli::run_command("save &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"6" => {let thread_option = cli::run_command("import project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"7" => {let thread_option = cli::run_command("remove project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"8" => {let thread_option = cli::run_command("show upcoming &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"9" => {let thread_option = cli::run_command("promote project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"10" => {let thread_option = cli::run_command("new terminal".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"15" => {let thread_option = cli::run_command("initial enum".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"16" => {let thread_option = cli::run_command("build attack notes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"17" => {let thread_option = cli::run_command("host discovery".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"18" => {let thread_option = cli::run_command("port scan".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"19" => {let thread_option = cli::run_command("parse port scan".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"20" => {let thread_option = cli::run_command("stop boxes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"21" => {let thread_option = cli::run_command("password spray".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"22" => {let thread_option = cli::run_command("bloodhound".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"23" => {let thread_option = cli::run_command("parse gather contacts".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"24" => {let thread_option = cli::run_command("prune distroboxes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"25" => {let thread_option = cli::run_command("dns records".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"26" => {let thread_option = cli::run_command("brute force subdomains".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"27" => {let thread_option = cli::run_command("dns enumeration".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"28" => {let threads_option = external_menu(banner, &mut projects, config_path.clone(), settings); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread);}}},
"29" => {let threads_option = internal_menu(banner, &mut projects, config_path.clone(), settings); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread);}}},
"30" => loopize = false,
_ => println!("{}","unknown selection, try again!".red()),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
pub fn external_menu(
banner: &str,
mut projects: &mut Vec<Project>,
config_path: PathBuf,
settings: &HashMap<&str, String>
) -> Option<Vec<JoinHandle<()>>>{
let mut loopize = true;
let mut threads = Vec::new();
while loopize {
let _enter_to_clear = get_user_input("press enter to display external project menu.");
clear().expect("error clearing screen");
print!("
{}
{}
\n", banner.custom_color((255,165,0)), "
_____ _ _ ___ ___
| ___| | | | | | \\/ | _
| |____ _| |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
| __\\ \\/ / __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
| |___> <| || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
\\____/_/\\_\\\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
1 .) Show Active Project
2 .) List Projects
3 .) Switch Active Project
4 .) create new project with Pyro's default layout
5 .) Save Project Information
6 .) Import New Project to Current projects list - and setup new Distrobox
7 .) Remove Project
8 .) Print upcoming projects
9. ) promote project from upcoming to current
10.) Open A New Terminal in Current Active Project
11.) Open A Terminal In this windows for the current active project
12.) re-create the distrobox for the current active project
13.) generate userpass file from your obsidian notes
14.) run pyro's initail enum script on a nessus csv for the current project
15.) build external attack notes from host notes
16.) Stop All Distroboxes
17.) Password Spray (will print password to spray, and wait the obervation window time)
18.) Parse GatherContacts output file
19.) prune unused distroboxes (free up system storage)
20.) Gather DNS Records
21.) Brute force Subdomains
22.) Do all DNS Enumeration
23.) exit menu
".custom_color((255,165,0)));
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
"2" => {let thread_option = cli::run_command("list projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"3" => {let thread_option = cli::run_command("switch project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"5" => {let thread_option = cli::run_command("save projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"6" => {let thread_option = cli::run_command("import project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"7" => {let thread_option = cli::run_command("remove project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"9" => {let thread_option = cli::run_command("promote project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"10" => {let thread_option = cli::run_command("new terminal".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"12" => {let thread_option = cli::run_command("recreate distrobox".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"13" => {let thread_option = cli::run_command("generate userpass".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"14" => {let thread_option = cli::run_command("initial enum".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"15" => {let thread_option = cli::run_command("build attack notes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"26" => {let thread_option = cli::run_command("stop boxes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"17" => {let thread_option = cli::run_command("password spray".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"18" => {let thread_option = cli::run_command("parse gather contacts".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"19" => {let thread_option = cli::run_command("prune distroboxes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"20" => {let thread_option = cli::run_command("dns records".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"21" => {let thread_option = cli::run_command("brute force subdomains".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"22" => {let thread_option = cli::run_command("dns enumeration".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
"23" => loopize = false,
_ => println!("{}", "unknown selection, try again!".red()),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
}
pub fn internal_menu(
banner: &str,
mut projects: &mut Vec<Project>,
config_path: PathBuf,
settings: &HashMap<&str, String>) -> Option<Vec<JoinHandle<()>>>{
let mut loopize = true;
let mut threads = Vec::new();
while loopize {
let _enter_to_clear = get_user_input("press enter to display internal project menu.");
clear().expect("error clearing screen");
print!("
{}
{}
\n", banner.custom_color((255,165,0)), "
_____ _ _ ___ ___
|_ _| | | | | | \\/ | _
| | _ __ | |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
| || '_ \\| __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
_| || | | | || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
\\___/_| |_|\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
1 .) Show Active Project
2 .) List Projects
3 .) Switch Active Project
4 .) create new project with Pyro's default layout
5 .) Save Project Information
6 .) Import New Project to Current projects list - and setup new Distrobox
7 .) Remove Project
8 .) Print upcoming projects
9. ) promote project from upcoming to current
10.) Open A New Terminal in Current Active Project
11.) Open A Terminal In this windows for the current active project
12.) open cobalt strike in the current project's distrobox
13.) re-create the distrobox for the current active project
14.) generate userpass file from your obsidian notes
15.) print host discvoery command for internal pingsweep
16.) print cobalt strike portscan command to include all in scope ranges
17) parse a cobalt strike portscan CSV
18.) Stop All Distroboxes
19.) Password Spray (will print password to spray, and wait the obervation window time)
20.) open bloodhound in the current project's distrobox
21.) prune unused distroboxes (free up system storage)
22.) exit menu
".custom_color((255,165,0)));
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"2" => {let thread_option = cli::run_command("list projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"3" => {let thread_option = cli::run_command("switch project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"5" => {let thread_option = cli::run_command("save projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"6" => {let thread_option = cli::run_command("import project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"7" => {let thread_option = cli::run_command("remove project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"9" => {let thread_option = cli::run_command("promote project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"10" => {let thread_option = cli::run_command("new terminal".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"15" => {let thread_option = cli::run_command("host discovery".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"16" => {let thread_option = cli::run_command("port scan".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"18" => {let thread_option = cli::run_command("stop boxes".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"19" => {let thread_option = cli::run_command("password spray".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"20" => {let thread_option = cli::run_command("bloodhound".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"21" => {let thread_option = cli::run_command("prune distroboxes".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
"22" => loopize = false,
_ => println!("{}", "unknown selection, try again!".red()),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
}
}

View File

@@ -1,5 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::{default, fs}; use std::fs;
use std::fs::{read_to_string, create_dir_all}; use std::fs::{read_to_string, create_dir_all};
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
@@ -238,33 +238,12 @@ pub fn build_cmd_for_host_discovery(project: &Project){
print_success(final_command); print_success(final_command);
} }
pub fn parse_csportscan(project: &Project, given_tsv_path: Option<PathBuf>, given_save_path: Option<PathBuf>){ pub fn parse_csportscan(project: &Project){
let mut tsv_path = PathBuf::new(); let mut tsv_path = project.files_folder.clone();
let mut outfile = PathBuf::new(); tsv_path.push("working/tsvs/services.tsv");
if given_tsv_path.is_none(){ let mut outfile = tsv_path.clone();
let mut tsv_path = project.files_folder.clone(); outfile.pop();
if !get_user_input("do you have the tsv saved in the project folder under working/tsvs/services.tsv?").to_lowercase().contains("y"){ outfile.pop();
tsv_path.clear();
tsv_path.push(get_user_input("ooof ok, please enter the full path to your tsv file."));
}
tsv_path.push("working/tsvs/services.tsv");
}
else{
tsv_path = given_tsv_path.unwrap();
}
if given_save_path.is_none(){
let mut outfile = tsv_path.clone();
outfile.pop();
outfile.pop();
println!("is {} where you want to save your files?", outfile.display());
if get_user_input("").to_lowercase().contains("n"){
outfile.clear();
outfile.push(get_user_input("ok, please enter the full path to the folder you want to save them to."));
}
}
else{
outfile = given_save_path.unwrap();
}
let mut windows_hosts = Vec::new(); let mut windows_hosts = Vec::new();
let mut ssh_hosts = Vec::new(); let mut ssh_hosts = Vec::new();
let mut ftp_hosts = Vec::new(); let mut ftp_hosts = Vec::new();
@@ -274,6 +253,11 @@ pub fn parse_csportscan(project: &Project, given_tsv_path: Option<PathBuf>, give
let mut web_hosts = Vec::new(); let mut web_hosts = Vec::new();
let mut telnet_hosts = Vec::new(); let mut telnet_hosts = Vec::new();
let mut unknown_ports = Vec::new(); let mut unknown_ports = Vec::new();
if !get_user_input("do you have the tsv saved in the project folder under working/tsvs/services.tsv?").to_lowercase().contains("y"){
tsv_path.clear();
tsv_path.push(get_user_input("ooof ok, please enter the full path to your tsv file."));
}
let tsv_read_res = read_to_string(tsv_path); let tsv_read_res = read_to_string(tsv_path);
if tsv_read_res.is_err(){ if tsv_read_res.is_err(){
let error = tsv_read_res.err().unwrap(); let error = tsv_read_res.err().unwrap();
@@ -329,6 +313,11 @@ pub fn parse_csportscan(project: &Project, given_tsv_path: Option<PathBuf>, give
} }
} }
} }
println!("is {} where you want to save your files?", outfile.display());
if get_user_input("").to_lowercase().contains("n"){
outfile.clear();
outfile.push(get_user_input("ok, please enter the full path to the folder you want to save them to."));
}
let host_number_results = format!(" let host_number_results = format!("
{} Windows hosts found! {} Windows hosts found!
{} SSH hosts found! {} SSH hosts found!

View File

@@ -21,7 +21,8 @@ use crate::box_controls::make_box;
use crate::print_success; use crate::print_success;
use crate::print_error; use crate::print_error;
pub fn switch_project(projects: &mut Vec<Project>){ pub fn
switch_project(projects: &mut Vec<Project>){
for project in projects.clone(){ for project in projects.clone(){
if project.active == false{ if project.active == false{
println!("{} {}|{}", project.id, project.customer, project.project_name); println!("{} {}|{}", project.id, project.customer, project.project_name);
@@ -52,7 +53,7 @@ pub fn switch_project(projects: &mut Vec<Project>){
} }
pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf, display: &bool) -> Option<String>{ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
let mut save_file_path = config_path.clone(); let mut save_file_path = config_path.clone();
let mut active_set = false; let mut active_set = false;
save_file_path.pop(); save_file_path.pop();
@@ -60,13 +61,8 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf, display: &b
let save_file_res = fs::File::create(save_file_path); let save_file_res = fs::File::create(save_file_path);
if save_file_res.is_err(){ if save_file_res.is_err(){
let error = save_file_res.err().unwrap().to_string(); let error = save_file_res.err().unwrap().to_string();
if *display{ print_error("error creating save file.", error);
print_error("error creating save file.", error); return;
}
else{
return Some(format!("Error saving file! {}", error));
}
return None;
} }
let mut save_file = save_file_res.unwrap(); let mut save_file = save_file_res.unwrap();
save_file.write_all(b"Current Loaded Projects Config File\n").expect("error writing first line to file"); save_file.write_all(b"Current Loaded Projects Config File\n").expect("error writing first line to file");
@@ -86,21 +82,15 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf, display: &b
let write_res = save_file.write_all(_outline.as_bytes()); let write_res = save_file.write_all(_outline.as_bytes());
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap().to_string(); let error = write_res.err().unwrap().to_string();
if *display{ print_error("error saving projects.conf file!", error);
print_error("error saving projects.conf file!", error); return;
}
else{
return Some(format!("error saving projects! {}", error));
}
return None;
} }
write_res.unwrap(); write_res.unwrap();
} }
return None;
} }
#[allow(unused)] #[allow(unused)]
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool, terminal: Option<String>, display: &bool){ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool){
let mut new_project_dir = PathBuf::new(); let mut new_project_dir = PathBuf::new();
let mut new_note_dir = PathBuf::new(); let mut new_note_dir = PathBuf::new();
let mut existing_folders = String::new(); let mut existing_folders = String::new();
@@ -261,26 +251,21 @@ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir
stage: project_stage.to_owned() stage: project_stage.to_owned()
}; };
if project_stage.contains("current"){ if project_stage.contains("current"){
make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint, terminal, display); make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint);
} }
projects.push(new_project); projects.push(new_project);
save_projects(projects, config_path, &true); save_projects(projects, config_path);
} }
pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf, given_id: Option<String>){ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
for project in projects.clone(){
println!("{} {} {}", project.id, project.customer, project.project_name);
}
let mut project_to_remove = String::new(); let mut project_to_remove = String::new();
if given_id.is_none(){ println!("project to remove?");
for project in projects.clone(){ std::io::stdin().read_line(&mut project_to_remove).unwrap();
println!("{} {} {}", project.id, project.customer, project.project_name);
}
println!("project to remove?");
std::io::stdin().read_line(&mut project_to_remove).unwrap();
}
else{
project_to_remove = given_id.unwrap();
}
if project_to_remove.len() > 1{ if project_to_remove.len() > 1{
let mut project_to_keep = Vec::new(); let mut project_to_keep = Vec::new();
if project_to_remove.len() > 0{ if project_to_remove.len() > 0{
@@ -311,7 +296,7 @@ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf, given_
if project_set{ if project_set{
projects.clear(); projects.clear();
projects.append(&mut project_to_keep); projects.append(&mut project_to_keep);
save_projects(&projects, config_path, &true); save_projects(&projects, config_path);
} }
else{ else{
println!("error no prjects found to remove") println!("error no prjects found to remove")
@@ -393,7 +378,7 @@ pub fn get_projects(config_path: &PathBuf, show: bool) -> Option<Vec<Project>>{
return Some(projects) return Some(projects)
} }
pub fn print_upcoming_projects(projects: &Vec<Project>, display: &bool) -> Option<String>{ pub fn print_upcoming_projects(projects: &Vec<Project>){
let mut lines = vec![String::from("CUSTOMER||PROJECT")]; let mut lines = vec![String::from("CUSTOMER||PROJECT")];
for project in projects{ for project in projects{
if project.stage.contains("upcoming"){ if project.stage.contains("upcoming"){
@@ -401,38 +386,24 @@ pub fn print_upcoming_projects(projects: &Vec<Project>, display: &bool) -> Optio
lines.push(new_line); lines.push(new_line);
} }
} }
let return_string = tableize(lines, &false); tableize(lines);
if *display{
println!("{}", return_string);
return None;
}
else{
return Some(return_string);
}
} }
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool, given_data: Option<String>, terminal:String) -> Option<String>{ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool){
let working_projects = projects.clone(); let working_projects = projects.clone();
let display = given_data.is_none(); for project in &working_projects{
let mut return_data = String::new(); if project.stage.contains("upcoming"){
println!("{}.) {}:{}", project.id, project.customer, project.project_name);
}
}
println!("which project to promote?");
let mut selection = String::new(); let mut selection = String::new();
if display{ let result = stdin().read_line(&mut selection);
for project in &working_projects{ if result.is_err(){
if project.stage.contains("upcoming"){ println!("we need input here dummy try again....");
println!("{}.) {}:{}", project.id, project.customer, project.project_name);
}
}
println!("which project to promote?");
let result = stdin().read_line(&mut selection);
if result.is_err(){
println!("we need input here dummy try again....");
}
result.unwrap();
println!("{}", project_dir.display());
}
else{
selection = given_data.unwrap();
} }
result.unwrap();
println!("{}", project_dir.display());
let promote_id: i32 = selection.trim_end().parse().unwrap(); let promote_id: i32 = selection.trim_end().parse().unwrap();
let mut projects_to_save = Vec::new(); let mut projects_to_save = Vec::new();
for project in &working_projects{ for project in &working_projects{
@@ -455,87 +426,61 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
.arg(&new_notes_dir.display().to_string()) .arg(&new_notes_dir.display().to_string())
.status().expect("unable to call the system mv command"); .status().expect("unable to call the system mv command");
if folder_move_success.success(){ if folder_move_success.success(){
if display{ println!("we copied the project folder correctly!!");
println!("we copied the project folder correctly!!");
}
else{
return_data.push_str("we copied the project folder correctly!!");
}
let mut remove_folder = PathBuf::new(); let mut remove_folder = PathBuf::new();
remove_folder.push(&project.files_folder); remove_folder.push(&project.files_folder);
remove_folder.pop(); remove_folder.pop();
let remove_files_res = fs::remove_dir_all(remove_folder); let remove_files_res = fs::remove_dir_all(remove_folder);
if remove_files_res.is_err(){ if remove_files_res.is_err(){
if display{ println!("error removing the original files folder form the upcomming folder, manual cleanup required");
println!("error removing the original files folder form the upcomming folder, manual cleanup required");
}
else{
return_data.push_str("\nerror removing the original files folder form the upcomming folder, manual cleanup required");
}
} }
else{ else{
remove_files_res.unwrap(); remove_files_res.unwrap();
if display{ println!("upcoming files folder cleanup successful!");
println!("upcoming files folder cleanup successful!");
}
else{
return_data.push_str("\nupcoming files folder cleanup successful!");
}
} }
} }
else{ else{
if display{ println!("failed to copy the project folder, try to move it manually!");
println!("failed to copy the project folder, try to move it manually!");
}
else{
return_data.push_str("\nfailed to copy the project folder, try to move it manually!");
}
} }
if note_move_success.success(){ if note_move_success.success(){
if display{
print_success("we copied the notes folder correctly!!");;
}
else{
return_data.push_str("\nwe copied the notes folder correctly!!");
}
print_success("we copied the notes folder correctly!!"); print_success("we copied the notes folder correctly!!");
let mut remove_folder = PathBuf::new(); let mut remove_folder = PathBuf::new();
remove_folder.push(&project.files_folder); remove_folder.push(&project.files_folder);
remove_folder.pop(); remove_folder.pop();
let remove_notes_res = fs::remove_dir_all(remove_folder); let remove_notes_res = fs::remove_dir_all(remove_folder);
if remove_notes_res.is_err(){ if remove_notes_res.is_err(){
if display{ println!("error removing the original notes folder form the upcomming folder, manual cleanup required");
println!("error removing the original notes folder form the upcomming folder, manual cleanup required");
}
else{
return_data.push_str("\nerror removing the original notes folder form the upcomming folder, manual cleanup required");
}
} }
else{ else{
remove_notes_res.unwrap(); remove_notes_res.unwrap();
if display{ println!("upcoming notes folder cleanup successful!");
println!("upcoming notes folder cleanup successful!");
}
else{
return_data.push_str("\nupcoming notes folder cleanup successful!");
}
} }
} }
else{ else{
if display{ println!("failed to copy the notes folder, try to move it manually!");
println!("failed to copy the notes folder, try to move it manually!");
}
else{
return_data.push_str("\nfailed to copy the notes folder, try to move it manually!");
}
} }
new_files_dir.push(&promoted_project.project_name); new_files_dir.push(&promoted_project.project_name);
new_notes_dir.push(&promoted_project.project_name); new_notes_dir.push(&promoted_project.project_name);
promoted_project.files_folder = new_files_dir; promoted_project.files_folder = new_files_dir;
promoted_project.notes_folder = new_notes_dir; promoted_project.notes_folder = new_notes_dir;
promoted_project.stage = "current".to_owned(); promoted_project.stage = "current".to_owned();
let cs_response = get_user_input("will you need to be using cobalt strike for this project?");
if cs_response.to_lowercase().contains("y"){
let cs_path = get_user_input("path to your current cobalt strike directory?");
let copy_result = Command::new("cp").arg("-R").arg(&cs_path).arg(&promoted_project.files_folder).status();
if copy_result.is_err(){
println!("oof we had an error copying... you'll have to copy this manually");
}
else{
let copy_exit = copy_result.unwrap();
if copy_exit.success() == false{
println!("oof we had an error copying... you'll have to copy this manually");
println!("run cp -R {} {}", &cs_path, &promoted_project.files_folder.display());
}
}
}
thread::sleep(Duration::from_secs(3)); thread::sleep(Duration::from_secs(3));
make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint, Some(terminal.clone()), &display); make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint);
projects_to_save.push(promoted_project); projects_to_save.push(promoted_project);
} }
else{ else{
@@ -544,25 +489,17 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
} }
projects.clear(); projects.clear();
projects.append(&mut projects_to_save); projects.append(&mut projects_to_save);
save_projects(&projects_to_save, config_path, &display); save_projects(&projects_to_save, config_path);
if display{ print_success("project promoted successfully!");
print_success("project promoted successfully!");
return None;
}
else{
return_data.push_str("\nproject promoted successfully!");
return Some(return_data);
}
} }
pub fn list_projects(projects: &Vec<Project>, display: &bool) -> String{ pub fn list_projects(projects: &Vec<Project>){
let mut lines = vec!["customer||project||stage".to_owned()]; let mut lines = vec!["customer||project||stage".to_owned()];
for project in projects{ for project in projects{
let new_line = format!("{}||{}||{}", project.customer, project.project_name, project.stage); let new_line = format!("{}||{}||{}", project.customer, project.project_name, project.stage);
lines.push(new_line); lines.push(new_line);
} }
let out_text= tableize(lines.clone(), display); tableize(lines);
return out_text.to_owned();
} }
@@ -689,7 +626,8 @@ pub fn separate_personal_work_projects(config_path: &PathBuf){
let copy_res = fs::copy(&config, &config_personal); let copy_res = fs::copy(&config, &config_personal);
if copy_res.is_err(){ if copy_res.is_err(){
print_error("error copying to conf.personal!", copy_res.err().unwrap().to_string()); print_error("error copying to conf.personal!", copy_res.err().unwrap().to_string());
let copy_cmd = format!("plase run the following command in your terminal\ncp {} {}", &config.display(), &config_personal.display()); let copy_cmd = format!("plase run the following command in your
\ncp {} {}", &config.display(), &config_personal.display());
print_informational(copy_cmd); print_informational(copy_cmd);
} }
else{ else{

View File

@@ -9,7 +9,7 @@ use crate::project_controls;
use crate::get_user_input; use crate::get_user_input;
pub fn create_project_folder(path: &mut PathBuf, folder: &str){ fn create_project_folder(path: &mut PathBuf, folder: &str){
path.push(folder); path.push(folder);
let result = fs::create_dir_all(&path); let result = fs::create_dir_all(&path);
if result.is_err(){ if result.is_err(){
@@ -33,7 +33,7 @@ fn create_note_file(path: &PathBuf) -> Option<File>{
} }
} }
pub fn external(passtemp: &PathBuf, project: &Project){ fn external(passtemp: &PathBuf, project: &Project){
// using a pathbuf to create files. // using a pathbuf to create files.
let mut notes_path = project.notes_folder.clone(); let mut notes_path = project.notes_folder.clone();
let file_creation_res = fs::create_dir_all(&notes_path); let file_creation_res = fs::create_dir_all(&notes_path);
@@ -133,7 +133,7 @@ passwords tried:
} }
pub fn internal(passtemp: &PathBuf, project: &Project){ fn internal(passtemp: &PathBuf, project: &Project){
let mut notes_path = project.notes_folder.clone(); let mut notes_path = project.notes_folder.clone();
let file_creation_res = fs::create_dir_all(&notes_path); let file_creation_res = fs::create_dir_all(&notes_path);
if file_creation_res.is_err(){ if file_creation_res.is_err(){
@@ -316,7 +316,7 @@ powerup.ps1/sharpup.exe notes.
} }
pub fn vishing(project: &Project){ fn vishing(project: &Project){
let mut notes_path = project.notes_folder.clone(); let mut notes_path = project.notes_folder.clone();
let mknote_folder_res = fs::create_dir_all(&notes_path); let mknote_folder_res = fs::create_dir_all(&notes_path);
if mknote_folder_res.is_err(){ if mknote_folder_res.is_err(){
@@ -346,6 +346,7 @@ four main aspects
pretexts: pretexts:
default is third party it. default is third party it.
they have 2 dudes for helpdesk so this may not be the best pretext. Try to impersonate a specific helpdesk user. impersonate William sounds like our plan.
Vector - Vector -
@@ -431,6 +432,6 @@ pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32
vishing(&new_prject); vishing(&new_prject);
} }
projects.push(new_prject); projects.push(new_prject);
project_controls::save_projects(projects, config_path, &false); project_controls::save_projects(projects, config_path);
println!("project created and saved to the projects config file!"); println!("project created and saved to the projects config file!");
} }