12 Commits
3.1.5 ... 3.1.9

Author SHA1 Message Date
Pyro57000
1a7e7d4326 added the start of the gui re-write
not ready yet, but its getting there.
2025-06-24 16:02:29 -05:00
Pyro57000
98800e3f3f started work on the gui rewrite, its not ready
yet but we're getting close!
2025-06-24 16:00:42 -05:00
Pyro57000
637fd5417f re-did how settings are handled and updated how to load the settings, modify them, and save them so that when you separate work and play it all works right this time! 2025-06-05 15:49:31 -05:00
Pyro57000
9fa1800337 added final success message 2025-06-04 09:55:06 -05:00
Pyro57000
e211433772 udated the exit operations to only prompt for
work vs personal if work and personal configs
exist.
2025-06-04 09:50:13 -05:00
Pyro57000
6d92032d06 added some functions to switch between managing
personal projects and managing work projects
as well as the ability to separate your current
project list into work and personal.
2025-06-02 12:18:59 -05:00
Pyro57000
925c3fd471 removed some warnings. 2025-05-30 10:26:40 -05:00
Pyro57000
21d8da25e3 Added a tablize function and did more
re coloring.

The tablize function isn't quite 100% there yet.
It mostly works, but I need to figure out word
wrapping for cells.
2025-05-30 10:24:45 -05:00
Pyro57000
f8ec8de137 removed more debugging print statements 2025-05-28 15:36:18 -05:00
Pyro57000
a3f42ecb3f removed some debugging print comands 2025-05-28 15:31:17 -05:00
Pyro57000
387c12a247 fixed the nmap scanning function! 2025-05-28 15:29:19 -05:00
Pyro57000
249ecc786d added fun colors!
currently added some green for the initialization
and red for errors, output color will be added
soon!
2025-05-28 12:59:39 -05:00
17 changed files with 5284 additions and 876 deletions

3445
pentest_tool/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,14 @@ edition = "2021"
[dependencies] [dependencies]
chrono = "0.4.39" chrono = "0.4.39"
clearscreen = "3.0.0" clearscreen = "3.0.0"
colored = "3.0.0"
directories = "5.0.1" 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"
term_size = "0.3.2"
walkdir = "2.5.0" walkdir = "2.5.0"

View File

@@ -0,0 +1,7 @@
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,3 +1,4 @@
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;
@@ -5,6 +6,9 @@ use std::fs;
use std::io::Write; 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 iced::theme::palette::Success;
use crate::{get_user_input, Project}; use crate::{get_user_input, Project};
pub fn stop_all_boxes(projects: &Vec<Project>){ pub fn stop_all_boxes(projects: &Vec<Project>){
@@ -37,7 +41,8 @@ pub fn stop_all_boxes(projects: &Vec<Project>){
} }
} }
pub fn project_standalone_terminal(project: Project, mut terminal: String){ pub fn project_standalone_terminal(project: Project, mut terminal: String, display: &bool) -> Option<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"){
@@ -64,18 +69,69 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String){
print!("{}", terminal); print!("{}", terminal);
let start = terminal_start.spawn(); let start = terminal_start.spawn();
match start{ match start{
Ok(_child) => println!("New Terminal Started, you can retun to the menu now!"), Ok(_child) => {
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") if *display{
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){ pub fn project_inline_terminal(project: Project, given_command: Option<String>) -> Option<String>{
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"); let mut return_data = String::new();
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);
}
} }
#[allow(unused)] fn make_box_cli(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: 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(){
@@ -161,6 +217,104 @@ pub fn make_box(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);
@@ -222,8 +376,8 @@ pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
.output(); .output();
if cobalt_strike_launch_result.is_err(){ if cobalt_strike_launch_result.is_err(){
let error = cobalt_strike_launch_result.err().unwrap(); let error = cobalt_strike_launch_result.err().unwrap();
println!("error launching cobalt strike!"); println!("{}", "error launching cobalt strike!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
} }
}); });
@@ -259,8 +413,8 @@ pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
.status(); .status();
if neo4jstart_res.is_err(){ if neo4jstart_res.is_err(){
let error = neo4jstart_res.err().unwrap(); let error = neo4jstart_res.err().unwrap();
println!("errror starting neo4j..."); println!("{}","errror starting neo4j...".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
neo4j_started = true; neo4j_started = true;
@@ -280,8 +434,8 @@ pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
.output(); .output();
if bloodhound_res.is_err(){ if bloodhound_res.is_err(){
let error = bloodhound_res.err().unwrap(); let error = bloodhound_res.err().unwrap();
println!("error starting bloodhound!"); println!("{}","error starting bloodhound!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
}); });
return Some(handle); return Some(handle);

View File

@@ -1,151 +1,192 @@
use std::collections::HashMap;
use std::fs;
use std::process::Termination;
use rfd::FileDialog;
use std::fs::read_to_string;
use std::fs::OpenOptions;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use std::io::Write;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use chrono::Datelike; use chrono::Datelike;
use clearscreen::clear; use clearscreen::clear;
use clearscreen; use clearscreen;
use chrono::Local; use chrono::Local;
use colored::Colorize;
use crate::configuration::load_config;
use crate::print_error;
use crate::print_informational;
use crate::print_success;
use crate::Project; use crate::Project;
use crate::project_controls; use crate::project_controls;
use crate::box_controls; 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;
fn help(command: Option<String>){ fn help(command: Option<String>){
if command.is_some(){ if command.is_some(){
let help_cmd = command.unwrap(); let help_cmd = command.unwrap();
let mut lines = Vec::new();
lines.push("COMMAND||ALIASES||INFO".to_owned());
match help_cmd.as_str(){ match help_cmd.as_str(){
"list projects" | "lp" | "listp" | "list p" => {println!("Command: list projects\nAliases: lp, listp, list p\n\nThis command lists all projects currently tracked by the pentest_tool"); return;}, "list projects" | "lp" | "listp" | "list p" => lines.push("list projects||lp, listp, list p||This command lists all projects currently tracked by the pentest_tool".to_owned().to_owned()) ,
"switch project" | "swp" | "switch p" | "switchp" => {println!("Command: switch project\nAliases: swp, switch p, switchp\n\nThis command will switch the active project from the current one to a new on of your choosing. It will prompt you to make a selection."); return;}, "switch project" | "swp" | "switch p" | "switchp" => lines.push(" switch project|| swp, switch p, switchp||This command will switch the active project from the current one to a new on of your choosing. It will prompt you to make a selection.".to_owned()) ,
"show active project" | "show active" | "sa" | "show a" => {println!("Command: show active project\nAliases: sa, show a\n\nThis command shows information about the currently active project. NOTE the most useful information is already displayed above the CLI prompt."); return;}, "show active project" | "show active" | "sa" | "show a" => lines.push(" show active project|| sa, show a||This command shows information about the currently active project. NOTE the most useful information is already displayed above the CLI prompt.".to_owned()) ,
"create new project" | "cnp" | "new project" | "np" => {println!("Command: create new project\nAliases: cnp, new project, np\n\nThis command creates a new project and default note structure based on pyro's perferred note structure. It will prompt you for any needed information."); return;}, "create new project" | "cnp" | "new project" | "np" => lines.push(" create new project|| cnp, new project, np||This command creates a new project and default note structure based on pyro's perferred note structure. It will prompt you for any needed information.".to_owned()) ,
"save projects" | "sp" | "save" | "s" => {println!("Command: save projects\nAliases: sp save\n\nThis command saves all project information to the ~/.config/pyro_pentest_tool/projects.conf file"); return;}, "save projects" | "sp" | "save" | "s" => lines.push(" save projects|| sp save||This command saves all project information to the ~/.config/pyro_pentest_tool/projects.conf file".to_owned()) ,
"import project" | "ip" | "import" => {println!("Command: import project\nAliases: ip, import\n\nThis command will impot an existing project and set up a new distrobox for the project if it is a current project."); return;}, "import project" | "ip" | "import" => lines.push(" import project|| ip, import||This command will impot an existing project and set up a new distrobox for the project if it is a current project.".to_owned()) ,
"remove project" | "rp" | "remove" | "rmp" => {println!("Command:remove project\nAliases:rp, remove, rmp\n\nThis command removes a project from the list of projects tracked by the pentest_tool, and will destroy its distrobox. It does not remove any directories used or created by the distrobox. Run this after the report is written."); return;}, "remove project" | "rp" | "remove" | "rmp" => lines.push("remove project||rp, remove, rmp||This command removes a project from the list of projects tracked by the pentest_tool, and will destroy its distrobox. It does not remove any directories used or created by the distrobox. Run this after the report is written.".to_owned()) ,
"show upcoming projects" | "sup" | "show upcoming" => {println!("Command:show upcoming projects\nAliases:sup, show upcoming\n\nThis command shows a list of upcoming projects. Use this to verify which project you want to promote when the project enters the active phase."); return;}, "show upcoming projects" | "sup" | "show upcoming" => lines.push("show upcoming projects||sup, show upcoming||This command shows a list of upcoming projects. Use this to verify which project you want to promote when the project enters the active phase.".to_owned()) ,
"promote project" | "pp" | "promote" => {println!("Command:promote project\nAliases:pp (ha), promote\n\nThis command promotes an upcoming project to a current project. It will copy the folders that were created over to the current project space and set up a new distrobox for the project."); return;}, "promote project" | "pp" | "promote" => lines.push("promote project||pp (ha), promote||This command promotes an upcoming project to a current project. It will copy the folders that were created over to the current project space and set up a new distrobox for the project.".to_owned()) ,
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {println!("Command:new terminal\nAliases:enter, enter terminal, nt, et\n\nThis command spawns a new terminal window in the active project's distrobox. Use this to interact with your project's distrobox."); return;}, "new terminal" | "enter" | "enter terminal" | "nt" | "et" => lines.push("new terminal||enter, enter terminal, nt, et||This command spawns a new terminal window in the active project's distrobox. Use this to interact with your project's distrobox.".to_owned()) ,
"inline terminal" | "it" | "enter inline" | "ei" => {println!("Command:inline terminal\nAliases:it enter, inline, ei\n\nThis command spawns a terminal in this window using the current active project's distrobox"); return;}, "inline terminal" | "it" | "enter inline" | "ei" => lines.push("inline terminal||it enter, inline, ei||This command spawns a terminal in this window using the current active project's distrobox".to_owned()) ,
"cobalt strike" | "cs" => {println!("Command:cobalt strike\nAliases:cs\n\nThis command opens cobalt strike in the active project's distrobox, and spins it off as a new thread to ensure it doesn't block the rest of this tools operation. NOTE the cobalt strike window will need to be closed before this tool exits sucessfully."); return;}, "cobalt strike" | "cs" => lines.push("cobalt strike||cs||This command opens cobalt strike in the active project's distrobox, and spins it off as a new thread to ensure it doesn't block the rest of this tools operation. NOTE the cobalt strike window will need to be closed before this tool exits sucessfully.".to_owned()) ,
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {println!("Command:recreate distrobox\nAliases:rdb, ndb, new distrobox\n\nThis command destroyes the existing distrobox for the currently active project, and clones a new one based on the current state of the template distrobox."); return;}, "recreate distrobox" | "rdb" | "ndb" | "new distrobox" => lines.push("recreate distrobox||rdb, ndb, new distrobox||This command destroyes the existing distrobox for the currently active project, and clones a new one based on the current state of the template distrobox.".to_owned()) ,
"generate userpass" | "userpass" | "gup" | "up" => {println!("Command:generate userpass\nAliases:userpass, gup, up\n\nThis command generates a userpass file based on the active project's notes. The file will be in the username:password format."); return;}, "generate userpass" | "userpass" | "gup" | "up" => lines.push("generate userpass||userpass, gup, up||This command generates a userpass file based on the active project's notes. The file will be in the username:password format.".to_owned()) ,
"inital enum" | "ie" | "enum" => {println!("Command:initial enum\nAliases:ie, enum\n\nThis command runs the initial enum script on a nessus csv and saves the output to the active project's notes in the host_notes.md file."); return;}, "inital enum" | "ie" | "enum" => lines.push("initial enum||ie, enum||This command runs the initial enum script on a nessus csv and saves the output to the active project's notes in the host_notes.md file.".to_owned()) ,
"build attack notes" | "ban" | "attack notes" | "hn" => {println!("Command:build attack notes\nAliases:ban, attack notes\n\nThis command builds the active project's attack note based on the active project's host notes (for external tests). It is expected that you'd run the initial enum command, then manually fill out the enumeration talbes with correct service names and ports."); return;}, "build attack notes" | "ban" | "attack notes" | "hn" => lines.push("build attack notes||ban, attack notes||This command builds the active project's attack note based on the active project's host notes (for external tests). It is expected that you'd run the initial enum command, then manually fill out the enumeration talbes with correct service names and ports.".to_owned()) ,
"host discovery" | "build host discovery" | "hd" | "bhd" => {println!("Command:host discovery\nAliases:build host discovery, hd, bhd\n\nThis command prints the host discovery ping command for the active project, based on the scope table in the general.md notes file."); return;}, "host discovery" | "build host discovery" | "hd" | "bhd" => lines.push("host discovery||build host discovery, hd, bhd||This command prints the host discovery ping command for the active project, based on the scope table in the general.md notes file.".to_owned()) ,
"cobaltstrike port scan" | "cs port scan" | "csps" => {println!("Command:port scan\nAliases:cs port scan, cobaltstrike port scan, csps, ps (tell your cat I said that)\n\nThis command prints the cobalt strike portscan command based on the active project's scope table in the general.md notes file"); return;}, "cobaltstrike port scan" | "cs port scan" | "csps" => lines.push("port scan||cs port scan, cobaltstrike port scan, csps, ps (tell your cat I said that)||This command prints the cobalt strike portscan command based on the active project's scope table in the general.md notes file".to_owned()) ,
"parse port scan" | "pps" | "parse scan" => {println!("Command:parse port scan\nAliases:pps, parse scan\n\nThis commmand parses a cobalt strike portscan TSV and saves interesting hoests to files to the active project's files folder. The host files are designated with the service that was detected that might be interesting. Use this to generate target lists for specific protocols."); return;}, "parse port scan" | "pps" | "parse scan" => lines.push("parse port scan||pps, parse scan||This commmand parses a cobalt strike portscan TSV and saves interesting hoests to files to the active project's files folder. The host files are designated with the service that was detected that might be interesting. Use this to generate target lists for specific protocols.".to_owned()) ,
"stop boxes" | "stop distroboxes" | "sdb" => {println!("Command:stop boxes\nAliases:stop distroboxes, sdb\n\nThis command stops all distroboxes for the tracked projects. Note if the distrobox isn't running you will see errors in the console, you can safely ignore these."); return;}, "stop boxes" | "stop distroboxes" | "sdb" => lines.push("stop boxes||stop distroboxes, sdb||This command stops all distroboxes for the tracked projects. Note if the distrobox isn't running you will see errors in the console, you can safely ignore these.".to_owned()) ,
"password spray" | "pass spray" | "pas" => {println!("Command:password spray\nAliases:pass spray, pas\n\nThis command iterates through the password spray note file and print the command to perform the spray, waiting the proper observation window beteen commands. It prompts you to save if needed. NOTE this will block execution for the rest of the program until it is either finished, or you save and exit the password spray function. I'm working on making this better."); return;}, "password spray" | "pass spray" | "pas" => lines.push("password spray||pass spray, pas||This command iterates through the password spray note file and print the command to perform the spray, waiting the proper observation window beteen commands. It prompts you to save if needed. NOTE this will block execution for the rest of the program until it is either finished, or you save and exit the password spray function. I'm working on making this better.".to_owned()) ,
"bloodhound" | "bh" => {println!("Command:bloodhound\nAliases:bh\n\nThis command launches bloodhound in the active project's distrobox. It will automatically start neo4j before staring bloodhound."); return;}, "bloodhound" | "bh" => lines.push("bloodhound||bh||This command launches bloodhound in the active project's distrobox. It will automatically start neo4j before staring bloodhound.".to_owned()) ,
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {println!("Command:parse gather contacts\nAliases:pgc, parse contacts, pc\n\nThis command parses output saved from the gather contacts burpsuite extension."); return;}, "parse gather contacts" | "pgc" | "parse contacts" | "pc" => lines.push("parse gather contacts||pgc, parse contacts, pc||This command parses output saved from the gather contacts burpsuite extension.".to_owned()) ,
"prune distroboxes" | "pdb" | "prune" => {println!("Command:prune distroboxes\nAliases:pdb, prune\n\nthis command prunes distroboxes for all projects that are not being tracked by this tool (frees up system storage). This will start all the currently acvtive distorboxes to ensure they don't get pruned, and then will delete all the not-started distrobox volumes and resources."); return;}, "prune distroboxes" | "pdb" | "prune" => lines.push("prune distroboxes||pdb, prune||this command prunes distroboxes for all projects that are not being tracked by this tool (frees up system storage). This will start all the currently acvtive distorboxes to ensure they don't get pruned, and then will delete all the not-started distrobox volumes and resources.".to_owned()) ,
"clear" | "clear screen" | "cls" => {println!("Command:clear\nAliases:clear screen, cls\n\nThis command clears the screen of command output."); return}, "clear" | "clear screen" | "cls" => lines.push("clear||clear screen, cls||This command clears the screen of command output.".to_owned()) ,
"exit" => {println!("Command:exit\nAliases:(none)\nThis command exits the pentest_tool, it will save all project infomation, and wait for all threads to re-join the main thread before exiting."); return;}, "exit" => lines.push("exit||(none)\nThis command exits the pentest_tool, it will save all project infomation, and wait for all threads to re-join the main thread before exiting.".to_owned()) ,
"settings" => {println!("\n\nThe settings file is located at ~/.config/pyro_pentest_tool/conf\n\nThe format is setting_name:setting_value.\n\nNeeded settings are\n project_files - the place to store current project files folders\n\n projtect_notes - the place to store current project notes\n\n tools_folder - the place to store custom tools like those downloaded from github\n\n upcoming_files - the place to store upcoming project files folders\n\n upcoming_notes - The place to store upcoming project note files\n\n box_template - the name of the distrobox you want to clone for project boxes\n\n terminal - the command you use to launch a terminal, while running a specific command: Ex: konsole -e \n\n cracking_rig - the user and host you use for a personal cracking rig in the openssh formating: Ex: pyro@cracking_rig or pyro@192.168.1.101 if you do not have a cracking rig the default is @n\n\n rockyou_location - the location on the cracking rig for the rockyou.txt file default is n\n\n rule_location - the location on the cracking rig for the one rule to rule them all file. Default is n\n\n pass_file - this is the location where you store your standard password spray file. If you do not have a custom one this tool provides one. The default is ~/.config/pyro_pentest_tool/passwordspary.md\n\n fingerprint - this is whether you want fingerprint authentication within your distroboxes, takes y/n\n\n vault_name - the name of your obsidian vault, default is notes\n\n"); return;}, "settings" => lines.push("||The settings file is located at ~/.config/pyro_pentest_tool/conf||The format is setting_name:setting_value.||Needed settings are\n project_files - the place to store current project files folders|| projtect_notes - the place to store current project notes|| tools_folder - the place to store custom tools like those downloaded from github|| upcoming_files - the place to store upcoming project files folders|| upcoming_notes - The place to store upcoming project note files|| box_template - the name of the distrobox you want to clone for project boxes|| terminal - the command you use to launch a terminal, while running a specific Ex: konsole -e || cracking_rig - the user and host you use for a personal cracking rig in the openssh formating: Ex: pyro@cracking_rig or pyro@192.168.1.101 if you do not have a cracking rig the default is @n|| rockyou_location - the location on the cracking rig for the rockyou.txt file default is n|| rule_location - the location on the cracking rig for the one rule to rule them all file. Default is n|| pass_file - this is the location where you store your standard password spray file. If you do not have a custom one this tool provides one. The default is ~/.config/pyro_pentest_tool/passwordspary.md|| fingerprint - this is whether you want fingerprint authentication within your distroboxes, takes y/n|| vault_name - the name of your obsidian vault, default is notes||".to_owned()) ,
"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {println!("Command:parse normal nmap file\nAliases: pnnf, parse nmap, pn\n\nThis command parses the normal output of an nmap scan (like if you just tee'd or >'d it to a file) and outputs in host:port or int the coablt strike tsv format. It will attempt to find the file within the active project's files folder, and if it can't find the file it will prompt you for input.")}, "parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => lines.push("parse normal nmap file|| pnnf, parse nmap, pn||This command parses the normal output of an nmap scan (like if you just tee'd or >'d it to a file) and outputs in host:port or int the coablt strike tsv format. It will attempt to find the file within the active project's files folder, and if it can't find the file it will prompt you for input.".to_owned()),
"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {println!("Command: sharpersist command\nAliases: spc, sharp scheduled task, sst\n\nThis comand prints the commands to run to use sharpersist.exe to create a scheduled task that runs hourly called FRPersist.")}, "sharpersist command" | "spc" | "sharp scheduled task" | "sst" => lines.push(" sharpersist command|| spc, sharp scheduled task, sst||This comand prints the commands to run to use sharpersist.exe to create a scheduled task that runs hourly called FRPersist.".to_owned()),
"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {println!("Command: port scan\nAliases: ps, nmap, nmap scan, ns, nm\n\nThis command runs an nmap scan against the scope in the active projects notes, and saves the output.")}, "port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => lines.push(" port scan|| ps, nmap, nmap scan, ns, nm||This command runs an nmap scan against the scope in the active projects notes, and saves the output.".to_owned()),
"show scope" | "ss" | "show s" | "s s" | "scope" => {println!("Command:show scope\nAliases:ss, show s, s s, scope\n\nThis command displays the current project's scope as just the hosts in the scope table in your notes.")}, "show scope" | "ss" | "show s" | "s s" | "scope" => lines.push("show scope||ss, show s, s s, scope||This command displays the current project's scope as just the hosts in the scope table in your notes.".to_owned()),
"port scan command" | "psc" | "nmap command" | "nmc" => {println!("command:port scan command\nAliases:psc,nmap command, nmc\n\nThis command will print the nmap command to manually run a scan to the terminal so you can copy paste it.")}, "port scan command" | "psc" | "nmap command" | "nmc" => lines.push("port scan command||psc,nmap command, nmc||This command will print the nmap command to manually run a scan to the terminal so you can copy paste it.".to_owned()),
"update git tools" | "ugt" | "update git" | "ug" => {println!("Command: update git tools\nAliases: update git, ugt, ug\n\nThis command attempts to update the git tools in your tools directory, it will attempt to update every directory as a git project. If the directory is not a git project it should just error out and continue to the next one.")}, "update git tools" | "ugt" | "update git" | "ug" => lines.push(" update git tools|| update git, ugt, ug||This command attempts to update the git tools in your tools directory, it will attempt to update every directory as a git project. If the directory is not a git project it should just error out and continue to the next one.".to_owned()),
"dns records" | "dr" => {println!("Command:dnsrecords\nAliases:dr\n\nThis command will run dns recon inside of your distrobox and save the results to your enumeration notes.")}, "dns records" | "dr" => lines.push("dnsrecords||dr||This command will run dns recon inside of your distrobox and save the results to your enumeration notes.".to_owned()),
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => {println!("Command:brute force subdomains\nAliases:bsd,gobuster dns, gd\n\nthis command will run gobuster in the project's distrobox and save the results to your notes.")}, "brute force subdomains"| "bsd" | "gobuster dns" | "gd" => lines.push("brute force subdomains||bsd,gobuster dns, gd||this command will run gobuster in the project's distrobox and save the results to your notes.".to_owned()),
"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => {println!("Command:dns enumeration\nAliases:de, all dns stuff, ads, dns stuff, de\n\nThis command will perform both dns record enumeration with dnsrecon, and subdomain enumeration using gobster inside of your distrobox and save the output to your notes.")}, "dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => lines.push("dns enumeration||de, all dns stuff, ads, dns stuff, de||This command will perform both dns record enumeration with dnsrecon, and subdomain enumeration using gobster inside of your distrobox and save the output to your notes.".to_owned()),
"modify tool config" | "mtc" => {println!("Command: modify tool config\nAliases: mtc\n\nThis command lets you modify the tool's configuration.");} "modify tool config" | "mtc" => lines.push("modify tool config|| mtc||This command lets you modify the tool's configuration.".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 work projects" | "switch work" => lines.push("switch to work projects||switch work||This command lets you switch to load the work projects.".to_owned()),
_ => () _ => ()
} }
tableize(lines, &true);
}
else{
println!("Welcom to Pyro's pentest command line!");
println!("the pentest_tool uses a configuration file to store your settings. This configuration file is located at ~/.config/pyro_pentest_tool/conf.\nYou can modify this file, but do so cautiously, incorrect formatting will cause this program to have a bruh moment.\nThe correct format is setting_name:setting_value\nExample:\nprojecT_files:/var/home/pyro/pentests/current");
println!("for help configuring the settings file run help settings");
let lines = vec!["command||aliases".to_owned(),
"menu||main menu, mm".to_owned(),
"list projects||lp, listp, list p".to_owned(),
"switch project||sp, switch p, switchp".to_owned(),
"show active project||show active, sa, show a".to_owned(),
"create new project||cnp, new project, np".to_owned(),
"save projects||sp, save, s".to_owned(),
"import project||ip, import".to_owned(),
"remove project||rp, remove, rmp".to_owned(),
"show upcoming project||sup, show upcoming".to_owned(),
"promote project||pp, promote".to_owned(),
"new terminal||enter, enter terminal, nt, et".to_owned(),
"inline terminal||it, enter inline, ei".to_owned(),
"cobalt strike||cs".to_owned(),
"recreate distrobox||rdb, ndb, new distrobox".to_owned(),
"generate userpass||userpass, gup, up".to_owned(),
"inital enum||ie, enum".to_owned(),
"host discovery ||build host discovery, hd, bhd".to_owned(),
"port scan||cs port scan, cobaltstrike port scan, csps, ps".to_owned(),
"parse port scan ||pps, parse scan".to_owned(),
"stop boxes||stop distroboxes, sdb".to_owned(),
"password spray||pass spray, pas".to_owned(),
"bloodhound||bh".to_owned(),
"parse gather contacts||pgc, parse contacts, pc".to_owned(),
"prune distroboxes||pdb, prune".to_owned(),
"clear||clear screen, cls".to_owned(),
"parse nomral nmap file||pnnf, parse nmap, pn".to_owned(),
"show scope||ss, show s, s s, scope".to_owned(),
"sharpersist command||spc, sharp scheduled task".to_owned(),
"port scan||ps, nmap, nmap scan, ns, nm".to_owned(),
"port scan command||psc, nmap command, nmc".to_owned(),
"update git tools||ugt, update git, ug".to_owned(),
"dns records||dr".to_owned(),
"brute force subdomain||bsd, gobuster dns, gd".to_owned(),
"dns enumeration||de, all dns stuff, ads, dns stuff, ds".to_owned(),
"modify tool config||mtc".to_owned(),
"separate work and personal projects||swpp, separate projects, seppro".to_owned(),
"switch to personal projects||switch personal".to_owned(),
"switch to work projects||switch work".to_owned(),
"help||?, -h".to_owned()];
println!("available commands:");
tableize(lines, &true);
} }
println!("Welcom to Pyro's pentest command line!");
println!("the pentest_tool uses a configuration file to store your settings. This configuration file is located at ~/.config/pyro_pentest_tool/conf.\nYou can modify this file, but do so cautiously, incorrect formatting will cause this program to have a bruh moment.\nThe correct format is setting_name:setting_value\nExample:\nprojecT_files:/var/home/pyro/pentests/current");
println!("for help configuring the settings file run help settings");
println!("available commands: name | aliases | ...");
print!("
menu | main menu | mm
list projects | lp | listp | list p
switch project | sp | switch p | switchp
show active project | show active | sa | show a
create new project | cnp | new project | np
save projects | sp | save | s
import project | ip | import
remove project | rp | remove | rmp
show upcoming project | sup | show upcoming
promote project | pp | promote
new terminal | enter | enter terminal | nt | et
inline terminal | it | enter inline | ei
cobalt strike | cs
recreate distrobox | rdb | ndb | new distrobox
generate userpass | userpass | gup | up
inital enum | ie | enum
host discovery | build host discovery | hd | bhd
port scan | cs port scan | cobaltstrike port scan | csps | ps
parse port scan | pps | parse scan
stop boxes | stop distroboxes | sdb
password spray | pass spray | pas
bloodhound | bh
parse gather contacts | pgc | parse contacts | pc
prune distroboxes | pdb | prune
clear | clear screen | cls
parse nomral nmap file | pnnf | parse nmap | pn
show scope | ss | show s | s s | scope
sharpersist command | spc | sharp scheduled task
port scan | ps | nmap | nmap scan | ns | nm
port scan command | psc | nmap command | nmc
update git tools | ugt | update git | ug
dns records | dr
brute force subdomains| bsd | gobuster dns | gd
dns enumeration | de | all dns stuff | ads | dns stuff | ds
modify tool config | mtc
help | ? | -h
")
} }
pub fn get_active_project(projects: &Vec<Project>) -> &Project{ pub fn get_active_project(projects: &Vec<Project>) -> Option<&Project>{
let mut active_project = &projects[0]; let mut active_project = &projects[0];
for project in projects{ for project in projects{
if project.active == true{ if project.active == true{
active_project = project active_project = project
} }
} }
return active_project return Some(active_project)
} }
pub fn next_project_id(config_path: &PathBuf) -> i32{ pub fn next_project_id(config_path: &PathBuf) -> Option<i32>{
let projects = project_controls::get_projects(config_path, false); let projects_res = project_controls::get_projects(config_path, false);
if projects_res.is_none(){
println!("{}", "Error loading projects!!".red());
return None;
}
let projects = projects_res.unwrap();
let mut new_id = 0; let mut new_id = 0;
for project in projects.clone(){ for project in projects.clone(){
if project.id > new_id{ if project.id > new_id{
new_id = project.id + 1; new_id = project.id + 1;
} }
} }
return new_id; return Some(new_id);
} }
#[allow(unused)] #[allow(unused)]
pub fn run_command(cmd: String, pub fn run_command(cmd: String,
mut projects: &mut Vec<Project>, settings: &HashMap<&str, String>,
config_path: PathBuf, config_path: &PathBuf,
base_files: &PathBuf, mut projects: &mut Vec<Project>,
base_notes: &PathBuf, display: bool,
tools_dir: &PathBuf, given_data: Option<String>) -> (Option<Option<JoinHandle<()>>>, Option<String>) {
boxtemplate: String, let base_files = PathBuf::from(settings["project_files"].clone());
terminal: String, let base_notes = PathBuf::from(settings["project_notes"].clone());
cracking_rig: String, let tools_dir = PathBuf::from(settings["tools_folder"].clone());
rockyou: String, let boxtemplate= settings["box_template"].clone();
rule: String, let terminal = settings["terminal_command"].clone();
upcoming_files: &PathBuf, let cracking_rig = settings["cracking_rig"].clone();
upcoming_notes: &PathBuf, let rockyou = settings["rockyou"].clone();
password_spray_file: &PathBuf, let rule = settings["rule"].clone();
fingerprint: bool, let upcoming_files = PathBuf::from(settings["upcoming_files"].clone());
vault_name: String) -> Option<JoinHandle<()>> { let upcoming_notes = PathBuf::from(settings["upcoming_notes"].clone());
let mut new_id = next_project_id(&config_path); let password_spray_file = PathBuf::from(settings["pass_spray_file"].clone());
let active_project = get_active_project(&projects); let fingerprint = settings["fingerprint"].to_lowercase().contains("y");
let vault_name = settings["vault_name"].clone();
let new_id_res = next_project_id(&config_path);
if new_id_res.is_none(){
println!("{}", "failed to get new project ID!".red());
return (None, None);
}
let mut new_id = new_id_res.unwrap();
let active_project_res = get_active_project(&projects);
if active_project_res.is_none(){
println!("{}", "failed to get active project!".red());
return (None, None);
}
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());
let mut obsidian_folder_vec = PathBuf::new(); let mut obsidian_folder_vec = PathBuf::new();
let mut reached_vault_folder = false; let mut reached_vault_folder = false;
@@ -182,73 +223,76 @@ pub fn run_command(cmd: String,
else{ else{
help(None); help(None);
} }
return None; return (None, 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); return None}, "list projects" | "lp" | "listp" | "list p" => {project_controls::list_projects(&projects, &display); return (None, None)},
"switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return None}, "switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return (None, None)},
"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}, "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))},
"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}, "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)},
"save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path); return None}, "save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path, &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}, "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)},
"remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path); return None}, "remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path, None); return (None, None)},
"show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects); return None}, "show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects, &display); 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}, "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)},
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()); return None}, "new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone(), &display); return (None, None)},
"inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone()); return None}, "inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone(), given_data); return (None, None)},
"cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); return cs_thread}, //"cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone(), &display); return (Some(cs_thread), None)},
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint); return None}, "recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint, Some(terminal), &display); return (None, None)},
"generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project); return None}, //"generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project, &display); return (None, None)},
"inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project); return None}, //"inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project, &display); return (None, None)},
"build attack notes" | "ban" | "attack notes" | "hn" => {portscan_controls::build_cmd_for_host_discovery(&active_project); return None;} //"build attack notes" | "ban" | "attack notes" | "hn" => {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}, //"host discovery" | "build host discovery" | "hd" | "bhd" => {portscan_controls::build_cmd_for_host_discovery(&active_project, &display); return (None, None)},
"cobaltstrike port scan" | "cs port scan" | "csps" => {portscan_controls::build_cs_portscan_cmd(&active_project); return None}, //"cobaltstrike port scan" | "cs port scan" | "csps" => {portscan_controls::build_cs_portscan_cmd(&active_project, &display); return (None, None)},
"parse port scan" | "pps" | "parse scan" => {portscan_controls::parse_csportscan(&active_project); return None}, //"parse port scan" | "pps" | "parse scan" => {portscan_controls::parse_csportscan(&active_project, None, None, &display); return (None, None)},
"stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects); return None}, //"stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects, &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}, //"password spray" | "pass spray" | "pas" => {info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path, &display); return (None, None)},
"bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); return Some(bloodhound_handle);}, //"bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone(), &display); return (Some(bloodhound_handle), None);},
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project); return None}, //"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project, &display); return (None, None)},
"prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); return prune_thread}, //"prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate, &display); return (Some(prune_thread), None)},
"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {portscan_controls::parse_normal_nmap_output(&active_project); return None;}, //"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {portscan_controls::parse_normal_nmap_output(&active_project, &display); 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}, //"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)},
"update git tools" | "ugt" | "update git" | "ug" => {tool_controls::update_git_tools(tools_dir); return None}, //"update git tools" | "ugt" | "update git" | "ug" => {tool_controls::update_git_tools(&tools_dir, &display); return (None, None)},
"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project); return None;}, //"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project, &display); return (None, None);},
"port scan command" | "psc" | "nmap command" | "nmc" => {portscan_controls::build_nmap_command(&active_project); return None;} //"port scan command" | "psc" | "nmap command" | "nmc" => {portscan_controls::build_nmap_command(&active_project, &display); return (None, None);}
"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir); return None;}, //"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir, &display); return (None, None);},
"dns records" | "dr" => {let dns_handle = enumeration::run_dns_enumeration(&active_project, None, true); return dns_handle;}, //"dns records" | "dr" => {let dns_handle = enumeration::run_dns_enumeration(&active_project, None, true, , &display); return (Some(dns_handle), None);},
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => {let gobuster_handle = enumeration::bruteforce_subs(&active_project, None,None, true); return gobuster_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)},
"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 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 squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true); return twist_handle}, //"dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true, &display); return (Some(twist_handle), None)},
"print report information" | "pri" => {info_controls::print_report_information(&active_project); return None;}, //"print report information" | "pri" => {info_controls::print_report_information(&active_project, &display); return (None, None);},
"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path); return None;}, //"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path, &display); return (None, None);},
_ => {help(None); println!("\n\n unknown command."); return None;} //"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => {project_controls::separate_personal_work_projects(&config_path, &display); return (None, 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 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);},
//"show settings" | "print settings" | "shset" | "pset" => {configuration::print_settings(&settings, &display); return (None, None)},
_ => {help(None); println!("\n\n unknown command."); return (None, None);}
} }
} }
fn print_banner(banner: &str){ fn print_banner(banner: &str){
print!("{}", banner); print!("{}", banner.custom_color((255,165,0)));
} }
pub fn cli(interactive: bool, #[allow(unused)]
mut projects: Vec<Project>, pub fn cli(mut projects: &mut Vec<Project>, config_path: &PathBuf) {
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,
vault_name: String) {
let mut threads = Vec::new(); let mut threads = Vec::new();
if interactive{ let mut loopize = true;
let mut loopize = true; let mut work_loaded = true;
let banner = " let mut workspace_config_path = config_path.clone();
let mut workspace_settings_path = config_path.clone();
workspace_config_path.pop();
workspace_settings_path.pop();
let mut project_conf_path = config_path.clone();
let mut success_message = String::new();
project_conf_path.pop();
project_conf_path.push("projects.work");
let worksapces_in_use = project_conf_path.exists();
if worksapces_in_use{
work_loaded = get_user_input("is thie loading your work projects?").to_lowercase().contains("y");
}
let banner = "
,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,'''' ,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,''''
,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,'' ,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,''
,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,' ,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,'
@@ -296,11 +340,17 @@ pub fn cli(interactive: bool,
"; ";
print_banner(banner); print_banner(banner);
while loopize{ while loopize{
project_controls::save_projects(&projects, &config_path); let settings = configuration::load_config(config_path);
let active_project = get_active_project(&projects); project_controls::save_projects(&projects, &config_path, &true);
let current_information = format!(" let active_project_res = get_active_project(&projects);
if active_project_res.is_none(){
println!("{}", "failed to get active project!".red());
return;
}
let active_project = active_project_res.unwrap();
let current_information = format!("
Active Project: {}, {} Active Project: {}, {}
Project Status: {} Project Status: {}
Files Folder: {} Files Folder: {}
@@ -311,30 +361,94 @@ Obsidian URI: {}
for help enter help or ?. for information about a specific command enter help (command) for help enter help or ?. for information about a specific command enter help (command)
", active_project.customer, active_project.project_name, active_project.stage, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, "coming soon"); ", active_project.customer.green(), active_project.project_name.green(), active_project.stage.green(), active_project.files_folder.display().to_string().green(), active_project.notes_folder.display().to_string().green(), active_project.boxname.green(), "coming soon".red());
let prompt = format!("\n{}:{}\nCommand?", active_project.customer, active_project.project_name); load_config(config_path);
let command = get_user_input(&prompt);
match command.as_str(){ let prompt = format!("\n{}:{}\nCommand?", active_project.customer.custom_color((255,165,0)), active_project.project_name.custom_color((255,165,0)));
"exit" => loopize = false, let command = get_user_input(&prompt);
"menu" | "main menu" | "mm" => {let menu_thread_option = menu::main_menu(&mut projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.clone(), cracking_rig.clone(), rockyou.clone(), rule.clone(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.clone()); if menu_thread_option.is_some(){for thread in menu_thread_option.unwrap(){threads.push(thread);}}}, if command.contains("switch work") || command.contains("switch to work projects"){
"print banner" | "banner" => print_banner(banner), work_loaded = true;
"clear" | "clear screen" | "cls" => {clear().unwrap(); print_banner(banner);}, }
"list threads" | "threads" | "lst" => println!("There are {} threads still running.", threads.len()), else if command.contains("switch personal") || command.contains("switch to personal projects"){
"info" => println!("{}", current_information), work_loaded = false;
_ => {let thread_option = run_command(command, &mut projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.clone(), cracking_rig.clone(), rockyou.clone(), rule.clone(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.clone()); if thread_option.is_some(){threads.push(thread_option.unwrap())}}, }
match command.as_str(){
"exit" => loopize = false,
"print banner" | "banner" => print_banner(banner),
"clear" | "clear screen" | "cls" => {clear().unwrap(); print_banner(banner);},
"list threads" | "threads" | "lst" => println!("There are {} threads still running.", threads.len()),
"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, &true);}
_ => {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);
if get_user_input("do you want to stop all the boxes?").contains("y"){
box_controls::stop_all_boxes(&projects);
}
print_informational("saving workspace projects...");
let worksapces_in_use = project_conf_path.exists();
if worksapces_in_use{
if work_loaded{
print_informational("saving projects.work");
workspace_config_path.push("projects.work");
workspace_settings_path.push("conf.working");
success_message = String::from("projects.conf saved to projects.work\nconf saved to conf.working");
}
else{
print_informational("saving projects.personal");
workspace_config_path.push("projects.personal");
workspace_settings_path.push("conf.personal");
success_message = String::from("projects.conf saved to projects.personal\nconf saved to conf.personal");
}
let open_res = OpenOptions::new().create(true).write(true).open(workspace_config_path);
if open_res.is_err(){
print_error("error opeing workspace config file!", open_res.err().unwrap().to_string());
}
else{
project_conf_path.pop();
project_conf_path.push("projects.conf");
let mut workspace_config_file = open_res.unwrap();
let projects_read_res = read_to_string(project_conf_path);
if projects_read_res.is_ok(){
let project_string = projects_read_res.unwrap();
let write_res = write!(workspace_config_file, "{}", project_string);
if write_res.is_err(){
print_error("error writing workspace config file!", write_res.err().unwrap().to_string());
}
}
else{
print_error("error reading projects config file!", projects_read_res.err().unwrap().to_string());
} }
} }
project_controls::save_projects(&projects, &config_path); let remove_res = fs::remove_file(&workspace_settings_path);
if get_user_input("do you want to stop all the boxes?").contains("y"){ if remove_res.is_err(){
box_controls::stop_all_boxes(&projects); print_error("error removing to save over workspace settings!", remove_res.err().unwrap().to_string());
} }
else{
remove_res.unwrap();
let copy_res = fs::copy(config_path, &workspace_settings_path);
if copy_res.is_err(){
print_error("error copying worksapce settings!", copy_res.err().unwrap().to_string());
}
}
print_success(success_message);
} }
if threads.len() > 0{ if threads.len() > 0{
println!("closing threads..."); println!("closing threads...");
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{
let _ = thread.join(); if thread.is_some(){
thread.unwrap().join().unwrap();
}
} }
} }
if worksapces_in_use{
print_success("projects saved to projects.conf, workspace projects updated, workspace settings saved, threads finished. pentest_tool OUT!");
}
else{
print_success("projects saved to projects.conf, threads finished. pentest_tool OUT!");
}
} }

View File

@@ -1,7 +1,8 @@
use std::path::PathBuf; use std::{collections::HashMap, path::PathBuf};
use std::fs::read_to_string; use std::fs::read_to_string;
use std::io::Write; use std::io::Write;
use crate::{get_user_input, open_overwrite}; use colored::Colorize;
use crate::{get_user_input, open_overwrite, tableize};
@@ -138,11 +139,50 @@ vault_name:{}
let write_res= write!(config_file, "{}", new_config); let write_res= write!(config_file, "{}", new_config);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("error writing config file!"); println!("{}","error writing config file!".red());
println!("{}", error); println!("{}", error.to_string().red());
println!("nothing was saved..."); println!("nothing was saved...");
return; return;
} }
write_res.unwrap(); write_res.unwrap();
} }
}
pub fn load_config(config: &PathBuf) -> HashMap<&'static str, String>{
let mut settings_map = HashMap::new();
let settings_string = read_to_string(&config).expect("error reading config file");
let settings: Vec<&str> = settings_string.split("\n").collect();
for line in settings{
if line.len() > 1{
let setting_vec: Vec<&str> = line.split(":").collect();
match setting_vec[0]{
"Project_files" => {settings_map.insert("project_files", setting_vec[1].trim_end().to_owned());},
"Project_notes" => {settings_map.insert("project_notes", setting_vec[1].trim_end().to_owned());},
"tools_folder" => {settings_map.insert("tools_folder",setting_vec[1].trim_end().to_owned());},
"upcoming_files" => {settings_map.insert("upcoming_files",setting_vec[1].trim_end().to_owned());},
"upcoming_notes" => {settings_map.insert("upcoming_notes",setting_vec[1].trim_end().to_owned());},
"box_template" => {settings_map.insert("box_template", setting_vec[1].trim_end().to_owned());},
"terminal" => {settings_map.insert("terminal_command", setting_vec[1].trim_end().to_owned());},
"cracking_rig" => {settings_map.insert("cracking_rig", setting_vec[1].trim_end().to_owned());},
"rockyou_location" => {settings_map.insert("rockyou", setting_vec[1].trim_end().to_owned());},
"rule_location" => {settings_map.insert("rule", setting_vec[1].trim_end().to_owned());},
"pass_file"=> {settings_map.insert("pass_spray_file", setting_vec[1].trim_end().to_owned());},
"fingerprint" => {settings_map.insert("fingerprint", setting_vec[1].trim_end().to_owned());},
"vault_name" => {settings_map.insert("vault_name", setting_vec[1].trim_end().to_owned());},
_ => println!("error unknown setting: {}", setting_vec[0])
}
}
}
return settings_map;
}
pub fn print_settings(settings: &HashMap<&str, String>){
let mut lines = Vec::new();
lines.push(String::from("Settings||value"));
for setting in settings.keys(){
let new_line = format!("{}||{}", setting, settings[setting]);
lines.push(new_line);
}
tableize(lines, &true);
} }

View File

@@ -4,10 +4,14 @@ use std::thread::JoinHandle;
use std::thread::{spawn, sleep}; use std::thread::{spawn, sleep};
use std::io::Write; use std::io::Write;
use std::time::Duration; use std::time::Duration;
use colored::Colorize;
use dns_lookup::lookup_host; use dns_lookup::lookup_host;
use crate::get_user_input; use crate::get_user_input;
use crate::Project; use crate::Project;
use crate::open_append; use crate::open_append;
use crate::print_error;
use crate::print_success;
use crate::print_informational;
#[allow(unused)] #[allow(unused)]
pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>>, standalone: bool) -> Option<JoinHandle<()>>{ pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>>, standalone: bool) -> Option<JoinHandle<()>>{
@@ -52,8 +56,8 @@ pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>
.output(); .output();
if output_res.is_err(){ if output_res.is_err(){
let error = output_res.err().unwrap(); let error = output_res.err().unwrap();
println!("From DNS Enumeration Thread: error running dnsrecon in the project's distrobox!"); println!("{}", "From DNS Enumeration Thread: error running dnsrecon in the project's distrobox!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
println!("sleping for 10 seconds to allow for sudo password input."); println!("sleping for 10 seconds to allow for sudo password input.");
@@ -62,9 +66,10 @@ pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>
if output_string_res.is_err(){ if output_string_res.is_err(){
let error = output_string_res.err().unwrap(); let error = output_string_res.err().unwrap();
println!("From DNS Enumeration Thread: error reading output data!"); println!("From DNS Enumeration Thread: error reading output data!");
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
print_success("DNS Enumeration Done, Writing to file...");
let output_string = output_string_res.unwrap(); let output_string = output_string_res.unwrap();
let lines: Vec<&str> = output_string.split("\n").collect(); let lines: Vec<&str> = output_string.split("\n").collect();
let mut out_data = String::new(); let mut out_data = String::new();
@@ -109,8 +114,8 @@ pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>
if standalone{ if standalone{
out_data.push_str("\n---\n"); out_data.push_str("\n---\n");
} }
println!("From DNS Enumeration Thread: Finished gathering data for {} writing to notes...", domain);
write!(enumeration_file, "{}", &out_data).unwrap(); write!(enumeration_file, "{}", &out_data).unwrap();
print_success("DNS Records: Gathered | Notes: Written | DNS Record Thread OUT!");
let remove_res = remove_file("dns_temp.csv"); let remove_res = remove_file("dns_temp.csv");
if remove_res.is_err(){ if remove_res.is_err(){
println!("From DNS Enumeration Thread: error removing temporay data file!"); println!("From DNS Enumeration Thread: error removing temporay data file!");
@@ -128,8 +133,7 @@ pub fn bruteforce_subs(project: &Project, given_domains: Option<&Vec<String>>, g
let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path); let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path);
if enumeration_file_res.is_err(){ if enumeration_file_res.is_err(){
let error = enumeration_file_res.err().unwrap(); let error = enumeration_file_res.err().unwrap();
println!("error opening enumeration notes file!"); print_error("FROM GOBUSTER THREAD: error opening enumeration notes file!", error.to_string());
println!("{}", error);
return None; return None;
} }
let mut enumeration_file = enumeration_file_res.unwrap(); let mut enumeration_file = enumeration_file_res.unwrap();
@@ -182,17 +186,45 @@ pub fn bruteforce_subs(project: &Project, given_domains: Option<&Vec<String>>, g
.output(); .output();
if gobuster_cmd_res.is_err(){ if gobuster_cmd_res.is_err(){
let error = gobuster_cmd_res.err().unwrap(); let error = gobuster_cmd_res.err().unwrap();
println!("From gobuster thread: Error running gobuster command!"); println!("{}","From gobuster thread: Error running gobuster command!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
println!("sleeping for 10 seconds to allow for sudo password input."); print_informational("sleeping for 10 seconds to allow for sudo password input.");
sleep(Duration::from_secs(10)); sleep(Duration::from_secs(10));
let gobuser_output = gobuster_cmd_res.unwrap().stdout; let gobuser_output = gobuster_cmd_res.unwrap().stdout;
println!("From Gobuster Thread: Sudomain enumeration Done!");
let gobuster_string = String::from_utf8_lossy(&gobuser_output); let gobuster_string = String::from_utf8_lossy(&gobuser_output);
let mut final_string = String::new();
if gobuster_string.contains("specify the '--wildcard' switch"){
let gobuster_cmd_res = Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(working_project.boxname.to_owned())
.arg("--")
.arg("gobuster")
.arg("dns")
.arg("-d")
.arg(&domain)
.arg("-w")
.arg(wordlist.to_owned())
.arg("--wildcard")
.output();
if gobuster_cmd_res.is_err(){
let error = gobuster_cmd_res.err().unwrap();
println!("{}","From gobuster thread: Error running gobuster command!".red());
println!("{}", error.to_string().red());
return;
}
let new_gobuser_output = gobuster_cmd_res.unwrap().stdout;
let new_gobuser_string = String::from_utf8_lossy(&new_gobuser_output);
final_string = new_gobuser_string.to_string();
}
else{
final_string = gobuster_string.to_string();
}
print_success("Gobuster enumeration Done!");
let mut domain_names = Vec::new(); let mut domain_names = Vec::new();
let lines: Vec<&str> = gobuster_string.split("\n").collect(); let lines: Vec<&str> = final_string.split("\n").collect();
for line in lines{ for line in lines{
if line.contains("Found:"){ if line.contains("Found:"){
let domain = line.split_whitespace().collect::<Vec<&str>>()[1]; let domain = line.split_whitespace().collect::<Vec<&str>>()[1];
@@ -218,11 +250,12 @@ pub fn bruteforce_subs(project: &Project, given_domains: Option<&Vec<String>>, g
let write_res = write!(enumeration_file, "{}", out_data); let write_res = write!(enumeration_file, "{}", out_data);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("FROM Gobuster Thread: error writing notes!"); println!("{}","FROM Gobuster Thread: error writing notes!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
write_res.unwrap(); write_res.unwrap();
print_success("Subdomains: Bruteforced | Enumeration notes: Written | Gobuster thread out!");
}); });
return Some(gobuster_thread); return Some(gobuster_thread);
} }
@@ -233,8 +266,8 @@ pub fn dns_squatting(project: &Project, given_domains: Option<&Vec<String>>, sta
let open_enumeration_notes_res = OpenOptions::new().append(true).create(true).open(enumeration_notes); let open_enumeration_notes_res = OpenOptions::new().append(true).create(true).open(enumeration_notes);
if open_enumeration_notes_res.is_err(){ if open_enumeration_notes_res.is_err(){
let error = open_enumeration_notes_res.err().unwrap(); let error = open_enumeration_notes_res.err().unwrap();
println!("Error opening enumeration notes"); println!("{}","Error opening enumeration notes".red());
println!("{}", error); println!("{}", error.to_string().red());
return None; return None;
} }
let mut enumeration_file = open_enumeration_notes_res.unwrap(); let mut enumeration_file = open_enumeration_notes_res.unwrap();
@@ -258,8 +291,8 @@ pub fn dns_squatting(project: &Project, given_domains: Option<&Vec<String>>, sta
let write_res = write!(enumeration_file, "### Domain Squatting\n"); let write_res = write!(enumeration_file, "### Domain Squatting\n");
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("error writing to enumeration notes file!"); println!("{}","error writing to enumeration notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
write_res.unwrap(); write_res.unwrap();
@@ -280,11 +313,11 @@ pub fn dns_squatting(project: &Project, given_domains: Option<&Vec<String>>, sta
.output(); .output();
if twist_output.is_err(){ if twist_output.is_err(){
let error = twist_output.err().unwrap(); let error = twist_output.err().unwrap();
println!("From DNSTwist thread: Error running dnstwist command!"); println!("{}","From DNSTwist thread: Error running dnstwist command!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
println!("sleeping for 10 seconds to allow for sudo password input."); print_informational("sleeping for 10 seconds to get sudo password.");
sleep(Duration::from_secs(10)); sleep(Duration::from_secs(10));
let twist_output_vec = twist_output.unwrap().stdout; let twist_output_vec = twist_output.unwrap().stdout;
let output_string = String::from_utf8_lossy(&twist_output_vec); let output_string = String::from_utf8_lossy(&twist_output_vec);
@@ -300,6 +333,7 @@ pub fn dns_squatting(project: &Project, given_domains: Option<&Vec<String>>, sta
} }
} }
}); });
print_success("Domains: Squatted | Notes: Written | DNSTwist thread OUT!");
return Some(squatting_thread); return Some(squatting_thread);
} }
@@ -309,8 +343,8 @@ pub fn do_all_dns_enumeration(project: &Project) -> Option<JoinHandle<()>>{
let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path); let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path);
if enumeration_file_res.is_err(){ if enumeration_file_res.is_err(){
let error = enumeration_file_res.err().unwrap(); let error = enumeration_file_res.err().unwrap();
println!("error opening enumeration notes file!"); println!("{}","error opening enumeration notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return None; return None;
} }
let mut enumeration_file = enumeration_file_res.unwrap(); let mut enumeration_file = enumeration_file_res.unwrap();
@@ -325,14 +359,15 @@ pub fn do_all_dns_enumeration(project: &Project) -> Option<JoinHandle<()>>{
} }
} }
let wordlist = get_user_input("path to wordlist for sub domain bruteforcing?"); let wordlist = get_user_input("path to wordlist for sub domain bruteforcing?");
print_informational("target data gathered. Spawning threads to do enumeration...");
let working_project = project.clone(); let working_project = project.clone();
let all_dns_handle = spawn(move ||{ let all_dns_handle = spawn(move ||{
let mut write_success = true; let mut write_success = true;
let write_res = write!(enumeration_file, "# DNS Enumeration\n"); let write_res = write!(enumeration_file, "# DNS Enumeration\n");
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("From All DNS thread: Error writing notes file!"); println!("{}","From All DNS thread: Error writing notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
write_success = false; write_success = false;
} }
if write_success{ if write_success{
@@ -356,6 +391,7 @@ pub fn do_all_dns_enumeration(project: &Project) -> Option<JoinHandle<()>>{
} }
write!(enumeration_file, "\n---\n").unwrap(); write!(enumeration_file, "\n---\n").unwrap();
} }
print_success("All DNS Enum threads finished, notes have been written. DNS Enumeration Thread OUT!");
} }
}); });
return Some(all_dns_handle); return Some(all_dns_handle);

498
pentest_tool/src/gui.rs Normal file
View File

@@ -0,0 +1,498 @@
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

@@ -8,6 +8,7 @@ use std::path::PathBuf;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::io::stdin; use std::io::stdin;
use colored::Colorize;
use walkdir::WalkDir; use walkdir::WalkDir;
use clearscreen::clear; use clearscreen::clear;
use clearscreen; use clearscreen;
@@ -33,8 +34,8 @@ pub fn run_initial_enum(project: &Project){
let csv_read_res = fs::read_to_string(&csv_path); let csv_read_res = fs::read_to_string(&csv_path);
if csv_read_res.is_err(){ if csv_read_res.is_err(){
let error = csv_read_res.err().unwrap(); let error = csv_read_res.err().unwrap();
println!("error reading csv!"); println!("{}","error reading csv!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let csv_data = csv_read_res.unwrap(); let csv_data = csv_read_res.unwrap();
@@ -70,16 +71,16 @@ pub fn run_initial_enum(project: &Project){
let host_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&host_notes_path); let host_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&host_notes_path);
if host_notes_open_res.is_err(){ if host_notes_open_res.is_err(){
let error = host_notes_open_res.err().unwrap(); let error = host_notes_open_res.err().unwrap();
println!("error opening host notes file!"); println!("{}","error opening host notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let host_notes = host_notes_open_res.unwrap(); let host_notes = host_notes_open_res.unwrap();
let attack_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&attack_notes_path); let attack_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&attack_notes_path);
if attack_notes_open_res.is_err(){ if attack_notes_open_res.is_err(){
let error = attack_notes_open_res.err().unwrap(); let error = attack_notes_open_res.err().unwrap();
println!("error opening attack notes!"); println!("{}","error opening attack notes!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
for target in targets.clone(){ for target in targets.clone(){
@@ -110,7 +111,7 @@ pub fn run_initial_enum(project: &Project){
if host_notes_read_res.is_err(){ if host_notes_read_res.is_err(){
let error = host_notes_read_res.err().unwrap(); let error = host_notes_read_res.err().unwrap();
println!("error reading host notes"); println!("error reading host notes");
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let host_notes_string = host_notes_read_res.unwrap(); let host_notes_string = host_notes_read_res.unwrap();
@@ -221,8 +222,8 @@ pub fn print_report_information(project: &Project){
let enumeration_read_res = fs::read_to_string(notes_path); let enumeration_read_res = fs::read_to_string(notes_path);
if enumeration_read_res.is_err(){ if enumeration_read_res.is_err(){
let error = enumeration_read_res.err().unwrap(); let error = enumeration_read_res.err().unwrap();
println!("error reading enumeration notes!"); println!("{}","error reading enumeration notes!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
let enumeration_text = enumeration_read_res.unwrap(); let enumeration_text = enumeration_read_res.unwrap();
@@ -752,7 +753,7 @@ pub fn get_mssql_column_names(project: &Project) -> Option<JoinHandle<()>>{
if netexec_cmd_res.is_err(){ if netexec_cmd_res.is_err(){
let error = netexec_cmd_res.err().unwrap(); let error = netexec_cmd_res.err().unwrap();
println!("error running netexec command!"); println!("error running netexec command!");
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
let output_string = String::from_utf8(netexec_cmd_res.unwrap().stdout).unwrap(); let output_string = String::from_utf8(netexec_cmd_res.unwrap().stdout).unwrap();
@@ -827,8 +828,8 @@ last
let gather_source = fs::read_to_string(gather_file); let gather_source = fs::read_to_string(gather_file);
if gather_source.is_err(){ if gather_source.is_err(){
let error = gather_source.err().unwrap(); let error = gather_source.err().unwrap();
println!("error reading gather contacts output!"); println!("{}","error reading gather contacts output!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let gather_source_string = gather_source.unwrap(); let gather_source_string = gather_source.unwrap();
@@ -854,15 +855,15 @@ last
let email_text_res = OpenOptions::new().append(true).create(true).open(email_text_path); let email_text_res = OpenOptions::new().append(true).create(true).open(email_text_path);
if email_text_res.is_err(){ if email_text_res.is_err(){
let error = email_text_res.err().unwrap(); let error = email_text_res.err().unwrap();
println!("error opening email text file!"); println!("{}","error opening email text file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let email_notes_res = OpenOptions::new().append(true).create(true).open(email_note_path); let email_notes_res = OpenOptions::new().append(true).create(true).open(email_note_path);
if email_notes_res.is_err(){ if email_notes_res.is_err(){
let error = email_notes_res.err().unwrap(); let error = email_notes_res.err().unwrap();
println!("error opeing email notes file!"); println!("{}","error opeing email notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let mut email_text_file = email_text_res.unwrap(); let mut email_text_file = email_text_res.unwrap();
@@ -871,8 +872,8 @@ last
let note_wriet_res = write!(email_note_file, "# Email Enumeration\n"); let note_wriet_res = write!(email_note_file, "# Email Enumeration\n");
if note_wriet_res.is_err(){ if note_wriet_res.is_err(){
let error = note_wriet_res.err().unwrap(); let error = note_wriet_res.err().unwrap();
println!("error writing to email notes file!"); println!("{}","error writing to email notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
write_success = false; write_success = false;
} }
if write_success{ if write_success{
@@ -901,8 +902,8 @@ pub fn get_scope_entries(project: &Project) -> Option<Vec<String>>{
let genera_read_res = read_to_string(general_path); let genera_read_res = read_to_string(general_path);
if genera_read_res.is_err(){ if genera_read_res.is_err(){
let error = genera_read_res.err().unwrap(); let error = genera_read_res.err().unwrap();
println!("ooof error reading your general notes file!"); println!("{}","ooof error reading your general notes file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return None; return None;
} }
let general_string = genera_read_res.unwrap(); let general_string = genera_read_res.unwrap();

View File

@@ -1,7 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::{File, create_dir_all, remove_dir_all}; use std::fs::{create_dir_all, remove_dir_all, File};
use std::io::Read; use std::io::Read;
use std::io::Write; use std::io::Write;
use std::env;
use std::io::copy; use std::io::copy;
use std::process::Command; use std::process::Command;
use std::time::Duration; use std::time::Duration;
@@ -9,8 +10,9 @@ use reqwest::blocking::get;
use std::{path::Path, path::PathBuf}; use std::{path::Path, path::PathBuf};
use std::thread; use std::thread;
use std::process::exit; use std::process::exit;
use colored::Colorize;
use crate::get_user_input; use crate::{get_user_input, print_informational, print_success};
#[allow(unused)] #[allow(unused)]
pub fn install(config_path: &PathBuf){ pub fn install(config_path: &PathBuf){
@@ -51,8 +53,8 @@ pub fn install(config_path: &PathBuf){
let create_res = create_dir_all(folder); let create_res = create_dir_all(folder);
if create_res.is_err(){ if create_res.is_err(){
let error = create_res.err().unwrap(); let error = create_res.err().unwrap();
println!("error creating folder {}", folder.display()); println!("{}{}","error creating folder ".red(), folder.display().to_string().red());
println!("{}", error); println!("{}", error.to_string().red());
println!("you'll need to create this manually after the install is done!"); println!("you'll need to create this manually after the install is done!");
folder_creation = false; folder_creation = false;
} }
@@ -63,12 +65,12 @@ pub fn install(config_path: &PathBuf){
let distrobox_run_res = Command::new("distrobox").arg("list").arg("--root").output(); let distrobox_run_res = Command::new("distrobox").arg("list").arg("--root").output();
if distrobox_run_res.is_err(){ if distrobox_run_res.is_err(){
let error = distrobox_run_res.err().unwrap(); let error = distrobox_run_res.err().unwrap();
println!("Distrobox file was not found!"); println!("{}","Distrobox file was not found!".red());
println!("This usually means that distrobox is not installed."); println!("{}","This usually means that distrobox is not installed.".red());
println!("please install distrobox, if you're on kali run `sudo apt install distrobox`"); println!("{}","please install distrobox, if you're on kali run `sudo apt install distrobox`".red());
println!("{}", error); println!("{}", error.to_string().red());
println!("this project heavily relies on distrobox, as its primarily a distrobox mangement tool."); println!("{}","this project heavily relies on distrobox, as its primarily a distrobox mangement tool.".red());
println!("cleaning up up configuration folders, please install distrobox and re-run this program."); println!("{}","cleaning up up configuration folders, please install distrobox and re-run this program.".red());
let cleanup = remove_dir_all(&del_on_fail); let cleanup = remove_dir_all(&del_on_fail);
if cleanup.is_err(){ if cleanup.is_err(){
println!("error cleaning up configuration folder!"); println!("error cleaning up configuration folder!");
@@ -118,9 +120,9 @@ pub fn install(config_path: &PathBuf){
.status(); .status();
if template_box_create_res.is_err(){ if template_box_create_res.is_err(){
let error = template_box_create_res.err().unwrap(); let error = template_box_create_res.err().unwrap();
println!("error creating template box!"); println!("{}","error creating template box!".red());
println!("{}", error); println!("{}", error.to_string().red());
println!("\n\n\nplese create it yourself with the following command."); println!("{}","\n\n\nplese create it yourself with the following command.".red());
println!("\n\ndistrobox create --root --image {}, --name {}, --init --volume {}", &box_image, &template_box_name, &tool_volume); println!("\n\ndistrobox create --root --image {}, --name {}, --init --volume {}", &box_image, &template_box_name, &tool_volume);
} }
else{ else{
@@ -212,15 +214,15 @@ vault_name:{}"
let project_conf_res = File::create_new(&projects_conf_path); let project_conf_res = File::create_new(&projects_conf_path);
if project_conf_res.is_err(){ if project_conf_res.is_err(){
let error = project_conf_res.err().unwrap(); let error = project_conf_res.err().unwrap();
println!("ooof error creating the projects configuration file."); println!("{}","ooof error creating the projects configuration file.".red());
println!("try creating it manually!"); println!("{}","try creating it manually!".red());
println!("copy the following configuration and save it to {}", &projects_conf_path.display()); println!("copy the following configuration and save it to {}", &projects_conf_path.display());
println!("customer:name:notes:files:active:time:box_name:stage"); println!("customer:name:notes:files:active:time:box_name:stage");
println!("default:default:{}:{}:yes:{}:current", &current_notes.display(), &current_projects.display(), &template_box_name); println!("default:default:{}:{}:yes:{}:current", &current_notes.display(), &current_projects.display(), &template_box_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, "customer:name:notes:files:active:time:box_name:stage\ndefault:default:{}:{}:yes:{}:current", &current_notes.display(), &current_projects.display(), &template_box_name); let project_write_res = write!(project_conf_file, "Projects Config File");
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);
@@ -269,6 +271,35 @@ vault_name:{}"
exit(1); exit(1);
} }
password_write_res.unwrap(); password_write_res.unwrap();
println!("install completed successfully!"); let current_path_res = env::current_exe();
println!("re-run this to launch!"); let mut copied_to_path = false;
if current_path_res.is_ok(){
let current_path = current_path_res.unwrap();
let mut new_path = PathBuf::from("/usr/bin/pentest_tool");
print_informational("We ar going to try and copy this executable to a location on your $PATH");
print_informational("the default location is /usr/bin/pentest_tool");
if get_user_input("is this ok?").contains("n"){
new_path.clear();
new_path.push(get_user_input("ooof, ok. Please enter where you'd like to save it on your $PATH"));
if !new_path.display().to_string().contains("pentest_tool"){
new_path.push("pentest_tool");
}
}
let copy_cmd_res = Command::new("sudo").arg("cp").arg(current_path.display().to_string()).arg(new_path.display().to_string()).status();
if copy_cmd_res.is_ok(){
let copy_cmd_status = copy_cmd_res.unwrap();
if copy_cmd_status.success(){
copied_to_path = true;
}
}
}
if !copied_to_path{
print_informational("we could not copy this executable to your path!");
print_informational("please copy this file to somewhere on your $PATH.");
print_informational("for example `cp pentest_tool /usr/bin/pentest_tool");
print_success("otherwise this tool is ready to go, you would just need to launch it from this folder.");
}
else{
print_success("install completed successfully!");
}
} }

View File

@@ -1,9 +1,12 @@
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;
#[derive(Clone)] #[derive(Debug, Clone)]
pub struct Project{ pub struct Project{
pub customer: String, pub customer: String,
pub project_name: String, pub project_name: String,
@@ -21,19 +24,148 @@ 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;
pub fn print_error(message: &str ,error: String){
println!("{}", message.red());
println!("{}", error.red());
}
pub fn print_success<T>(message: T) where T: AsRef<str> {
println!("{}", message.as_ref().green());
}
pub fn print_informational<T>(message: T) where T: AsRef<str>{
println!("{}", message.as_ref().custom_color((255,165,0)));
}
pub fn tableize(given_lines: Vec<String>, display: &bool) -> String{
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...
// I want to try to figure out why its getten eaten, but just needed to get it working for now.
let mut lines = Vec::new();
let mut junk_line = format!("{}", "junk||".repeat(column_count));
junk_line.pop();
junk_line.pop();
for line in given_lines{
lines.push(line);
}
lines.insert(1,junk_line);
// end of junk line logic.
let (terminal_width, _terminal_height) = term_size::dimensions().unwrap();
let mut column_sizes:HashMap<usize, usize> = HashMap::new();
for column_number in 0..column_count{
column_sizes.insert(column_number, 0);
}
let mut longest_column = 0;
for line in &lines{
let cells: Vec<&str> = line.split("||").collect();
let mut current_cell: usize = 0;
for cell in cells{
let cell_length = cell.len() + 2;
if column_sizes[&current_cell] < cell_length{
column_sizes.insert(current_cell, cell_length);
}
if cell_length > longest_column{
longest_column = current_cell;
}
current_cell += 1;
}
if *display{
let longest_line = (column_count*2) - 1;
if longest_line > terminal_width{
let difference = longest_line - terminal_width - 3;
column_sizes.insert(longest_column, column_sizes[&longest_column] - difference);
}
}
}
let mut header = String::new();
let mut outdata = String::new();
let mut count = 0;
let mut separater = String::new();
let mut ending = String::new();
if *display{
ending = format!("{}\n", "|".green());
}
else{
ending = format!("{}\n", "|");
}
for line in lines{
count += 1;
//println!("{}", line);
let mut add_ending = false;
let data_vec: Vec<&str> = line.split("||").collect();
let mut column_numbers: Vec<&usize> = column_sizes.keys().collect();
column_numbers.sort_by(|a, b| a.cmp(b));
for column in column_numbers{
let mut data_to_add = String::new();
let mut data_vec_len = data_vec[*column].len();
if *display{
if data_vec_len > column_sizes[&longest_column]{
while data_vec_len > column_sizes[&longest_column]{
data_vec_len = data_vec_len / 2;
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);
}
}
}
else{
data_to_add = String::from(data_vec[*column]);
}
let padding = column_sizes[column] - data_vec_len;
if *display{
if count == 1{
let formatted_cell = format!("{} {}{}", "|".green(), data_vec[*column].bold().green(), " ".repeat(padding));
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{
println!("no display");
if count == 1{
let formatted_cell = format!("{} {}{}", "|", data_vec[*column], " ".repeat(padding));
header.push_str(&formatted_cell);
}
else if count == 2 {
let formatted_cell = format!("{} {} ", "|", "-".repeat(column_sizes[column] - 1));
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{
outdata.push_str(&ending)
}
}
outdata.push_str(&separater);
outdata.push_str(&ending);
let print_output = format!("{}{}{}{}{}", header, ending, separater, ending, outdata);
return print_output;
}
pub fn open_overwrite(path: &PathBuf) -> Option<File>{ pub fn open_overwrite(path: &PathBuf) -> Option<File>{
let file_create_res = fs::OpenOptions::new().create(true).write(true).open(path); let file_create_res = fs::OpenOptions::new().create(true).write(true).truncate(true).open(path);
if file_create_res.is_err(){ if file_create_res.is_err(){
let error = file_create_res.err().unwrap(); let error = file_create_res.err().unwrap();
println!("error opening {} file!", path.display()); println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
println!("{}", error); println!("{}", error.to_string().red());
return None; return None;
} }
else { else {
@@ -46,8 +178,8 @@ pub fn open_append(path: &PathBuf) -> Option<File>{
let file_create_res = fs::OpenOptions::new().create(true).append(true).open(path); let file_create_res = fs::OpenOptions::new().create(true).append(true).open(path);
if file_create_res.is_err(){ if file_create_res.is_err(){
let error = file_create_res.err().unwrap(); let error = file_create_res.err().unwrap();
println!("error opening {} file!", path.display()); println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
println!("{}", error); println!("{}", error.to_string().red());
return None; return None;
} }
else { else {
@@ -74,7 +206,7 @@ pub fn get_user_input(prompt: &str) -> String{
fn main() { fn main() {
print!(" print!("{}","
⠀⠀⠀⣠⠶⠚⠛⠛⠛⠲⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⣠⠶⠚⠛⠛⠛⠲⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣠⣾⣷⣄⠀⠀⠀⢀⣠⣤⣤⡀⠀⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⣠⣾⣷⣄⠀⠀⠀⢀⣠⣤⣤⡀⠀⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
@@ -93,7 +225,7 @@ fn main() {
⠀⠀⠀⠀⣀⡀⠀⣰⠇⣾⠀⠀⠈⣩⣥⣄⣿⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⣀⡀⠀⣰⠇⣾⠀⠀⠈⣩⣥⣄⣿⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
"); ".red());
let mut config_path = PathBuf::new(); let mut config_path = PathBuf::new();
let user_dirs_res = UserDirs::new(); let user_dirs_res = UserDirs::new();
if user_dirs_res.is_none(){ if user_dirs_res.is_none(){
@@ -115,55 +247,38 @@ fn main() {
if config_path.as_path().exists() == false{ if config_path.as_path().exists() == false{
install::install(&config_path); install::install(&config_path);
} }
let mut project_base_folder = PathBuf::new();
let mut project_base_notes = PathBuf::new();
let mut tools_folder = PathBuf::new();
let mut terminal_command = String::new();
let mut box_template = String::new();
let mut cracking_rig = String::new();
let mut rockyou = String::new();
let mut rule = String::new();
let mut upcoming_files = PathBuf::new();
let mut upcoming_notes = PathBuf::new();
let mut pass_spray_file = PathBuf::new();
let mut fingerprint = false;
let mut vault_name = String::new();
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 = configuration::load_config(&config_path);
let settings: Vec<&str> = settings_string.split("\n").collect(); for setting in settings.keys(){
for line in settings{ println!("{}: {}", setting, settings[setting].green());
if line.len() > 1{ }
let setting_vec: Vec<&str> = line.split(":").collect(); println!("{}","loading project configs...".green());
match setting_vec[0]{ let projects_res = project_controls::get_projects(&config_path, true);
"Project_files" => project_base_folder.push(setting_vec[1].trim_end()), if projects_res.is_none(){
"Project_notes" => project_base_notes.push(setting_vec[1].trim_end()), println!("{}", "ERROR NO PROJECTS LOADED!!!".red());
"tools_folder" => tools_folder.push(setting_vec[1].trim_end()), println!("{}", "CHECK YOUR PROJECTS.CONF FILE".red());
"upcoming_files" => upcoming_files.push(setting_vec[1].trim_end()), return;
"upcoming_notes" => upcoming_notes.push(setting_vec[1].trim_end()), }
"box_template" => box_template = setting_vec[1].trim_end().to_owned(), let mut projects = projects_res.unwrap();
"terminal" => terminal_command = setting_vec[1].trim_end().to_owned(), let help_text = format!("
"cracking_rig" => cracking_rig = setting_vec[1].trim_end().to_owned(), pentest_tool -> launch cli
"rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(), pentest_tool gui -> launch gui
"rule_location" => rule = setting_vec[1].trim_end().to_owned(), pentest_tool anything else -> display this help
"pass_file"=> pass_spray_file.push(setting_vec[1]), ");
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}}, let args: Vec<String> = args().collect();
"vault_name" => vault_name = setting_vec[1].trim_end().to_owned(), if args.len() == 1{
_ => println!("error unknown setting: {}", setting_vec[0]) 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();
} }
} }
print!(" else {
Project Folders: {} println!("{}", help_text);
Note Folders: {} }
Tools Folder: {}
distrobox template: {}
terminal_command: {}
cracking_rig: {}\n
upcoming project folders: {}
upcoming project notes: {}
", &project_base_folder.display(), &project_base_notes.display(), &tools_folder.display(), box_template, terminal_command, cracking_rig, &upcoming_files.display(), &upcoming_notes.display());
println!("loading project configs...");
let projects = project_controls::get_projects(&config_path, true);
let _continue = get_user_input("press enter to load command line interface.");
cli::cli(true, 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, vault_name);
} }

View File

@@ -1,321 +0,0 @@
use std::path::PathBuf;
use std::thread::JoinHandle;
use clearscreen::clear;
use clearscreen;
use crate::get_user_input;
use crate::Project;
use crate::cli;
pub fn main_menu(projects: &mut 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,
vault_name: String) -> Option<Vec<JoinHandle<()>>>{
let mut loopize = true;
let mut threads = Vec::new();
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!("
{}
___ ___ _ ___ ___
| \\/ | (_) | \\/ | _
| . . | __ _ _ _ __ | . . | ___ _ __ _ _(_)
| |\\/| |/ _` | | '_ \\ | |\\/| |/ _ \\ '_ \\| | | |
| | | | (_| | | | | | | | | | __/ | | | |_| |_
\\_| |_/\\__,_|_|_| |_| \\_| |_/\\___|_| |_|\\__,_(_)
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
\n", banner);
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"2" => {let thread_option = cli::run_command("list projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"3" => {let thread_option = cli::run_command("switch project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"5" => {let thread_option = cli::run_command("save projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"6" => {let thread_option = cli::run_command("import project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"7" => {let thread_option = cli::run_command("remove project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"9" => {let thread_option = cli::run_command("promote project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"10" => {let thread_option = cli::run_command("new terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"15" => {let thread_option = cli::run_command("initial enum".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"16" => {let thread_option = cli::run_command("build attack notes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"17" => {let thread_option = cli::run_command("host discovery".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"18" => {let thread_option = cli::run_command("port scan".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"19" => {let thread_option = cli::run_command("parse port scan".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"20" => {let thread_option = cli::run_command("stop boxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"21" => {let thread_option = cli::run_command("password spray".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"22" => {let thread_option = cli::run_command("bloodhound".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"23" => {let thread_option = cli::run_command("parse gather contacts".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"24" => {let thread_option = cli::run_command("prune distroboxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"25" => {let thread_option = cli::run_command("dns records".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"26" => {let thread_option = cli::run_command("brute force subdomains".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"27" => {let thread_option = cli::run_command("dns enumeration".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"28" => {let threads_option = external_menu(banner, projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.clone(), cracking_rig.clone(), rockyou.clone(), rule.clone(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.clone()); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread)}}},
"29" => {let threads_option = internal_menu(banner, projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.clone(), cracking_rig.clone(), rockyou.clone(), rule.clone(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.clone()); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread)}}},
"30" => loopize = false,
_ => println!("unknown selection, try again!"),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
pub fn external_menu(
banner: &str,
projects: &mut 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,
vault_name: 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!("
{}
_____ _ _ ___ ___
| ___| | | | | | \\/ | _
| |____ _| |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
| __\\ \\/ / __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
| |___> <| || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
\\____/_/\\_\\\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
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
\n", banner);
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"2" => {let thread_option = cli::run_command("list projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"3" => {let thread_option = cli::run_command("switch project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"5" => {let thread_option = cli::run_command("save projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"6" => {let thread_option = cli::run_command("import project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"7" => {let thread_option = cli::run_command("remove project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"9" => {let thread_option = cli::run_command("promote project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"10" => {let thread_option = cli::run_command("new terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"12" => {let thread_option = cli::run_command("recreate distrobox".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"13" => {let thread_option = cli::run_command("generate userpass".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"14" => {let thread_option = cli::run_command("initial enum".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"15" => {let thread_option = cli::run_command("build attack notes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"26" => {let thread_option = cli::run_command("stop boxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"17" => {let thread_option = cli::run_command("password spray".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"18" => {let thread_option = cli::run_command("parse gather contacts".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"19" => {let thread_option = cli::run_command("prune distroboxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"20" => {let thread_option = cli::run_command("dns records".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"21" => {let thread_option = cli::run_command("brute force subdomains".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"22" => {let thread_option = cli::run_command("dns enumeration".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"23" => loopize = false,
_ => println!("unknown selection, try again!"),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
}
pub fn internal_menu(
banner: &str,
projects: &mut 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,
vault_name: 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!("
{}
_____ _ _ ___ ___
|_ _| | | | | | \\/ | _
| | _ __ | |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
| || '_ \\| __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
_| || | | | || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
\\___/_| |_|\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
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
\n", banner);
match get_user_input("selection?").as_str(){
"1" => {let thread_option = cli::run_command("show active project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"2" => {let thread_option = cli::run_command("list projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"3" => {let thread_option = cli::run_command("switch project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"5" => {let thread_option = cli::run_command("save projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"6" => {let thread_option = cli::run_command("import project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"7" => {let thread_option = cli::run_command("remove project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"9" => {let thread_option = cli::run_command("promote project".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"10" => {let thread_option = cli::run_command("new terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"15" => {let thread_option = cli::run_command("host discovery".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"16" => {let thread_option = cli::run_command("port scan".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"17" => {let thread_option = cli::run_command("parse port scan".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"18" => {let thread_option = cli::run_command("stop boxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"19" => {let thread_option = cli::run_command("password spray".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"20" => {let thread_option = cli::run_command("bloodhound".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"21" => {let thread_option = cli::run_command("prune distroboxes".to_owned(), projects, config_path.clone(), base_files, base_notes, tools_dir, boxtemplate.clone(), terminal.to_owned(), cracking_rig.to_owned(), rockyou.to_owned(), rule.to_owned(), upcoming_files, upcoming_notes, password_spray_file, fingerprint, vault_name.to_owned()); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
"22" => loopize = false,
_ => println!("unknown selection, try again!"),
}
}
if threads.len() > 0{
return Some(threads);
}
else{
return None;
}
}
}

View File

@@ -1,13 +1,14 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::{default, 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;
use std::process::Command; use std::process::Command;
use std::thread::{sleep, spawn, JoinHandle}; use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration; use std::time::Duration;
use colored::Colorize;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::get_user_input; use crate::{get_user_input, print_error, print_informational, print_success};
use crate::Project; use crate::Project;
use crate::open_overwrite; use crate::open_overwrite;
use crate::open_append; use crate::open_append;
@@ -55,8 +56,8 @@ pub fn parse_normal_nmap_output(project: &Project){
let file_read_res = fs::read_to_string(file_to_parse); let file_read_res = fs::read_to_string(file_to_parse);
if file_read_res.is_err(){ if file_read_res.is_err(){
let error = file_read_res.err().unwrap(); let error = file_read_res.err().unwrap();
println!("ooof error reading the file!"); println!("{}","ooof error reading the file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let nmap_string = file_read_res.unwrap(); let nmap_string = file_read_res.unwrap();
@@ -97,8 +98,8 @@ pub fn parse_normal_nmap_output(project: &Project){
let save_open_res = fs::OpenOptions::new().create(true).append(true).open(&save_path); let save_open_res = fs::OpenOptions::new().create(true).append(true).open(&save_path);
if save_open_res.is_err(){ if save_open_res.is_err(){
let error = save_open_res.err().unwrap(); let error = save_open_res.err().unwrap();
println!("oof error opening the save file!"); println!("{}","oof error opening the save file!".red());
println!("{}", error); println!("{}", error.to_string().red());
if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){ if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){
for host in &host_ports{ for host in &host_ports{
println!("{}", host); println!("{}", host);
@@ -112,8 +113,8 @@ pub fn parse_normal_nmap_output(project: &Project){
let tsv_open_res = fs::OpenOptions::new().create(true).append(true).open(save_path); let tsv_open_res = fs::OpenOptions::new().create(true).append(true).open(save_path);
if tsv_open_res.is_err(){ if tsv_open_res.is_err(){
let error = tsv_open_res.err().unwrap(); let error = tsv_open_res.err().unwrap();
println!("error opening tsv file!"); println!("{}","error opening tsv file!".red());
println!("{}", error); println!("{}", error.to_string().red());
if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){ if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){
for host in &host_ports{ for host in &host_ports{
println!("{}", host); println!("{}", host);
@@ -195,7 +196,7 @@ pub fn build_cmd_for_host_discovery(project: &Project){
let general_note_string = read_to_string(general_note_path); let general_note_string = read_to_string(general_note_path);
let mut _note_string = String::new(); let mut _note_string = String::new();
match general_note_string{ match general_note_string{
Err(error) => {println!("error reading file to string!! {}", error); return;}, Err(error) => {println!("{} {}", "error reading file to string!!".green(), error.to_string().green()); return;},
_=> _note_string = general_note_string.unwrap() _=> _note_string = general_note_string.unwrap()
} }
let lines: Vec<&str> = _note_string.split("\n").collect(); let lines: Vec<&str> = _note_string.split("\n").collect();
@@ -234,15 +235,36 @@ pub fn build_cmd_for_host_discovery(project: &Project){
final_command.push_str(">> ping_only_replies.txt &"); final_command.push_str(">> ping_only_replies.txt &");
} }
final_command.pop(); final_command.pop();
println!("{}", final_command); print_success(final_command);
} }
pub fn parse_csportscan(project: &Project){ pub fn parse_csportscan(project: &Project, given_tsv_path: Option<PathBuf>, given_save_path: Option<PathBuf>){
let mut tsv_path = project.files_folder.clone(); let mut tsv_path = PathBuf::new();
tsv_path.push("working/tsvs/services.tsv"); let mut outfile = PathBuf::new();
let mut outfile = tsv_path.clone(); if given_tsv_path.is_none(){
outfile.pop(); 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"){
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();
@@ -252,16 +274,11 @@ pub fn parse_csportscan(project: &Project){
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();
println!("ooof error reading tsv file!"); println!("{}","ooof error reading tsv file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
println!("tsv read, parsing lines..."); println!("tsv read, parsing lines...");
@@ -312,12 +329,7 @@ pub fn parse_csportscan(project: &Project){
} }
} }
} }
println!("is {} where you want to save your files?", outfile.display()); let host_number_results = format!("
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."));
}
print!("
{} Windows hosts found! {} Windows hosts found!
{} SSH hosts found! {} SSH hosts found!
{} FTP hosts found! {} FTP hosts found!
@@ -327,7 +339,8 @@ pub fn parse_csportscan(project: &Project){
{} RDP hosts found! {} RDP hosts found!
{} untagged hosts found! {} untagged hosts found!
", windows_hosts.len(), ssh_hosts.len(), ftp_hosts.len(), telnet_hosts.len(), snmp_hosts.len(), dns_hosts.len(), rdp_hosts.len(), unknown_ports.len()); ", windows_hosts.len(), ssh_hosts.len(), ftp_hosts.len(), telnet_hosts.len(), snmp_hosts.len(), dns_hosts.len(), rdp_hosts.len(), unknown_ports.len());
println!("lines parsed! creating output files..."); print_success(host_number_results);
print_informational("data gathered, writing to notes...");
outfile.push("windows_hosts.txt"); outfile.push("windows_hosts.txt");
let file_option = open_overwrite(&outfile); let file_option = open_overwrite(&outfile);
if file_option.is_some(){ if file_option.is_some(){
@@ -336,11 +349,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(windows_file, "{}\n", host); let write_res = write!(windows_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing windows_hosts.txt!!"); println!("{}","oooof error writing windows_hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("windows hosts file written!");
} }
} }
} }
@@ -353,11 +367,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(ssh_file, "{}\n", host); let write_res = write!(ssh_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing ssh_hosts.txt!!"); println!("{}","oooof error writing ssh_hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("ssh hosts file written!");
} }
} }
} }
@@ -370,11 +385,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(telnet_file, "{}\n", host); let write_res = write!(telnet_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("telnet hosts file written!");
} }
} }
} }
@@ -387,11 +403,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(ftp_file, "{}\n", host); let write_res = write!(ftp_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("fpt hosts file written!");
} }
} }
} }
@@ -404,11 +421,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(snmp_file, "{}\n", host); let write_res = write!(snmp_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("snmp hosts file written!")
} }
} }
} }
@@ -421,11 +439,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(dns_file, "{}\n", host); let write_res = write!(dns_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("dns hosts file written!")
} }
} }
} }
@@ -438,11 +457,12 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(rdp_file, "{}\n", host); let write_res = write!(rdp_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("rdp hosts file written!");
} }
} }
} }
@@ -455,26 +475,28 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(web_file, "{}\n", host); let write_res = write!(web_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("oooof error writing _hosts.txt!!"); println!("{}","oooof error writing _hosts.txt!!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
write_res.unwrap(); write_res.unwrap();
print_success("web hosts file written!");
} }
} }
} }
println!("interesting ports have been written to... writing untagged port files..."); print_informational("tagged port files have been written to, saving untagged ports...");
outfile.pop(); outfile.pop();
outfile.push("untagged ports"); outfile.push("untagged ports");
if !outfile.exists(){ if !outfile.exists(){
let untagged_res = create_dir_all(&outfile); let untagged_res = create_dir_all(&outfile);
if untagged_res.is_err(){ if untagged_res.is_err(){
let error = untagged_res.err().unwrap(); let error = untagged_res.err().unwrap();
println!("ooof error creating untagged folder!"); println!("{}","ooof error creating untagged folder!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
untagged_res.unwrap(); untagged_res.unwrap();
print_success("untagged port file written!");
} }
} }
for line in unknown_ports{ for line in unknown_ports{
@@ -489,13 +511,13 @@ pub fn parse_csportscan(project: &Project){
let write_res = write!(write_file, "{}\n", host); let write_res = write!(write_file, "{}\n", host);
if write_res.is_err(){ if write_res.is_err(){
let error = write_res.err().unwrap(); let error = write_res.err().unwrap();
println!("ooof error writing to file..."); println!("{}","ooof error writing to file...".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
} }
outfile.pop(); outfile.pop();
} }
println!("DONE all files saved to {}", outfile.display()); print_success(format!("DONE all files saved to {}", outfile.display()));
println!("note if no hosts were found for a protocol their files will be empty."); println!("note if no hosts were found for a protocol their files will be empty.");
} }
@@ -525,7 +547,7 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
return None; return None;
} }
let mut targets = targets_res.unwrap(); let mut targets = targets_res.unwrap();
println!("Got targets from scope!"); print_success("Got targets from scope!");
for target in &targets{ for target in &targets{
println!("{}", target); println!("{}", target);
} }
@@ -578,7 +600,11 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
} }
} }
let proxy = get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y"); let proxy = get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y");
println!("sweet we have what we need!"); print_success("sweet we have what we need!");
print_informational("Targets:");
for target in &targets{
print_success(format!("{}", target));
}
println!("building portscan command..."); println!("building portscan command...");
let working_project = project.clone(); let working_project = project.clone();
let mut save_path = project.files_folder.clone(); let mut save_path = project.files_folder.clone();
@@ -590,7 +616,6 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
save_path.push("services.tsv"); save_path.push("services.tsv");
let mut enumeration_notes_path = project.notes_folder.clone(); let mut enumeration_notes_path = project.notes_folder.clone();
enumeration_notes_path.push("enumeration.md"); enumeration_notes_path.push("enumeration.md");
println!("{}", save_path.display());
let mut nmap_output = Vec::new(); let mut nmap_output = Vec::new();
let nmap_thread = spawn(move || { let nmap_thread = spawn(move || {
if proxy{ if proxy{
@@ -608,8 +633,8 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
.output(); .output();
if port_scancmd_res.is_err(){ if port_scancmd_res.is_err(){
let error = port_scancmd_res.err().unwrap(); let error = port_scancmd_res.err().unwrap();
println!("FROM NMAP THREAD: error running portscan!"); println!("{}","FROM NMAP THREAD: error running portscan!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
nmap_output = port_scancmd_res.unwrap().stdout; nmap_output = port_scancmd_res.unwrap().stdout;
@@ -628,8 +653,8 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
.output(); .output();
if port_scancmd_res.is_err(){ if port_scancmd_res.is_err(){
let error = port_scancmd_res.err().unwrap(); let error = port_scancmd_res.err().unwrap();
println!("FROM NMAP THREAD: error running portscan!"); println!("{}","FROM NMAP THREAD: error running portscan!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
nmap_output = port_scancmd_res.unwrap().stdout; nmap_output = port_scancmd_res.unwrap().stdout;
@@ -643,6 +668,7 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
if nmap_log_file.is_some(){ if nmap_log_file.is_some(){
let mut nmap_log_file = nmap_log_file.unwrap(); let mut nmap_log_file = nmap_log_file.unwrap();
write!(nmap_log_file, "{}", nmap_output_string).unwrap(); write!(nmap_log_file, "{}", nmap_output_string).unwrap();
print_success("nmap log file written!");
} }
let mut host_ports = Vec::new(); let mut host_ports = Vec::new();
let host_sections: Vec<&str> = nmap_output_string.split("Nmap scan report ").collect(); let host_sections: Vec<&str> = nmap_output_string.split("Nmap scan report ").collect();
@@ -689,14 +715,13 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
let mut services_file = services_file_open_res.unwrap(); let mut services_file = services_file_open_res.unwrap();
let enumeration_open_res = open_append(&enumeration_notes_path); let enumeration_open_res = open_append(&enumeration_notes_path);
if enumeration_open_res.is_none(){ if enumeration_open_res.is_none(){
println!("error opening enumeration notes file!"); print_error("error opening enumeration notes file!", "".to_owned());
println!("scan data will not be saved to enumeration notes!");
} }
let services_write_res = write!(services_file, "host\tport\tbanner\tnotes\n"); let services_write_res = write!(services_file, "host\tport\tbanner\tnotes\n");
if services_write_res.is_err(){ if services_write_res.is_err(){
let error = services_write_res.err().unwrap(); let error = services_write_res.err().unwrap();
println!("FROM NMAP THREAD: error writing to the services.tsv file!"); println!("{}","FROM NMAP THREAD: error writing to the services.tsv file!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
let mut enumeration_write = false; let mut enumeration_write = false;
@@ -706,10 +731,10 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
let mut host_all_ports: HashMap<String, Vec<String>> = HashMap::new(); let mut host_all_ports: HashMap<String, Vec<String>> = HashMap::new();
for host in &host_ports{ for host in &host_ports{
write!(services_file, "{}\n", host).unwrap(); write!(services_file, "{}\n", host).unwrap();
let host_data: Vec<&str> = host.split_whitespace().collect(); let host_data: Vec<&str> = host.split("\t").collect();
let address = host_data[0].to_owned(); let address = host_data[0].to_owned();
let port = host_data[1].to_owned(); let port = host_data[1].to_owned();
let service = host_data[2..].join(" "); let service = host_data[2].to_owned();
if host_all_ports.contains_key(&address){ if host_all_ports.contains_key(&address){
host_all_ports.get_mut(&address).unwrap().push(format!("{}:{}", port, service)); host_all_ports.get_mut(&address).unwrap().push(format!("{}:{}", port, service));
} }
@@ -725,17 +750,16 @@ pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
for host in host_all_ports.keys(){ for host in host_all_ports.keys(){
write!(enumeration_file, "## {}\n| HOST | PORT | SERVICE |\n| ---- | ---- | ------- |\n", host).unwrap(); write!(enumeration_file, "## {}\n| HOST | PORT | SERVICE |\n| ---- | ---- | ------- |\n", host).unwrap();
for port_entry in &host_all_ports[host]{ for port_entry in &host_all_ports[host]{
println!("{}", port_entry);
let parts: Vec<&str> = port_entry.split(":").collect(); let parts: Vec<&str> = port_entry.split(":").collect();
let port = parts[0]; let port = parts[0];
let services = parts[1]; let services = parts[1];
write!(enumeration_file, "| {} | {} |\n", port, services).unwrap(); write!(enumeration_file, "| {} | {} | {} |\n", host, port, services).unwrap();
} }
} }
write!(enumeration_file, "---\n").unwrap(); write!(enumeration_file, "\n---\n").unwrap();
} }
} }
println!("FROM NMAP THREAD: Parsing done! You're scan results are saved in cobalt strike services.tsv format at {}", save_path.display()); print_success(format!("FROM NMAP THREAD: Parsing done! You're scan results are saved in cobalt strike services.tsv format at {}", save_path.display()));
}); });
sleep(Duration::from_secs(10)); sleep(Duration::from_secs(10));
return Some(nmap_thread); return Some(nmap_thread);
@@ -822,9 +846,9 @@ pub fn build_nmap_command(project: &Project){
let targets_string = targets.join(" "); let targets_string = targets.join(" ");
println!("\nYour portscan command is:"); println!("\nYour portscan command is:");
if get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y"){ if get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y"){
println!("\n\nproxychains nmap -sT -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()); print_success(format!("\n\nproxychains nmap -sT -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()));
} }
else{ else{
println!("nmap -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()); print_success(format!("nmap -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()));
} }
} }

View File

@@ -1,5 +1,6 @@
use std::env; use std::env;
use std::fs; use std::fs;
use std::fs::read_to_string;
use std::io::stdin; use std::io::stdin;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
@@ -8,12 +9,19 @@ use std::process::Command;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::str::FromStr; use std::str::FromStr;
use colored::Colorize;
use crate::configuration;
use crate::get_user_input; use crate::get_user_input;
use crate::open_overwrite;
use crate::print_informational;
use crate::tableize;
use crate::Project; use crate::Project;
use crate::box_controls::make_box; use crate::box_controls::make_box;
use crate::print_success;
use crate::print_error;
pub fn pub fn switch_project(projects: &mut Vec<Project>){
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);
@@ -27,30 +35,41 @@ switch_project(projects: &mut Vec<Project>){
for project in projects{ for project in projects{
if project.id == new_id{ if project.id == new_id{
project.active = true; project.active = true;
println!("project found switching to {} {}", project.customer, project.project_name); print_success(format!("project found switching to {} {}", project.customer, project.project_name));
env::set_var("CURRENT_PROJECT_BOX", project.boxname.clone()); env::set_var("CURRENT_PROJECT_BOX", project.boxname.clone());
} }
else if project.id != new_id{ else if project.id != new_id{
project.active = false; project.active = false;
} }
else{ else{
println!("error unknown project id"); print_error("error selecting new project", String::from("unknown project id selected."));
} }
} }
} }
else{ else{
println!("error we need user input here dummy!"); print_error("error selecting new project", String::from("we need input here dummy!"));
} }
} }
pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf, display: &bool) -> Option<String>{
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();
save_file_path.push("projects.conf"); save_file_path.push("projects.conf");
let mut save_file = fs::File::create(save_file_path).expect("error creating save_file"); let save_file_res = fs::File::create(save_file_path);
save_file.write_all(b"customer:name:notes:files:active:time:box_name:stage\n").expect("error writing first line to file"); if save_file_res.is_err(){
let error = save_file_res.err().unwrap().to_string();
if *display{
print_error("error creating save file.", error);
}
else{
return Some(format!("Error saving file! {}", error));
}
return None;
}
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");
for project in projects{ for project in projects{
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()}; let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
let mut _outline = String::new(); let mut _outline = String::new();
@@ -64,12 +83,24 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
else{ else{
_outline = format!("{}no:{}:{}\n", default, project.boxname, project.stage); _outline = format!("{}no:{}:{}\n", default, project.boxname, project.stage);
} }
save_file.write_all(_outline.as_bytes()).expect("error writing outline"); let write_res = save_file.write_all(_outline.as_bytes());
if write_res.is_err(){
let error = write_res.err().unwrap().to_string();
if *display{
print_error("error saving projects.conf file!", error);
}
else{
return Some(format!("error saving projects! {}", error));
}
return None;
}
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){ 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){
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();
@@ -230,21 +261,26 @@ 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); make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint, terminal, display);
} }
projects.push(new_project); projects.push(new_project);
save_projects(projects, config_path); save_projects(projects, config_path, &true);
} }
pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf, given_id: Option<String>){
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();
println!("project to remove?"); if given_id.is_none(){
std::io::stdin().read_line(&mut project_to_remove).unwrap(); for project in projects.clone(){
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{
@@ -275,7 +311,7 @@ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
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); save_projects(&projects, config_path, &true);
} }
else{ else{
println!("error no prjects found to remove") println!("error no prjects found to remove")
@@ -291,7 +327,7 @@ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
} }
} }
pub fn get_projects(config_path: &PathBuf, show: bool) -> Vec<Project>{ pub fn get_projects(config_path: &PathBuf, show: bool) -> Option<Vec<Project>>{
let mut mut_config_path = config_path.clone(); let mut mut_config_path = config_path.clone();
mut_config_path.pop(); mut_config_path.pop();
mut_config_path.push("projects.conf"); mut_config_path.push("projects.conf");
@@ -301,75 +337,102 @@ pub fn get_projects(config_path: &PathBuf, show: bool) -> Vec<Project>{
let bkup_result = fs::copy(&mut_config_path, &bkup_config_path); let bkup_result = fs::copy(&mut_config_path, &bkup_config_path);
if bkup_result.is_err(){ if bkup_result.is_err(){
let error = bkup_result.err().unwrap(); let error = bkup_result.err().unwrap();
println!("error backing up the projects.conf file!"); println!("{}","error backing up the projects.conf file!".red());
println!("error: {}", error); println!("{}", error.to_string().red());
} }
let mut projects = Vec::new(); let mut projects = Vec::new();
let projects_string = fs::read_to_string(mut_config_path).expect("error reading projects file"); let projects_string_res = fs::read_to_string(mut_config_path);
if projects_string_res.is_err(){
let error = projects_string_res.err().unwrap();
println!("{}", "Error Loading Project!".red());
println!("{}", error.to_string().red());
return None;
}
let projects_string = projects_string_res.unwrap();
let project_lines:Vec<&str> = projects_string.split("\n").collect(); let project_lines:Vec<&str> = projects_string.split("\n").collect();
let mut first = 0; let mut first = 0;
let mut already_active = false; let mut already_active = false;
for line in project_lines{ for line in project_lines{
//println!("{}", line);
first = first + 1; first = first + 1;
if first != 1{ if first != 1{
if line.len() > 1{ if line.len() > 1{
let settings: Vec<&str> = line.split(":").collect(); let settings: Vec<&str> = line.split(":").collect();
//debug config file... if settings.len() > 5{
/*let mut count = 0; // debug config file...
for settin in &settings{ /*let mut count = 0;
println!("{}: {}", count, settin); for settin in &settings{
count = count + 1; println!("{}: {}", count, settin);
}*/ count = count + 1;
let customer = settings[0].to_owned(); }*/
let project = settings[1].to_owned(); let customer = settings[0].to_owned();
let notes_string = settings[2].to_owned(); let project = settings[1].to_owned();
let folder_string = settings[3].to_owned(); let notes_string = settings[2].to_owned();
let notes_folder = PathBuf::from_str(&notes_string.trim_end()).expect("error reading notes string"); let folder_string = settings[3].to_owned();
let project_folder = PathBuf::from_str(&folder_string.trim_end()).expect("error reading folding sering"); let notes_folder = PathBuf::from_str(&notes_string.trim_end()).expect("error reading notes string");
let mut active = false; let project_folder = PathBuf::from_str(&folder_string.trim_end()).expect("error reading folding sering");
let boxname = settings[5].to_owned(); let mut active = false;
if settings[4] == "yes"{ let boxname = settings[5].to_owned();
if already_active == false{ if settings[4] == "yes"{
env::set_var("CURRENT_PROJECT_BOX", boxname.clone()); if already_active == false{
already_active = true; env::set_var("CURRENT_PROJECT_BOX", boxname.clone());
active = true; already_active = true;
active = true;
}
} }
let project_stage = settings[6].to_owned();
let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname, stage: project_stage};
if show{
println!("{} {} {}", &new_project.customer, &new_project.project_name, "LOADED!".green());
}
projects.push(new_project);
} }
let project_stage = settings[6].to_owned();
let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname, stage: project_stage};
if show{
println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
}
projects.push(new_project);
} }
} }
} }
return projects return Some(projects)
} }
pub fn print_upcoming_projects(projects: &Vec<Project>){ pub fn print_upcoming_projects(projects: &Vec<Project>, display: &bool) -> Option<String>{
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"){
println!("{}:{}", project.customer, project.project_name); let new_line = format!("{}||{}", project.customer, project.project_name);
lines.push(new_line);
} }
} }
let return_string = tableize(lines, &false);
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){ 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>{
let working_projects = projects.clone(); let working_projects = projects.clone();
for project in &working_projects{ let display = given_data.is_none();
if project.stage.contains("upcoming"){ let mut return_data = String::new();
println!("{}.) {}:{}", project.id, project.customer, project.project_name);
}
}
println!("which project to promote?");
let mut selection = String::new(); let mut selection = String::new();
let result = stdin().read_line(&mut selection); if display{
if result.is_err(){ for project in &working_projects{
println!("we need input here dummy try again...."); if project.stage.contains("upcoming"){
} println!("{}.) {}:{}", project.id, project.customer, project.project_name);
result.unwrap(); }
println!("{}", project_dir.display()); }
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();
}
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{
@@ -392,61 +455,87 @@ 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(){
println!("we copied the project folder correctly!!"); if display{
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(){
println!("error removing the original files folder form the upcomming folder, manual cleanup required"); if display{
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();
println!("upcoming files folder cleanup successful!"); if display{
println!("upcoming files folder cleanup successful!");
}
else{
return_data.push_str("\nupcoming files folder cleanup successful!");
}
} }
} }
else{ else{
println!("failed to copy the project folder, try to move it manually!"); if display{
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(){
println!("we copied the notes folder correctly!!"); 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!!");
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(){
println!("error removing the original notes folder form the upcomming folder, manual cleanup required"); if display{
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();
println!("upcoming notes folder cleanup successful!"); if display{
println!("upcoming notes folder cleanup successful!");
}
else{
return_data.push_str("\nupcoming notes folder cleanup successful!");
}
} }
} }
else{ else{
println!("failed to copy the notes folder, try to move it manually!"); if display{
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); make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint, Some(terminal.clone()), &display);
projects_to_save.push(promoted_project); projects_to_save.push(promoted_project);
} }
else{ else{
@@ -455,12 +544,285 @@ 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); save_projects(&projects_to_save, config_path, &display);
if display{
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>){ pub fn list_projects(projects: &Vec<Project>, display: &bool) -> String{
println!("+++++++++++++++++++++"); let mut lines = vec!["customer||project||stage".to_owned()];
for project in projects{ for project in projects{
println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)} let new_line = format!("{}||{}||{}", project.customer, project.project_name, project.stage);
println!("++++++++++++++++++++") lines.push(new_line);
}
let out_text= tableize(lines.clone(), display);
return out_text.to_owned();
}
pub fn separate_personal_work_projects(config_path: &PathBuf){
let config = config_path.clone();
let mut config_personal = config_path.clone();
config_personal.pop();
config_personal.push("conf.personal");
let mut config_work = config_path.clone();
config_work.pop();
config_work.push("conf.working");
let mut projects_conf_path = config_path.clone();
projects_conf_path.pop();
projects_conf_path.push("projects.conf");
let mut working_conf_path = config_path.clone();
working_conf_path.pop();
working_conf_path.push("projects.work");
let mut personal_conf_path = config_path.clone();
personal_conf_path.pop();
personal_conf_path.push("projects.personal");
let project_read_res = read_to_string(&projects_conf_path);
if project_read_res.is_err(){
print_error("error reading current projects config file!", project_read_res.err().unwrap().to_string());
return;
}
let project_string = project_read_res.unwrap();
let project_lines: Vec<&str> = project_string.split("\n").collect();
let mut personal_projects = Vec::new();
let mut work_projects = Vec::new();
let mut default = String::new();
print_success("current projects loaded!");
print_informational("we'll now go through project by project, answer yes or no to the following questions...");
for line in project_lines{
if line.contains("default"){
default = line.trim_end().to_owned();
}
else{
let words: Vec<&str> = line.split(":").collect();
if words.len() > 3{
println!("{} {}", words[0], words[1]);
if get_user_input("should this project be added to your personal projects config files?").to_lowercase().contains("y"){
personal_projects.push(line.to_owned());
print_success(format!("{}:{} {}",words[0], words[1], "successfully added to personal config!"));
if get_user_input("Do you also want to keep it in your work projects config?").to_lowercase().contains("y"){
work_projects.push(line.to_owned());
}
}
else{
work_projects.push(line.to_owned());
}
}
}
}
let work_config_open_res = fs::OpenOptions::new().create(true).write(true).open(working_conf_path);
if work_config_open_res.is_err(){
print_error("error opening work projects config file!", work_config_open_res.err().unwrap().to_string());
return;
}
let person_config_open_res = fs::OpenOptions::new().create(true).write(true).open(personal_conf_path);
if person_config_open_res.is_err(){
print_error("error opening personal projects config file!", person_config_open_res.err().unwrap().to_string());
return;
}
let mut work_config_file = work_config_open_res.unwrap();
let mut personal_config_file = person_config_open_res.unwrap();
let work_write_success = write!(work_config_file, "Work Config File\n");
let personal_write_success = write!(personal_config_file, "Personal Config File\n");
if work_write_success.is_err(){
print_error("error writing to work config file!", work_write_success.err().unwrap().to_string());
return;
}
else{
work_write_success.unwrap();
}
if personal_write_success.is_err(){
print_error("error writing personal config file!", personal_write_success.err().unwrap().to_string());
return;
}
else{
personal_write_success.unwrap();
}
write!(personal_config_file, "{}\n", default).unwrap();
write!(work_config_file, "{}\n", default).unwrap();
for project in work_projects{
write!(work_config_file, "{}\n", project).unwrap();
}
for project in personal_projects{
write!(personal_config_file, "{}\n", project).unwrap();
}
print_success("projects separated successfully!");
print_informational("now we'll separate the configuration files.");
let current_config_type = get_user_input("is the current settings loaded for work? (not personal)");
if current_config_type.to_lowercase().contains("y"){
let copy_res = fs::copy(&config, &config_work);
if copy_res.is_err(){
print_error("error copying config file to config.work!", copy_res.unwrap().to_string());
let copy_cmd = format!("cp {} {}", &config.display(), &config_work.display());
print_informational(copy_cmd);
}
else{
copy_res.unwrap();
print_success("conf.work successfully created!");
}
print_informational("Next we will create a new config file for work.\nIt will be save as conf.personal");
print_informational("\nplease select create from scratch at the next prompt, and fill out the information for your personal settings");
}
else{
let copy_res = fs::copy(&config, &config_personal);
if copy_res.is_err(){
print_error("error copying config file to config.personal!", copy_res.unwrap().to_string());
let copy_cmd = format!("cp {} {}", &config.display(), &config_personal.display());
print_informational(copy_cmd);
}
else{
copy_res.unwrap();
print_success("conf.personal successfully created!");
}
print_informational("Next we will create a new config file for work.\nIt will be save as conf.working");
print_informational("\nplease select create from scratch at the next prompt, and fill out the information for your work settings");
}
configuration::generate_tool_config(&config);
print_informational("great! now we're going to copy that to the specified new config file!");
if current_config_type.to_lowercase().contains("y"){
let copy_res = fs::copy(&config, &config_personal);
if copy_res.is_err(){
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());
print_informational(copy_cmd);
}
else{
copy_res.unwrap();
print_success("conf.personal successfully created!");
let remove_res = fs::remove_file(&config);
if remove_res.is_err(){
print_error("error restroing original config file!", remove_res.err().unwrap().to_string());
}
else{
remove_res.unwrap();
let copy_res = fs::copy(&config_work, &config);
if copy_res.is_err(){
print_error("error restoring original config file!", copy_res.err().unwrap().to_string());
}
else{
copy_res.unwrap();
print_success("original configuration successfully restored!");
}
}
}
}
else{
let copy_res = fs::copy(&config, &config_work);
if copy_res.is_err(){
print_error("error copying to conf.work!", copy_res.err().unwrap().to_string());
let copy_cmd = format!("plase run the following command in your terminal\ncp {} {}", &config.display(), &config_work.display());
print_informational(copy_cmd);
}
else{
copy_res.unwrap();
print_success("conf.personal successfully created!");
let remove_res = fs::remove_file(&config);
if remove_res.is_err(){
print_error("error restoring original config!", remove_res.err().unwrap().to_string());
}
else{
remove_res.unwrap();
let copy_res = fs::copy(&config_personal, &config);
if copy_res.is_err(){
print_error("error resoring original config!", copy_res.err().unwrap().to_string());
}
else{
copy_res.unwrap();
print_success("original configuration successfully restored!");
}
}
}
}
}
pub fn swith_to_personal(config: &PathBuf) -> Option<Vec<Project>>{
let mut personal_config_path = config.clone();
personal_config_path.pop();
personal_config_path.push("conf.personal");
let mut projects_path = config.clone();
projects_path.pop();
let mut personal_projects = config.clone();
personal_projects.pop();
projects_path.push("projects.conf");
personal_projects.push("projects.personal");
let personal_projects_read_res = read_to_string(&personal_projects);
if personal_projects_read_res.is_err(){
print_error("error reading personal projects!", personal_projects_read_res.err().unwrap().to_string());
return None;
}
let person_projects_string = personal_projects_read_res.unwrap();
let open_res = open_overwrite(&projects_path);
if open_res.is_none(){
print_error("error opening projects.conf file!", "".to_string());
return None;
}
let mut project_conf = open_res.unwrap();
write!(project_conf, "{}", person_projects_string).unwrap();
print_success("projects changed successfully!");
let new_projects = get_projects(config, true);
let remove_res = fs::remove_file(config);
if remove_res.is_ok(){
remove_res.unwrap();
let copy_res = fs::copy(personal_config_path, config);
if copy_res.is_ok(){
copy_res.unwrap();
print_success("settings successfully changed!");
}
else{
print_error("error changing settings!", copy_res.err().unwrap().to_string());
}
}
else{
print_error("error removing current settings!", remove_res.err().unwrap().to_string());
}
return new_projects;
}
pub fn swith_to_work(config: &PathBuf) -> Option<Vec<Project>>{
let mut work_config_path = config.clone();
work_config_path.pop();
work_config_path.push("conf.working");
let mut projects_path = config.clone();
projects_path.pop();
let mut work_projects = config.clone();
work_projects.pop();
projects_path.push("projects.conf");
work_projects.push("projects.work");
let work_projects_read_res = read_to_string(work_projects);
if work_projects_read_res.is_err(){
print_error("error reading personal projects!", work_projects_read_res.err().unwrap().to_string());
return None;
}
let work_projects_string = work_projects_read_res.unwrap();
let open_res = open_overwrite(&projects_path);
if open_res.is_none(){
print_error("", "error opening projects.conf file!".to_string());
return None;
}
let mut project_conf = open_res.unwrap();
write!(project_conf, "{}", work_projects_string).unwrap();
print_success("projects changed successfully!");
let new_projects = get_projects(config, true);
let remove_res = fs::remove_file(config);
if remove_res.is_ok(){
remove_res.unwrap();
let copy_res = fs::copy(work_config_path, config);
if copy_res.is_ok(){
copy_res.unwrap();
print_success("settings successfully changed!");
}
else{
print_error("error changing settings!", copy_res.err().unwrap().to_string());
}
}
else{
print_error("error removing current settings!", remove_res.err().unwrap().to_string());
}
return new_projects;
} }

View File

@@ -2,12 +2,14 @@ use std::fs;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use colored::Colorize;
use crate::Project; use crate::Project;
use crate::project_controls; use crate::project_controls;
use crate::get_user_input; use crate::get_user_input;
fn create_project_folder(path: &mut PathBuf, folder: &str){ pub 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(){
@@ -31,13 +33,14 @@ fn create_note_file(path: &PathBuf) -> Option<File>{
} }
} }
fn external(passtemp: &PathBuf, project: &Project){ pub 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);
if file_creation_res.is_err(){ if file_creation_res.is_err(){
let error = file_creation_res.err().unwrap(); let error = file_creation_res.err().unwrap();
println!("error creating notes folder! {}", error); println!("{}","error creating notes folder!".red());
println!("{}", error.to_string().red())
} }
else{ else{
file_creation_res.unwrap(); file_creation_res.unwrap();
@@ -130,12 +133,13 @@ passwords tried:
} }
fn internal(passtemp: &PathBuf, project: &Project){ pub 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(){
let error = file_creation_res.err().unwrap(); let error = file_creation_res.err().unwrap();
println!("error creating notes folder! {}", error); println!("{}","error creating notes folder!".red());
println!("{}", error.to_string().red())
} }
else{ else{
file_creation_res.unwrap(); file_creation_res.unwrap();
@@ -145,7 +149,8 @@ fn internal(passtemp: &PathBuf, project: &Project){
let pass_result = fs::copy(&passtemp, &notes_path); let pass_result = fs::copy(&passtemp, &notes_path);
if pass_result.is_err(){ if pass_result.is_err(){
let error = pass_result.err().unwrap(); let error = pass_result.err().unwrap();
println!("error copying password spray file, try again manually! {}", error); println!("{}","error copying password spray file, try again manually!".red());
println!("{}", error.to_string().red())
} }
else{ else{
pass_result.unwrap(); pass_result.unwrap();
@@ -311,13 +316,13 @@ powerup.ps1/sharpup.exe notes.
} }
fn vishing(project: &Project){ pub 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(){
let error = mknote_folder_res.err().unwrap(); let error = mknote_folder_res.err().unwrap();
println!("Error creating notes folder!"); println!("{}","Error creating notes folder!".red());
println!("{}", error); println!("{}", error.to_string().red());
return; return;
} }
notes_path.push("general.md"); notes_path.push("general.md");
@@ -341,7 +346,6 @@ 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 -
@@ -427,6 +431,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); project_controls::save_projects(projects, config_path, &false);
println!("project created and saved to the projects config file!"); println!("project created and saved to the projects config file!");
} }

View File

@@ -1,6 +1,8 @@
use std::{env::set_current_dir, path::PathBuf}; use std::{env::set_current_dir, path::PathBuf};
use std::process::Command; use std::process::Command;
use colored::Colorize;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::print_success;
pub fn update_git_tools(tools_dir: &PathBuf){ pub fn update_git_tools(tools_dir: &PathBuf){
@@ -16,8 +18,8 @@ pub fn update_git_tools(tools_dir: &PathBuf){
let cd_res = set_current_dir(&folder); let cd_res = set_current_dir(&folder);
if cd_res.is_err(){ if cd_res.is_err(){
let error = cd_res.err().unwrap(); let error = cd_res.err().unwrap();
println!("error changing directory!"); println!("{}","error changing directory!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
let _cd = cd_res.unwrap(); let _cd = cd_res.unwrap();
@@ -27,13 +29,13 @@ pub fn update_git_tools(tools_dir: &PathBuf){
.status(); .status();
if git_command_res.is_err(){ if git_command_res.is_err(){
let error = git_command_res.err().unwrap(); let error = git_command_res.err().unwrap();
println!("error running git pull command!"); println!("{}","error running git pull command!".red());
println!("{}", error); println!("{}", error.to_string().red());
} }
else{ else{
let git_command = git_command_res.unwrap(); let git_command = git_command_res.unwrap();
if git_command.success(){ if git_command.success(){
println!("successfully updated {}", folder.display()); print_success(format!("successfully updated {}", folder.display()));
} }
} }
} }

View File

@@ -1,6 +1,8 @@
use std::path::PathBuf; use std::path::PathBuf;
use colored::Colorize;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::get_user_input; use crate::get_user_input;
use crate::print_success;
pub fn sharp_persist_command(tools_dir: &PathBuf){ pub fn sharp_persist_command(tools_dir: &PathBuf){
let filename = "SharPersist.exe"; let filename = "SharPersist.exe";
@@ -20,13 +22,13 @@ pub fn sharp_persist_command(tools_dir: &PathBuf){
"1" => println!("execute-assembly {} -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path), "1" => println!("execute-assembly {} -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path),
"2" => println!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs -t schtask -c \"{}\" -n FRPersist -m add -o hourly --etw --amsi", binary_path, beacon_path), "2" => println!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs -t schtask -c \"{}\" -n FRPersist -m add -o hourly --etw --amsi", binary_path, beacon_path),
"3" => println!("upload {}\n\nrun .\\SharPersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path), "3" => println!("upload {}\n\nrun .\\SharPersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path),
_ => println!("unknown selection") _ => println!("{}","unknown selection".red())
} }
return; return;
} }
let file_to_run = get_user_input("path to the file you want to run for persistence?"); let file_to_run = get_user_input("path to the file you want to run for persistence?");
println!("ok then, upload the following file to the machine"); print_success("ok then, upload the following file to the machine");
println!("{}", binary_path); print_success(format!("{}", binary_path));
println!("C:\\path\\to\\your\\sharpersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", file_to_run); print_success(format!("C:\\path\\to\\your\\sharpersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", file_to_run));
return; return;
} }