5 Commits

Author SHA1 Message Date
pyro57000
b85d0e5d79 added some logic to give you some time to
enter the sudo password when required for
cobalt strike.
2025-03-27 11:49:53 -05:00
pyro57000
477ac6e360 Added logic and settings for enabling fingerprint
authentication within distro box
2025-03-19 14:52:21 -05:00
pyro57000
fe6524016f added a check to make sure cobalt strike exists
before spawning a thread.
2025-03-13 15:27:15 -05:00
pyro57000
967052a4e2 cleaned up un-needed library imports from
box_controls.
2025-03-13 15:03:14 -05:00
pyro57000
2796d31f14 added logic to launch bloodhound with the
distrobox.
2025-03-13 15:02:01 -05:00
6 changed files with 184 additions and 75 deletions

View File

@@ -53,11 +53,11 @@ Current engagements: client1 internal pentest, client 2 internal pentest
This tool automatically creates the file structure, and if you use the start_pentest option populates the markdown note files with the templates I use. This tool automatically creates the file structure, and if you use the start_pentest option populates the markdown note files with the templates I use.
For example if I get a new internal pentest engagement for client 3 but it hasn't started yet I'll start by creating the folder and note structure using option 4 in the menu system. This would create the folder structure and notes templates in the /home/pyro/pentests/upcomming/client3/internal_pentest and /home/pyro/notes/upcomming/client3/internal_pentest folders respectively. It does not create the distrobox or add it to the tracked project list yet. For example if I get a new internal pentest engagement for client 3 but it hasn't started yet I'll start by creating the folder and note structure using option 4 in the menu system. This would create the folder structure and notes templates in the /home/pyro/pentests/upcomming/client3/internal_pentest and /home/pyro/notes/upcomming/client3/internal_pentest folders respectively. It does not create the distrobox, but it does add it to the list of tracked projects, with a status of upcomming.
Once the engagement starts I'd run option 6 "import new project - and set up new distrobox" from the menu system. It will ask if you have an existing folder structure to copy over, since I created that structure before with option 4 I would answer y, yes, or anything with the letter y in it. Then it prompts you to past the path to the folders to copy over. Here I browse to /home/pyro/pentests/upcomming in dolphin. I right click on the client3 folder and select "copy path" and then paste that into the terminal. I repeat this process for the notes folder. Once the engagement starts I'd run option 9 to promote a project from upcomming status to current status. This will automatically copy the needed files over, and will clean up the empty directory in the upcomming files directory, but the empty folder in the upcomming notes folder is still not cleaning correctly, I'm working on that.
It then attempts to guess the client name and project name based on the folder structure, and asks you to confirm. If its correct the project object will be created, the folders will be copied, and a new distrobox will be set up. If it is not correct it will prompt you to correct it, then copy the files, create a new project object, and setup a new distrobox. At the moment it is not very fault tollerant and will fail if there is an existing folder with the same name. I plan to fix that later, but haven't gotten around to it yet. Once the distro box is set up (this takes a while) it will return you to the main menu. It then will create a new distrobox and ask you if you need to set up cobalt strike for the project. if so it'll ask you for the path to your cobalt strike, it'll copy that into the project files folder so that you can run it if needed.
During the test I use the menu system to spawn new terminals in the distrobox created for the engagement, use the various file generation options to get data in easily usable format for attack operations, etc. During the test I use the menu system to spawn new terminals in the distrobox created for the engagement, use the various file generation options to get data in easily usable format for attack operations, etc.

View File

@@ -1,15 +1,11 @@
use core::error;
use std::os::unix::thread::JoinHandleExt;
use std::process::Command; use std::process::Command;
use std::{path::PathBuf, process}; use std::{path::PathBuf, process};
use std::env; use std::env;
use std::fs; use std::fs;
use std::io::stdin;
use std::io::Write; use std::io::Write;
use std::thread::{self, JoinHandle, Thread}; use std::thread::{self, JoinHandle};
use std::time::Duration; use std::time::Duration;
use std::str::FromStr; use crate::{get_user_input, Project};
use crate::Project;
pub fn stop_all_boxes(projects: &Vec<Project>){ pub fn stop_all_boxes(projects: &Vec<Project>){
let mut problem_childs: Vec<Project> = Vec::new(); let mut problem_childs: Vec<Project> = Vec::new();
@@ -74,7 +70,7 @@ pub fn project_inline_terminal(project: Project){
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"); 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");
} }
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool){ 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(){
@@ -95,55 +91,68 @@ pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, ne
} }
} }
let mut box_name_path = project.files_folder.clone(); let mut box_name_path = project.files_folder.clone();
let mut box_name = format!("atarchbox_{}", &project.customer); let box_name = format!("{}_{}", &boxtemplate, &project.customer);
box_name_path.push("boxname"); box_name_path.push("boxname");
let mut box_name_file = fs::File::create(box_name_path).expect("Error creating box name file"); let mut box_name_file = fs::File::create(box_name_path).expect("Error creating box name file");
box_name_file.write_all(&box_name.as_bytes()).expect("error writing boxname to box file"); box_name_file.write_all(&box_name.as_bytes()).expect("error writing boxname to box file");
let pentest_volume = format!("{}:/pentest:rw", &project.files_folder.display()); let pentest_volume = format!("{}:/pentest:rw", &project.files_folder.display());
let toold_volume = format!("{}:/tools:rw", tools_dir.display()); let toold_volume = format!("{}:/tools:rw", tools_dir.display());
println!("distrobox create --root --init --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume, pentest_volume, box_name); let mut distrobox_cmd = String::new();
let distrobox_result = process::Command::new("distrobox") if fingerprint{
.arg("create") println!("creating box with shared volume for fingerprints... note you will still need to set up fingerprint authentication in your distrobox");
.arg("--root") println!("\nfor example, you may need to install fprintd and imagemegick on your template box, and set up the pam files to utilize finger print auth");
.arg("--init") println!("\nsee https://wiki.archlinux.org/title/Fprint for more information and instructions");
.arg("--unshare-all") distrobox_cmd = format!("distrobox create --root --init --clone {} --volume {} --volume {} --volume /var/lib/fprint:/var/lib/fprint:rw --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
.arg("--clone") }
.arg(boxtemplate) else {
.arg("--volume") distrobox_cmd = format!("distrobox create --root --init --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
.arg(&toold_volume) }
.arg("--volume") println!("{}", distrobox_cmd);
.arg(&pentest_volume) let distrobox_cmd_vec: Vec<&str> = distrobox_cmd.split_whitespace().collect();
.arg("--name") let mut distrobox_cmd_build = process::Command::new("distrobox");
.arg(&box_name) let mut first = true;
.status() for word in &distrobox_cmd_vec{
.expect("error getting distrobox status"); if first == false{
if distrobox_result.success(){ println!("adding {} as an argument for the creation command...", word);
println!("we made a distrobox oh boy!"); distrobox_cmd_build.arg(word);
let distrobox_start_result = process::Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&box_name)
.arg("--")
.arg("sudo")
.arg("-s")
.arg("ln")
.arg("-sf")
.arg("/pentest/boxname")
.arg("/etc/boxname")
.status()
.expect("error getting response from distrobox start");
if distrobox_start_result.success(){
println!("distrobox was started as well!!!! good job me!");
} }
else{ else{
println!("ooof did not start successfully try entering it yoruself"); first = false;
println!("distrobox enter --rrot {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
} }
} }
else{ let distrobox_result = distrobox_cmd_build.status();
println!("ooof distrobox did not work.... try creating it yourself"); if distrobox_result.is_err(){
println!("distrobox create --root --clone {} --volume {} --volume {} --name {}", boxtemplate, &toold_volume, &pentest_volume, &box_name); println!("oooof we ran into trouble creating your distrobox!!");
println!("distrobox enter --root {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name); println!("try creating it manually!");
println!("{}", distrobox_cmd);
}
else{
if distrobox_result.unwrap().success(){
println!("we made a distrobox oh boy!");
let distrobox_start_result = process::Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&box_name)
.arg("--")
.arg("sudo")
.arg("-s")
.arg("ln")
.arg("-sf")
.arg("/pentest/boxname")
.arg("/etc/boxname")
.status();
if distrobox_start_result.is_err(){
println!("ooof did not start successfully try entering it yoruself");
println!("distrobox enter --root {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
}
else if distrobox_start_result.unwrap().success(){
println!("distrobox was started as well!!!! good job me!");
}
else {
println!("ooof did not start successfully try entering it yoruself");
println!("distrobox enter --root {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
}
}
} }
} }
@@ -185,6 +194,15 @@ pub fn clean_unused_boxes(projects: &Vec<Project>, boxtemplate: &String) -> Opti
} }
pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{ pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
let mut check_path = PathBuf::new();
check_path.push(&project.files_folder);
check_path.push("cobaltstrike/client");
if check_path.as_path().exists() == false{
println!("looks like you don't have cobalt strike set up on this beacon... try copying your cobalt strike folder to the following path!");
println!("{}", &check_path.display());
return None;
}
println!("you will need to enter your sudo password shortly, when you've done that successfully please type END and hit enter");
let handle = thread::spawn(move ||{ let handle = thread::spawn(move ||{
let mut cs_dir = PathBuf::new(); let mut cs_dir = PathBuf::new();
cs_dir.push(project.files_folder); cs_dir.push(project.files_folder);
@@ -204,5 +222,61 @@ pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
} }
} }
}); });
thread::sleep(Duration::from_secs(5));
loop{
let end = get_user_input("please enter END if the sudo password was enter correctly!");
if end == "END".to_string(){
break;
}
}
return Some(handle);
}
pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
let mut bloodhound_command = String::new();
let version_response = get_user_input("do you want to use a specific bloodhound version?");
if version_response.to_lowercase().contains("y"){
bloodhound_command = get_user_input("path to the bloodhound binary you want to use?");
}
else{
bloodhound_command = "bloodhound".to_owned();
}
let mut neo4j_started = false;
let neo4jstart_res = Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&project.boxname)
.arg("--")
.arg("sudo")
.arg("neo4j")
.arg("start")
.status();
if neo4jstart_res.is_err(){
let error = neo4jstart_res.err().unwrap();
println!("errror starting neo4j...");
println!("{}", error);
}
else{
neo4j_started = true;
thread::sleep(Duration::from_secs(3));
}
if neo4j_started == false{
println!("review previous errors, not spawning bloodhound thread...");
return None;
}
let handle = thread::spawn(move ||{
let bloodhound_res = Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&project.boxname)
.arg("--")
.arg(bloodhound_command)
.output();
if bloodhound_res.is_err(){
let error = bloodhound_res.err().unwrap();
println!("error starting bloodhound!");
println!("{}", error);
}
});
return Some(handle); return Some(handle);
} }

View File

@@ -5,12 +5,15 @@ use std::io::Read;
use std::io::Write; use std::io::Write;
use std::io::stdin; use std::io::stdin;
use std::io::copy; use std::io::copy;
use std::process::Command;
use reqwest::blocking::get; use reqwest::blocking::get;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::process::exit; use std::process::exit;
use directories::UserDirs; use directories::UserDirs;
use crate::get_user_input;
fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){
let mut delete_for_cleanup = config_path.clone(); let mut delete_for_cleanup = config_path.clone();
@@ -286,18 +289,47 @@ Do you have a distrobox set up to function as your template for all new projects
"); ");
std::io::stdin().read_line(&mut have_template).unwrap(); std::io::stdin().read_line(&mut have_template).unwrap();
if have_template.contains("n"){ if have_template.contains("n"){
println!("please set up a distrobox with root as a template and re-run this tool"); println!("ooof buddy, should have had that already... no worries, we'll make one now.");
println!("example distrobox setup command:"); let new_boxname = get_user_input("name for your template box? (for exmaple I use atarchbox cause its my attacking archbox ;-)");
println!("distrobox create --root --image archlinux --name template"); println!("please review the following link to select an image to use for your distrobox");
println!("then enter that distrobox and install all the tools you want and do what ever setup you need"); println!("https://distrobox.it/compatibility/#containers-distros");
println!("and re-run this tool."); let image_name = get_user_input("which image would you like to use?");
process::Command::new("rm").arg(del_on_fail).spawn().expect("ERROR deleting config folder, please manually clean up"); let tools_volume =format!("{}:/tools:rw", &tools_response);
std::process::exit(1); let distrobox_create_res = Command::new("distrobox")
.arg("create")
.arg("--root")
.arg("--name")
.arg(new_boxname)
.arg("--init")
.arg("--image")
.arg(image_name)
.arg("--volume")
.arg(tools_volume)
.arg("--additional-packages")
.arg("systemd")
.arg("--")
.arg("exit")
.status();
if distrobox_create_res.is_err(){
let error = distrobox_create_res.err().unwrap();
println!("ooof we ran into a problem creating your distrobox....");
println!("{}", error);
println!("you'll have to make it manually, but remember the name you want to use for the next step.");
}
else{
distrobox_create_res.unwrap();
println!("nice, we created a distrobox, remeber the name of your box for the next step!");
}
} }
let _list = process::Command::new("distrobox").arg("list").arg("--root").status(); let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
println!("distrobox template name?"); println!("distrobox template name?");
std::io::stdin().read_line(&mut template_name).unwrap(); std::io::stdin().read_line(&mut template_name).unwrap();
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end()); let mut set_fprint = String::from("no");
let fprint_answer = get_user_input("do you want to use fingerprint authentication inside the distroboxes?").to_lowercase();
if fprint_answer.contains("y"){
set_fprint = "yes".to_owned();
}
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}\nfingerprint:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end(), set_fprint);
config_file.write_all(config_string.as_bytes()).expect("error writing to config file"); config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
let default_projectline = format!("default:default:{}:{}:yes:{}:current", &notes_response.trim_end(), &files_response.trim_end(), &template_name.trim_end()); let default_projectline = format!("default:default:{}:{}:yes:{}:current", &notes_response.trim_end(), &files_response.trim_end(), &template_name.trim_end());
projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line"); projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line");

View File

@@ -77,6 +77,7 @@ fn main() {
let mut upcoming_files = PathBuf::new(); let mut upcoming_files = PathBuf::new();
let mut upcoming_notes = PathBuf::new(); let mut upcoming_notes = PathBuf::new();
let mut pass_spray_file = PathBuf::new(); let mut pass_spray_file = PathBuf::new();
let mut fingerprint = false;
println!("\nconfig already generated\nloading config file...\n"); println!("\nconfig already generated\nloading config file...\n");
let settings_string = fs::read_to_string(&config_path).expect("error reading config file"); let settings_string = fs::read_to_string(&config_path).expect("error reading config file");
let settings: Vec<&str> = settings_string.split("\n").collect(); let settings: Vec<&str> = settings_string.split("\n").collect();
@@ -95,6 +96,7 @@ fn main() {
"rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(), "rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(),
"rule_location" => rule = setting_vec[1].trim_end().to_owned(), "rule_location" => rule = setting_vec[1].trim_end().to_owned(),
"pass_file"=> pass_spray_file.push(setting_vec[1]), "pass_file"=> pass_spray_file.push(setting_vec[1]),
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}},
_ => println!("error unknown setting: {}", setting_vec[0]) _ => println!("error unknown setting: {}", setting_vec[0])
} }
} }
@@ -114,5 +116,5 @@ fn main() {
println!("Enter to start main menu"); println!("Enter to start main menu");
let mut enter = String::new(); let mut enter = String::new();
std::io::stdin().read_line(&mut enter).unwrap(); std::io::stdin().read_line(&mut enter).unwrap();
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file); menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint);
} }

View File

@@ -1,6 +1,3 @@
use std::clone;
use std::path;
use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use chrono::Datelike; use chrono::Datelike;
@@ -34,10 +31,10 @@ fn get_active_project(projects: &Vec<Project>) -> &Project{
return active_project return active_project
} }
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, 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){ pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, 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){
let mut loopize = true; let mut loopize = true;
let mut new_id = next_project_id(&config_path); let mut new_id = next_project_id(&config_path);
let mut threads = Vec::new(); let mut threads = Vec::new();
loop { loop {
let active_project = get_active_project(&projects); let active_project = get_active_project(&projects);
let mut response = String::new(); let mut response = String::new();
@@ -137,8 +134,9 @@ Year: {}
21.) Stop All Distroboxes 21.) Stop All Distroboxes
22.) Password Spray (will print password to spray, and wait the obervation window time) 22.) Password Spray (will print password to spray, and wait the obervation window time)
23.) crack password hashes on your cracking rig 23.) crack password hashes on your cracking rig
24.) prune unused distroboxes (free up system storage) 24.) Launch bloodhound with the current project's distrobox
25.) Quit Application 25.) prune unused distroboxes (free up system storage)
26.) Quit Application
\n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year); \n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year);
std::io::stdin().read_line(&mut response).expect("error getting menu input"); std::io::stdin().read_line(&mut response).expect("error getting menu input");
clear().expect("error clearing screen"); clear().expect("error clearing screen");
@@ -151,14 +149,14 @@ Year: {}
"3" => project_controls::switch_project(&mut projects), "3" => project_controls::switch_project(&mut projects),
"4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)}, "4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)},
"5" => project_controls::save_projects(&projects, &config_path), "5" => project_controls::save_projects(&projects, &config_path),
"6" => {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)}, "6" => {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)},
"7" => project_controls::remove_project(&mut projects, &config_path), "7" => project_controls::remove_project(&mut projects, &config_path),
"8" => project_controls::print_upcoming_projects(&projects), "8" => project_controls::print_upcoming_projects(&projects),
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate), "9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint),
"10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()), "10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
"11" => box_controls::project_inline_terminal(active_project.clone()), "11" => box_controls::project_inline_terminal(active_project.clone()),
"12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}}, "12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}},
"13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false), "13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint),
"14" => info_controls::open_in_dolphin("files", active_project.clone()), "14" => info_controls::open_in_dolphin("files", active_project.clone()),
"15" => info_controls::open_in_dolphin("notes", active_project.clone()), "15" => info_controls::open_in_dolphin("notes", active_project.clone()),
"16" => info_controls::generate_userpass(&active_project), "16" => info_controls::generate_userpass(&active_project),
@@ -169,8 +167,9 @@ Year: {}
"21" => box_controls::stop_all_boxes(&projects), "21" => box_controls::stop_all_boxes(&projects),
"22" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path), "22" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
"23" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule), "23" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
"24" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}}, "24" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);},
"25" => {project_controls::save_projects(&projects, &config_path); "25" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
"26" => {project_controls::save_projects(&projects, &config_path);
let mut stop = String::new(); let mut stop = String::new();
println!("stop all boxes?\ny/n"); println!("stop all boxes?\ny/n");
std::io::stdin().read_line(&mut stop).unwrap(); std::io::stdin().read_line(&mut stop).unwrap();
@@ -187,6 +186,8 @@ Year: {}
let mut enter = String::new(); let mut enter = String::new();
std::io::stdin().read_line(&mut enter).unwrap(); std::io::stdin().read_line(&mut enter).unwrap();
} }
println!("this will hang until all threads are finished.");
println!("make sure to close all programs opened with this menu, like cobalt strike or bloodhound.");
for thread in threads{ for thread in threads{
thread.join().unwrap(); thread.join().unwrap();
} }

View File

@@ -68,7 +68,7 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
} }
} }
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){ 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();
@@ -229,7 +229,7 @@ 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); make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint);
} }
projects.push(new_project); projects.push(new_project);
save_projects(projects, config_path); save_projects(projects, config_path);
@@ -343,7 +343,7 @@ pub fn print_upcoming_projects(projects: &Vec<Project>){
} }
} }
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &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();
for project in &working_projects{ for project in &working_projects{
if project.stage.contains("upcoming"){ if project.stage.contains("upcoming"){
@@ -434,7 +434,7 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
} }
} }
thread::sleep(Duration::from_secs(3)); thread::sleep(Duration::from_secs(3));
make_box(&promoted_project, tools_dir, boxtemplate, true); make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint);
projects_to_save.push(promoted_project); projects_to_save.push(promoted_project);
} }
else{ else{