Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f99e395241 | ||
|
|
0cbe33357a | ||
|
|
4bd67a486f | ||
|
|
12e5ab38d2 | ||
|
|
f2370e463d | ||
|
|
92dd9766b8 | ||
|
|
dbbae0eb4e | ||
|
|
2346988e23 | ||
|
|
5bfa645b3d | ||
|
|
012ba517ab | ||
|
|
649dad5e79 | ||
|
|
2e839adccf | ||
|
|
fc316c2a71 |
2
pentest_tool/Cargo.lock
generated
2
pentest_tool/Cargo.lock
generated
@@ -1241,7 +1241,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pentest_tool"
|
name = "pentest_tool"
|
||||||
version = "0.2.0"
|
version = "3.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clearscreen",
|
"clearscreen",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pentest_tool"
|
name = "pentest_tool"
|
||||||
version = "0.2.0"
|
version = "3.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String){
|
|||||||
if terminal.contains("profile"){
|
if terminal.contains("profile"){
|
||||||
profile = true;
|
profile = true;
|
||||||
}
|
}
|
||||||
|
if terminal.contains("!!!"){
|
||||||
|
let terminal_launch_cmd = format!("distrobox enter --root {}", &project.boxname);
|
||||||
|
terminal = terminal.replace("!!!", &terminal_launch_cmd);
|
||||||
|
}
|
||||||
let terminal_vec:Vec<&str> = terminal.split(" ").collect();
|
let terminal_vec:Vec<&str> = terminal.split(" ").collect();
|
||||||
let mut terminal_start = process::Command::new(terminal_vec[0]);
|
let mut terminal_start = process::Command::new(terminal_vec[0]);
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|||||||
210
pentest_tool/src/cli.rs
Normal file
210
pentest_tool/src/cli.rs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::exit;
|
||||||
|
use std::thread::JoinHandle;
|
||||||
|
use chrono::Datelike;
|
||||||
|
use clearscreen::clear;
|
||||||
|
use clearscreen;
|
||||||
|
use chrono::Local;
|
||||||
|
use crate::Project;
|
||||||
|
use crate::project_controls;
|
||||||
|
use crate::box_controls;
|
||||||
|
use crate::info_controls;
|
||||||
|
use crate::start_pentest;
|
||||||
|
use crate::get_user_input;
|
||||||
|
use crate::menu;
|
||||||
|
|
||||||
|
|
||||||
|
fn help(command: Option<String>){
|
||||||
|
if command.is_some(){
|
||||||
|
let help_cmd = command.unwrap();
|
||||||
|
match help_cmd.as_str(){
|
||||||
|
"list projects" | "lp" | "listp" | "list p" => {println!("list all projects"); return;},
|
||||||
|
"switch project" | "swp" | "switch p" | "switchp" => {println!("switch active project"); return;},
|
||||||
|
"show active project" | "show active" | "sa" | "show a" => {println!("show currently active project"); return;},
|
||||||
|
"create new project" | "cnp" | "new project" | "np" => {println!("create a new project and default note structure"); return;},
|
||||||
|
"save projects" | "sp" | "save" | "s" => {println!("save project information"); return;},
|
||||||
|
"import project" | "ip" | "import" => {println!("impot existing project"); return;},
|
||||||
|
"remove project" | "rp" | "remove" | "rmp" => {println!("remove project"); return;},
|
||||||
|
"show upcoming projects" | "sup" | "show upcoming" => {println!("show upcoming projects"); return;},
|
||||||
|
"promote project" | "pp" | "promote" => {println!("promote upcoming project to current project"); return;},
|
||||||
|
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {println!("spawn a new terminal window in the active project's distrobox"); return;},
|
||||||
|
"inline terminal" | "it" | "enter inline" | "ei" => {println!("spawn a terminal in this window using the current active project's distrobox"); return;},
|
||||||
|
"cobalt strike" | "cs" => {println!("open cobalt strike in the active project's distrobox"); return;},
|
||||||
|
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {println!("recreate the active project's distrobox"); return;},
|
||||||
|
"generate userpass" | "userpass" | "gup" | "up" => {println!("generate userpass file based on the active project's notes"); return;},
|
||||||
|
"inital enum" | "ie" | "enum" => {println!("run the initial enum script on a nessus csv and save the output to the active project's notes"); return;},
|
||||||
|
"build attack notes" | "ban" | "attack notes" | "hn" => {println!("build the active project's attack note based on the active project's host notes (for external tests)"); return;},
|
||||||
|
"host discovery" | "build host discovery" | "hd" | "bhd" => {println!("print host discovery ping command for the active project, based on the scope table"); return;},
|
||||||
|
"port scan" | "cs port scan" | "cobaltstrike port scan" | "csps" | "ps" => {println!("print the cobalt strike portscan command based on the active project's scope table"); return;},
|
||||||
|
"parse port scan" | "pps" | "parse scan" => {println!("parse a cobalt strike portscan and save the files to the active project's files folder"); return;},
|
||||||
|
"stop boxes" | "stop distroboxes" | "sdb" => {println!("stop all distroboxes"); return;},
|
||||||
|
"password spray" | "pass spray" | "pas" => {println!("iterate through password spray note file and print the command to perform the spray, waiting the proper observation window beteen commands"); return;},
|
||||||
|
"bloodhound" | "bh" => {println!("launch bloodhound in the active project's distrobox"); return;},
|
||||||
|
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {println!("parse gather contacts output"); return;},
|
||||||
|
"prune distroboxes" | "pdb" | "prune" => {println!("prune distroboxes for all projects that are not being tracked by this tool (frees up system storage)"); return;},
|
||||||
|
"clear" | "clear screen" | "cls" => {println!("clears the screen of command output"); return},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Welcom to Pyro's pentest command line!");
|
||||||
|
println!("available commands: name | aliases | ...");
|
||||||
|
print!("
|
||||||
|
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
|
||||||
|
help | ? | -h
|
||||||
|
")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_command(cmd: String,
|
||||||
|
mut projects: Vec<Project>,
|
||||||
|
config_path: PathBuf,
|
||||||
|
base_files: &PathBuf,
|
||||||
|
base_notes: &PathBuf,
|
||||||
|
tools_dir: &PathBuf,
|
||||||
|
boxtemplate: String,
|
||||||
|
terminal: String,
|
||||||
|
cracking_rig: String,
|
||||||
|
rockyou: String,
|
||||||
|
rule: String,
|
||||||
|
upcoming_files: &PathBuf,
|
||||||
|
upcoming_notes: &PathBuf,
|
||||||
|
password_spray_file: &PathBuf,
|
||||||
|
fingerprint: bool,
|
||||||
|
vault_name: String) -> Option<JoinHandle<()>> {
|
||||||
|
let mut new_id = menu::next_project_id(&config_path);
|
||||||
|
let active_project = menu::get_active_project(&projects);
|
||||||
|
let mut notes_folder_string = format!("{}", &active_project.notes_folder.display());
|
||||||
|
let mut obsidian_folder_vec = PathBuf::new();
|
||||||
|
let mut reached_vault_folder = false;
|
||||||
|
for folder in notes_folder_string.split("/").collect::<Vec<&str>>(){
|
||||||
|
if !folder.contains(&vault_name){
|
||||||
|
reached_vault_folder = true;
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if reached_vault_folder{
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let obsidian_uri = format!("obsidian://open?vault={}&file={}", vault_name, obsidian_folder_vec.display().to_string().replace("/", "%2F"));
|
||||||
|
let mut response = String::new();
|
||||||
|
let now = Local::now();
|
||||||
|
let month = now.month();
|
||||||
|
let year = now.year();
|
||||||
|
let mut season = String::new();
|
||||||
|
let mut lseason = String::new();
|
||||||
|
match month{
|
||||||
|
12 | 01 | 02 => {season = "Winter".to_owned(); lseason = "Fall".to_owned()},
|
||||||
|
03 | 04 | 05 => {season = "Spring".to_owned(); lseason = "Winter".to_owned()},
|
||||||
|
06 | 07 | 08 => {season = "Summer".to_owned(); lseason = "Spring".to_owned()},
|
||||||
|
09 | 10 | 11 => {season = "Fall".to_owned(); lseason = "Summer".to_owned()},
|
||||||
|
_ => {println!("error getting season! Check code..."); exit(1)}
|
||||||
|
}
|
||||||
|
if cmd.contains("help"){
|
||||||
|
if cmd.contains(" "){
|
||||||
|
let help_with = &cmd.split(" ").collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
help(Some(help_with.to_owned()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
help(None);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match cmd.as_str(){
|
||||||
|
"list projects" | "lp" | "listp" | "list p" => {project_controls::list_projects(&projects); return None},
|
||||||
|
"switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return None},
|
||||||
|
"show active project" | "show active" | "sa" | "show a" => {println!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()); return None},
|
||||||
|
"create new project" | "cnp" | "new project" | "np" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file); return None},
|
||||||
|
"save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path); return None},
|
||||||
|
"import project" | "ip" | "import" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint); return None},
|
||||||
|
"remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path); return None},
|
||||||
|
"show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects); return None},
|
||||||
|
"promote project" | "pp" | "promote" => {project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint); return None},
|
||||||
|
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()); return None},
|
||||||
|
"inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone()); return None},
|
||||||
|
"cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); return cs_thread},
|
||||||
|
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint); return None},
|
||||||
|
"generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project); return None},
|
||||||
|
"inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project); return None},
|
||||||
|
"build attack notes" | "ban" | "attack notes" | "hn" => {info_controls::build_cmd_for_host_discovery(&active_project); return None;}
|
||||||
|
"host discovery" | "build host discovery" | "hd" | "bhd" => {info_controls::build_cmd_for_host_discovery(&active_project); return None},
|
||||||
|
"port scan" | "cs port scan" | "cobaltstrike port scan" | "csps" | "ps" => {info_controls::build_cs_portscan_cmd(&active_project); return None},
|
||||||
|
"parse port scan" | "pps" | "parse scan" => {info_controls::parse_csportscan(&active_project); return None},
|
||||||
|
"stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects); return None},
|
||||||
|
"password spray" | "pass spray" | "pas" => {info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path); return None},
|
||||||
|
"bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); return Some(bloodhound_handle);},
|
||||||
|
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project); return None},
|
||||||
|
"prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); return prune_thread},
|
||||||
|
"clear" | "clear screen" | "cls" => {clear().unwrap(); return None},
|
||||||
|
_ => {println!("unknown command."); return None;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cli(interactive: bool,
|
||||||
|
projects: Vec<Project>,
|
||||||
|
config_path: PathBuf,
|
||||||
|
base_files: &PathBuf,
|
||||||
|
base_notes: &PathBuf,
|
||||||
|
tools_dir: &PathBuf,
|
||||||
|
boxtemplate: String,
|
||||||
|
terminal: String,
|
||||||
|
cracking_rig: String,
|
||||||
|
rockyou: String,
|
||||||
|
rule: String,
|
||||||
|
upcoming_files: &PathBuf,
|
||||||
|
upcoming_notes: &PathBuf,
|
||||||
|
password_spray_file: &PathBuf,
|
||||||
|
fingerprint: bool,
|
||||||
|
vault_name: String) -> Option<Vec<JoinHandle<()>>>{
|
||||||
|
let mut threads = Vec::new();
|
||||||
|
let active_project = menu::get_active_project(&projects);
|
||||||
|
if interactive{
|
||||||
|
let mut loopize = true;
|
||||||
|
while loopize{
|
||||||
|
print!("
|
||||||
|
Active Project: {}, {}
|
||||||
|
Project Status: {}
|
||||||
|
Files Folder: {}
|
||||||
|
Notes Folder: {}
|
||||||
|
Boxname: {}
|
||||||
|
Obsidian URI: {}
|
||||||
|
|
||||||
|
|
||||||
|
", 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");
|
||||||
|
let command = get_user_input("command?");
|
||||||
|
match command.as_str(){
|
||||||
|
"exit" | "main menu" | "mm" | "menu" => loopize = false,
|
||||||
|
_ => {let thread_option = run_command(command, projects.clone(), 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())}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if threads.len() > 0{
|
||||||
|
return Some(threads);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::write;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::fs::create_dir_all;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -10,11 +14,16 @@ use std::thread;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::thread::JoinHandle;
|
use std::thread::JoinHandle;
|
||||||
|
use chrono::format;
|
||||||
|
use fs_extra::file;
|
||||||
|
use reqwest::dns::Name;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
use clearscreen::clear;
|
use clearscreen::clear;
|
||||||
use clearscreen;
|
use clearscreen;
|
||||||
use rodio::{Decoder, OutputStream, Sink};
|
use rodio::{Decoder, OutputStream, Sink};
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
|
use crate::open_overwrite;
|
||||||
|
use crate::open_append;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
|
|
||||||
pub fn run_initial_enum(project: &Project){
|
pub fn run_initial_enum(project: &Project){
|
||||||
@@ -96,67 +105,75 @@ pub fn run_initial_enum(project: &Project){
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_external_attack_notes(project: &Project){
|
pub fn build_external_attack_notes(project: &Project){
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Port{
|
struct Port{
|
||||||
number: String,
|
service: String,
|
||||||
hosts: Vec<String>,
|
hosts: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ports: Vec<Port> = Vec::new();
|
let mut ports: Vec<Port> = Vec::new();
|
||||||
let mut host_notes_path = project.notes_folder.clone();
|
let mut host_notes_path = project.notes_folder.clone();
|
||||||
let mut attack_notes_path = host_notes_path.clone();
|
|
||||||
host_notes_path.push("host_notes.md");
|
host_notes_path.push("host_notes.md");
|
||||||
|
let mut attack_notes_path = project.notes_folder.clone();
|
||||||
attack_notes_path.push("attacks.md");
|
attack_notes_path.push("attacks.md");
|
||||||
let host_notes_read_res = fs::read_to_string(host_notes_path);
|
let host_notes_read_res = fs::read_to_string(host_notes_path);
|
||||||
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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let host_notes = host_notes_read_res.unwrap();
|
let host_notes_string = host_notes_read_res.unwrap();
|
||||||
let attack_open_res = fs::OpenOptions::new().append(true).create(true).open(attack_notes_path);
|
let host_parts: Vec<&str> = host_notes_string.split("---").collect();
|
||||||
if attack_open_res.is_err(){
|
let mut host = String::new();
|
||||||
let error = attack_open_res.err().unwrap();
|
for part in host_parts{
|
||||||
println!("error opening attack notes!");
|
let lines: Vec<&str> = part.split("\n").collect();
|
||||||
println!("{}", error);
|
for line in lines{
|
||||||
return;
|
|
||||||
}
|
|
||||||
let attack_notes = attack_open_res.unwrap();
|
|
||||||
for line in host_notes.split("\n").collect::<Vec<&str>>(){
|
|
||||||
let mut current_host = String::new();
|
|
||||||
if line.len() > 1{
|
|
||||||
if line.contains("# "){
|
if line.contains("# "){
|
||||||
if !line.contains("## "){
|
if !line.contains("## "){
|
||||||
current_host = line.split_whitespace().collect::<Vec<&str>>()[1].trim().to_owned();
|
host = line.split("# ").collect::<Vec<&str>>()[1].to_owned();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if line.contains("|"){
|
if line.contains("|"){
|
||||||
let table_data:Vec <&str> = line.split("|").collect();
|
if line.contains(":"){
|
||||||
for item in table_data{
|
let entries: Vec<&str> = line.split("|").collect();
|
||||||
let mut is_new = true;
|
let service = entries[2].trim().to_owned();
|
||||||
if item.contains(":"){
|
for entry in entries{
|
||||||
|
if entry.contains(":"){
|
||||||
|
let port_number = entry.trim().to_owned();
|
||||||
|
let mut new = true;
|
||||||
for port in &mut ports{
|
for port in &mut ports{
|
||||||
if port.number == item.trim(){
|
if port.service == service{
|
||||||
if port.hosts.contains(¤t_host){
|
new = false;
|
||||||
port.hosts.push(current_host.clone());
|
let host_entry = format!("{} {}", host.clone(), port_number.clone());
|
||||||
}
|
port.hosts.push(host_entry);
|
||||||
is_new = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_new{
|
match new{
|
||||||
let new_port = Port{number: line.trim().to_owned(), hosts:vec![current_host.clone()]};
|
true => {let new_port = Port{service: service.clone(), hosts: vec![format!("{} {}", host.clone(), port_number.clone())]}; ports.push(new_port);},
|
||||||
|
false => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for port in ports{
|
println!("{} parsed!", host);
|
||||||
let output = format!("# {}\nHOSTS:\n", port.number);
|
}
|
||||||
|
println!("parsed host_notes.md, writing to attacks.md...");
|
||||||
|
let attack_open_res = open_append(&attack_notes_path);
|
||||||
|
if attack_open_res.is_none(){
|
||||||
|
println!("ooof error opening attack notes, returning...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut attack_file = attack_open_res.unwrap();
|
||||||
|
write!(attack_file, "\n---\n").expect("since we used the open options already this should never fail.");
|
||||||
|
for port in ports.clone(){
|
||||||
|
write!(attack_file, "# {}\n", port.service).expect("since we used the open options already this should never fail.");
|
||||||
|
write!(attack_file, "HOSTS:\n").expect("since we used the open options already this should never fail.");
|
||||||
for host in port.hosts{
|
for host in port.hosts{
|
||||||
// output.push_str("## {}");
|
write!(attack_file, "## {}\n\n", host).expect("since we used the open options already this should never fail.");
|
||||||
|
write!(attack_file, "\n---\n").expect("since we used the open options already this should never fail.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -776,3 +793,428 @@ pub fn get_mssql_column_names(project: &Project) -> Option<JoinHandle<()>>{
|
|||||||
});
|
});
|
||||||
return Some(db_handle);
|
return Some(db_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn partse_gathercontacts(project: &Project){
|
||||||
|
fn format_names(names: Vec<&str>) -> HashMap<&str, Vec<String>>{
|
||||||
|
let mut formated_data = HashMap::new();
|
||||||
|
let mut flast = Vec::new();
|
||||||
|
let mut fdotlast = Vec::new();
|
||||||
|
let mut fdashlast = Vec::new();
|
||||||
|
let mut firstl = Vec::new();
|
||||||
|
let mut firstdotlast = Vec::new();
|
||||||
|
let mut firstlast = Vec::new();
|
||||||
|
let mut last_vec = Vec::new();
|
||||||
|
let mut first_vec = Vec::new();
|
||||||
|
for name in names{
|
||||||
|
let name_vec: Vec<&str> = name.split("|").collect();
|
||||||
|
if name_vec.len() == 2{
|
||||||
|
let first = name_vec[0];
|
||||||
|
let last = name_vec[1];
|
||||||
|
let first_chars: Vec<char> = first.chars().collect();
|
||||||
|
let last_chars: Vec<char> = last.chars().collect();
|
||||||
|
flast.push(format!("{}{}", &first_chars[0], &last));
|
||||||
|
fdotlast.push(format!("{}.{}", &first_chars[0], &last));
|
||||||
|
fdashlast.push(format!("{}-{}", &first, &last));
|
||||||
|
firstl.push(format!("{}{}", &first, &last_chars[0]));
|
||||||
|
firstdotlast.push(format!("{}.{}", &first, &last));
|
||||||
|
firstlast.push(format!("{}{}", &first, &last));
|
||||||
|
last_vec.push(format!("{}", &last));
|
||||||
|
first_vec.push(format!("{}", &first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formated_data.insert("flast", flast);
|
||||||
|
formated_data.insert("fdotlast", fdotlast);
|
||||||
|
formated_data.insert("fdashlast", fdashlast);
|
||||||
|
formated_data.insert("firstl", firstl);
|
||||||
|
formated_data.insert("firstdotlast", firstdotlast);
|
||||||
|
formated_data.insert("firstlast", firstlast);
|
||||||
|
formated_data.insert("last", last_vec);
|
||||||
|
formated_data.insert("fisrt", first_vec);
|
||||||
|
return formated_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gather_file = get_user_input("path to your gather contacts output?");
|
||||||
|
print!("
|
||||||
|
supported formats:
|
||||||
|
flast
|
||||||
|
f.last
|
||||||
|
f-last
|
||||||
|
firstl
|
||||||
|
first.last
|
||||||
|
firstlast
|
||||||
|
last
|
||||||
|
\n");
|
||||||
|
let format = get_user_input("format of usernames?");
|
||||||
|
let domain = get_user_input("domain name?");
|
||||||
|
let gather_source = fs::read_to_string(gather_file);
|
||||||
|
if gather_source.is_err(){
|
||||||
|
let error = gather_source.err().unwrap();
|
||||||
|
println!("error reading gather contacts output!");
|
||||||
|
println!("{}", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let gather_source_string = gather_source.unwrap();
|
||||||
|
let gather_source_lines: Vec<&str> = gather_source_string.split("\n").collect();
|
||||||
|
let mut names = String::new();
|
||||||
|
for line in gather_source_lines{
|
||||||
|
if line.len() > 2{
|
||||||
|
let line_vec: Vec<&str> = line.split("\t").collect();
|
||||||
|
let first = line_vec[1].trim();
|
||||||
|
let last = line_vec[2].trim();
|
||||||
|
if first.len() > 1 && last.len() >1 {
|
||||||
|
let name = format!("{}|{}",first, last);
|
||||||
|
names = format!("{} {}", names, name.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let users: Vec<&str> = names.split(" ").collect();
|
||||||
|
let data = format_names(users);
|
||||||
|
let mut email_text_path = project.files_folder.clone();
|
||||||
|
let mut email_note_path = project.notes_folder.clone();
|
||||||
|
email_text_path.push("working/extrapolated_emails.txt");
|
||||||
|
email_note_path.push("email_enum.md");
|
||||||
|
let email_text_res = OpenOptions::new().append(true).create(true).open(email_text_path);
|
||||||
|
if email_text_res.is_err(){
|
||||||
|
let error = email_text_res.err().unwrap();
|
||||||
|
println!("error opening email text file!");
|
||||||
|
println!("{}", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let email_notes_res = OpenOptions::new().append(true).create(true).open(email_note_path);
|
||||||
|
if email_notes_res.is_err(){
|
||||||
|
let error = email_notes_res.err().unwrap();
|
||||||
|
println!("error opeing email notes file!");
|
||||||
|
println!("{}", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut email_text_file = email_text_res.unwrap();
|
||||||
|
let mut email_note_file = email_notes_res.unwrap();
|
||||||
|
let note_wriet_res = write!(email_note_file, "# Extrapolated Emails: \n");
|
||||||
|
if note_wriet_res.is_err(){
|
||||||
|
let error = note_wriet_res.err().unwrap();
|
||||||
|
println!("error writing to email notes file!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
println!("data gathered, printing emails and saving files...\n\n");
|
||||||
|
for email in &data[&format.to_lowercase().trim()]{
|
||||||
|
let outline = format!("{}@{}", email, domain);
|
||||||
|
println!("{}", &outline);
|
||||||
|
write!(email_note_file, "{}\n", outline).expect("error writing email notes file!");
|
||||||
|
write!(email_text_file, "{}\n", outline).expect("error writing email text file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_csportscan(project: &Project){
|
||||||
|
let mut tsv_path = project.files_folder.clone();
|
||||||
|
tsv_path.push("working/tsvs/services.tsv");
|
||||||
|
let mut outfile = tsv_path.clone();
|
||||||
|
outfile.pop();
|
||||||
|
outfile.pop();
|
||||||
|
let mut windows_hosts = Vec::new();
|
||||||
|
let mut ssh_hosts = Vec::new();
|
||||||
|
let mut ftp_hosts = Vec::new();
|
||||||
|
let mut rdp_hosts = Vec::new();
|
||||||
|
let mut dns_hosts = Vec::new();
|
||||||
|
let mut snmp_hosts = Vec::new();
|
||||||
|
let mut web_hosts = Vec::new();
|
||||||
|
let mut telnet_hosts = 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);
|
||||||
|
if tsv_read_res.is_err(){
|
||||||
|
let error = tsv_read_res.err().unwrap();
|
||||||
|
println!("ooof error reading tsv file!");
|
||||||
|
println!("{}", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("tsv read, parsing lines...");
|
||||||
|
let tsv_string = tsv_read_res.unwrap();
|
||||||
|
let lines: Vec<&str> = tsv_string.split("\n").collect();
|
||||||
|
for line in lines{
|
||||||
|
let words: Vec<&str> = line.split("\t").collect();
|
||||||
|
if words.len() > 1{
|
||||||
|
let host = words[0].to_lowercase().to_owned();
|
||||||
|
let port = words[1].to_lowercase().to_owned();
|
||||||
|
let host_entry = format!("{}:{}", &host, &port);
|
||||||
|
match words[1]{
|
||||||
|
"135" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}},
|
||||||
|
"445" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}},
|
||||||
|
"22" => {if !ssh_hosts.contains(&host){ssh_hosts.push(host);}},
|
||||||
|
"21" => {if !ftp_hosts.contains(&host){ftp_hosts.push(host);}},
|
||||||
|
"23" => {if !telnet_hosts.contains(&host){telnet_hosts.push(host)}},
|
||||||
|
"3389" => {if !rdp_hosts.contains(&host){rdp_hosts.push(host);}},
|
||||||
|
"80" | "443" | "8080" | "8443" | "4433" | "8000" => {if !web_hosts.contains(&host_entry){web_hosts.push(host_entry);}},
|
||||||
|
"53" => {if !dns_hosts.contains(&host){dns_hosts.push(host);}},
|
||||||
|
"161" => {if !snmp_hosts.contains(&host){snmp_hosts.push(host);}},
|
||||||
|
_ => {
|
||||||
|
if words.len() == 3{
|
||||||
|
let banner = words[2].to_lowercase().to_owned();
|
||||||
|
if words[2].to_lowercase().contains("ssh"){
|
||||||
|
if !ssh_hosts.contains(&host_entry){
|
||||||
|
ssh_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if banner.contains("ftp"){
|
||||||
|
if !ftp_hosts.contains(&host_entry){
|
||||||
|
ftp_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if banner.contains("nginx") || banner.contains("apache"){
|
||||||
|
if !web_hosts.contains(&host_entry){
|
||||||
|
web_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if words.len() == 2{
|
||||||
|
unknown_ports.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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."));
|
||||||
|
}
|
||||||
|
print!("
|
||||||
|
{} Windows hosts found!
|
||||||
|
{} SSH hosts found!
|
||||||
|
{} FTP hosts found!
|
||||||
|
{} Telnet hosts found!
|
||||||
|
{} SNMP hosts found!
|
||||||
|
{} DNS hosts found!
|
||||||
|
{} RDP 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());
|
||||||
|
println!("lines parsed! creating output files...");
|
||||||
|
outfile.push("windows_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut windows_file = file_option.unwrap();
|
||||||
|
for host in windows_hosts{
|
||||||
|
let write_res = write!(windows_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing windows_hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("ssh_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut ssh_file = file_option.unwrap();
|
||||||
|
for host in ssh_hosts{
|
||||||
|
let write_res = write!(ssh_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing ssh_hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("telnet_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut telnet_file = file_option.unwrap();
|
||||||
|
for host in telnet_hosts{
|
||||||
|
let write_res = write!(telnet_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("ftp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut ftp_file = file_option.unwrap();
|
||||||
|
for host in ftp_hosts{
|
||||||
|
let write_res = write!(ftp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("snmp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut snmp_file = file_option.unwrap();
|
||||||
|
for host in snmp_hosts{
|
||||||
|
let write_res = write!(snmp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("dns_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut dns_file = file_option.unwrap();
|
||||||
|
for host in dns_hosts{
|
||||||
|
let write_res = write!(dns_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("rdp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut rdp_file = file_option.unwrap();
|
||||||
|
for host in rdp_hosts{
|
||||||
|
let write_res = write!(rdp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("web_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut web_file = file_option.unwrap();
|
||||||
|
for host in web_hosts{
|
||||||
|
let write_res = write!(web_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("oooof error writing _hosts.txt!!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("interesting ports have been written to... writing untagged port files...");
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("untagged ports");
|
||||||
|
if !outfile.exists(){
|
||||||
|
let untagged_res = create_dir_all(&outfile);
|
||||||
|
if untagged_res.is_err(){
|
||||||
|
let error = untagged_res.err().unwrap();
|
||||||
|
println!("ooof error creating untagged folder!");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
untagged_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for line in unknown_ports{
|
||||||
|
let line_vec:Vec<&str> = line.split(":").collect();
|
||||||
|
let host = line_vec[0].to_owned();
|
||||||
|
let port = line_vec[1].to_owned();
|
||||||
|
let file_name = format!("{}_hosts.txt", port);
|
||||||
|
outfile.push(file_name);
|
||||||
|
let write_file_opt = open_append(&outfile);
|
||||||
|
if write_file_opt.is_some(){
|
||||||
|
let mut write_file = write_file_opt.unwrap();
|
||||||
|
let write_res = write!(write_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("ooof error writing to file...");
|
||||||
|
println!("{}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
}
|
||||||
|
println!("DONE all files saved to {}", outfile.display());
|
||||||
|
println!("note if no hosts were found for a protocol their files will be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fn get_scope(general: &PathBuf){
|
||||||
|
println!("opening general notes...");
|
||||||
|
let mut working = general.clone();
|
||||||
|
working.push("general.md");
|
||||||
|
let working_read = fs::read_to_string(working);
|
||||||
|
if working_read.is_err(){
|
||||||
|
let error = working_read.err().unwrap();
|
||||||
|
println!("error reading general notes file!");
|
||||||
|
println!("{}", error);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let general_string = working_read.unwrap();
|
||||||
|
println!("reading scop from general notes...");
|
||||||
|
let mut scope_ranges = Vec::new();
|
||||||
|
let general_lines: Vec<&str> = general_string.split("\n").collect();
|
||||||
|
for line in general_lines{
|
||||||
|
if line.contains("|"){
|
||||||
|
if !line.contains("range"){
|
||||||
|
if !line.contains("--"){
|
||||||
|
let items: Vec<&str> = line.split("|").collect();
|
||||||
|
let scop_item = items[1].trim();
|
||||||
|
println!("{} LOADED!!", scop_item);
|
||||||
|
scope_ranges.push(scop_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("scope loaded, parsing ip ranges...");
|
||||||
|
let mut ips = Vec::new();
|
||||||
|
for item in scope_ranges{
|
||||||
|
if item.contains("/"){
|
||||||
|
let network_split: Vec<&str> = item.split("/").collect();
|
||||||
|
let network_part = network_split[0];
|
||||||
|
let cidr = network_split[1];
|
||||||
|
let network_octets: Vec<&str> = network_part.split(".").collect();
|
||||||
|
let mut ip = String::new();
|
||||||
|
match cidr{
|
||||||
|
"24" => {let partial_ip = format!("{}.{}.{}.N", network_octets[0], network_octets[1], network_octets[2]);
|
||||||
|
ip.push_str(partial_ip);
|
||||||
|
},
|
||||||
|
"16" => {let partial_ip = format!("{}.{}.N.N", network_octets[0], network_octets[1]);
|
||||||
|
ip.push_str(partial_ip);},
|
||||||
|
"8" => {let partial_ip = format!("{}.N.N.N", network_octets[0]); ip.push_str(partial_ip)}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
pub fn get_all_host_addresses(project: &Project){
|
||||||
|
println!("to do");
|
||||||
|
}
|
||||||
@@ -1,231 +1,46 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::env::home_dir;
|
||||||
use std::fs::File;
|
use std::fs::{File, create_dir_all, remove_dir_all};
|
||||||
use std::io::Read;
|
use std::io::{read_to_string, Read};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::io::copy;
|
use std::io::copy;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::time::Duration;
|
||||||
use reqwest::blocking::get;
|
use reqwest::blocking::get;
|
||||||
use std::path::PathBuf;
|
use std::{path::Path, path::PathBuf};
|
||||||
use std::process;
|
use std::{process, thread};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
|
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
|
|
||||||
|
|
||||||
fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){
|
|
||||||
let mut delete_for_cleanup = config_path.clone();
|
|
||||||
delete_for_cleanup.pop();
|
|
||||||
let mut failed = false;
|
|
||||||
let mut new_files_folder = String::new();
|
|
||||||
let mut new_notes_folder = String::new();
|
|
||||||
let mut upcomming_files_folder = String::new();
|
|
||||||
let mut upcomming_notes_folder = String::new();
|
|
||||||
let mut tools_folder = String::new();
|
|
||||||
let mut cracking_rig = String::new();
|
|
||||||
let mut cracking_user = String::new();
|
|
||||||
let mut rockyou = String::new();
|
|
||||||
let mut rule = String::new();
|
|
||||||
while new_files_folder.is_empty() || new_notes_folder.is_empty() || tools_folder.is_empty(){
|
|
||||||
if new_files_folder.is_empty(){
|
|
||||||
println!("path to save active project files?");
|
|
||||||
match stdin().read_line(&mut new_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if new_notes_folder.is_empty(){
|
|
||||||
println!("path to save active project notes?");
|
|
||||||
match stdin().read_line(&mut new_notes_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tools_folder.is_empty(){
|
|
||||||
println!("path to custom tools (like github tools and what not)");
|
|
||||||
match stdin().read_line(&mut tools_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_files_folder.is_empty(){
|
|
||||||
println!("path to save upcomming project files?");
|
|
||||||
match stdin().read_line(&mut upcomming_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_notes_folder.is_empty(){
|
|
||||||
println!("path to save upcomming project notes?");
|
|
||||||
match stdin().read_line(&mut upcomming_notes_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cracking_rig.is_empty(){
|
|
||||||
let mut have_rig = String::new();
|
|
||||||
println!("do you have a separate computer that you can ssh into to crack passwords on?");
|
|
||||||
match stdin().read_line(&mut have_rig){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
have_rig = have_rig.to_lowercase();
|
|
||||||
if have_rig.contains("y"){
|
|
||||||
println!("excellent! Whats the IP or hostname?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut cracking_rig){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("user to ssh as for the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut cracking_user){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Path to rockyou.txt on the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut rockyou){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummyu try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Path to one rule to rule them all on the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut rule){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummyu try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if have_rig.contains("n"){
|
|
||||||
println!("ooof ok freeloader");
|
|
||||||
cracking_rig = "n".to_owned();
|
|
||||||
rule = "n".to_owned();
|
|
||||||
rockyou = "n".to_owned();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_files_folder = new_files_folder.trim_end().to_owned();
|
|
||||||
new_notes_folder = new_notes_folder.trim_end().to_owned();
|
|
||||||
upcomming_files_folder = upcomming_files_folder.trim_end().to_owned();
|
|
||||||
upcomming_notes_folder = upcomming_notes_folder.trim_end().to_owned();
|
|
||||||
tools_folder = tools_folder.trim_end().to_owned();
|
|
||||||
cracking_rig = cracking_rig.trim_end().to_owned();
|
|
||||||
cracking_user = cracking_user.trim_end().to_owned();
|
|
||||||
let new_files_path = PathBuf::from(&new_files_folder.trim_end());
|
|
||||||
let new_notes_path = PathBuf::from(&new_notes_folder.trim_end());
|
|
||||||
let upcomming_files_path = PathBuf::from(&upcomming_files_folder.trim_end());
|
|
||||||
let upcomming_notes_path = PathBuf::from(&upcomming_notes_folder.trim_end());
|
|
||||||
let tools_path = PathBuf::from(&tools_folder.trim_end());
|
|
||||||
if new_files_path.exists() == false{
|
|
||||||
println!("active project file folder does not exist, creating...");
|
|
||||||
match fs::create_dir_all(&new_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating active project files Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if new_notes_path.exists() == false{
|
|
||||||
println!("active project notes folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(new_notes_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating active project notes Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tools_path.exists() == false{
|
|
||||||
println!("tools folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(tools_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating tools Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_files_path.exists() == false{
|
|
||||||
println!("upcomming project files folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(upcomming_files_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating upcomming project files Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_notes_path.exists() == false{
|
|
||||||
println!("upcomming project notes folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(upcomming_notes_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating upcomming project notes Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if failed{
|
|
||||||
println!("install failed, cleaning up files...");
|
|
||||||
match fs::remove_dir_all(&delete_for_cleanup){
|
|
||||||
Ok(_r) => println!("cleanup successfull, please correct previously reported errors and rerun"),
|
|
||||||
Err(e) => println!("cleanup failed!: {}\nManually delete the following folder and retry\n{}", e, delete_for_cleanup.display())
|
|
||||||
}
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return (new_files_folder, new_notes_folder, tools_folder, upcomming_files_folder, upcomming_notes_folder, cracking_rig, cracking_user, rockyou, rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn configure_distrobox(){
|
|
||||||
let user_dirs_result = UserDirs::new();
|
|
||||||
let mut success = false;
|
|
||||||
let mut dbrcpath = PathBuf::new();
|
|
||||||
if user_dirs_result.is_some(){
|
|
||||||
let home = user_dirs_result.unwrap().home_dir().to_path_buf();
|
|
||||||
dbrcpath.push(home);
|
|
||||||
dbrcpath.push(".distroboxrc");
|
|
||||||
let box_config_string = String::from("container_always_pull=\"0\"\ncontainer_generate_entry=1\ncontainer_manager=\"podman\"\ncontainer_name_default=\"ubuntu\"\ncontainer_image_default=\"ghcr.io/ublue-os/ubuntu-toolbox:latest\"\nnon_interactive=\"1\"\nxhost +si:localuser:$USER >/dev/null\nexport PIPEWIRE_RUNTIME_DIR=/dev/null\nexport PATH=$PATH:$HOME/.local/bin\n");
|
|
||||||
let dbrc_file_res = fs::OpenOptions::new().write(true).create(true).open(dbrcpath);
|
|
||||||
if dbrc_file_res.is_err(){
|
|
||||||
let error = dbrc_file_res.err().unwrap();
|
|
||||||
println!("error opening distroboxrc file!");
|
|
||||||
println!("{}", error);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
let mut dibrc_file = dbrc_file_res.unwrap();
|
|
||||||
let dbrc_write_res = write!(dibrc_file, "{}",box_config_string);
|
|
||||||
if dbrc_write_res.is_err(){
|
|
||||||
println!("error writing config to distroboxrc file!");
|
|
||||||
println!("{}", dbrc_write_res.err().unwrap());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
let _dbrc_write = dbrc_write_res.unwrap();
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if success == false{
|
|
||||||
println!("Error getting user dirs!");
|
|
||||||
println!("distrobox config failed, please follow the following instructions...");
|
|
||||||
print!("
|
|
||||||
copy the distrobox config file to your home folder with the name .distroboxrc
|
|
||||||
cp /usr/etc/distrobox/distrobox.conf ~/.distroboxrc
|
|
||||||
|
|
||||||
Then edit the file to change the line container_always_pull=\"1\" to container_always_pull=\"0\"
|
|
||||||
");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn install(config_path: &PathBuf){
|
pub fn install(config_path: &PathBuf){
|
||||||
let mut _terminal_commands = HashMap::from([
|
let mut _terminal_commands = HashMap::from([
|
||||||
("konsole", "konsole -e !!!"),
|
("kde", "konsole -e !!!"),
|
||||||
|
("plasma", "konsole -e !!!"),
|
||||||
("gnome", "gnome-terminal -- bash !!!"),
|
("gnome", "gnome-terminal -- bash !!!"),
|
||||||
("xfce", "xfce4-terminal --execute '!!!'"),
|
("xfce", "xfce4-terminal --execute '!!!'"),
|
||||||
("alacritty", "alacritty -e !!!"),
|
("alacritty", "alacritty -e !!!"),
|
||||||
]);
|
]);
|
||||||
|
let mut folder_creation = true;
|
||||||
|
let current_projects = PathBuf::from(get_user_input("path to store your active projects?"));
|
||||||
|
let current_notes = PathBuf::from(get_user_input("path to store your active project notes?"));
|
||||||
|
let upcoming_projects = PathBuf::from(get_user_input("path to store your upcomming projects?"));
|
||||||
|
let upcoming_notes = PathBuf::from(get_user_input("path to store your upcomming project notes?"));
|
||||||
|
let tools = PathBuf::from(get_user_input("path where you store your custom tools (like from github and places)?"));
|
||||||
|
let mut vault_name = String::new();
|
||||||
|
let folders = vec![¤t_projects, ¤t_notes, &upcoming_projects, &upcoming_notes, &tools];
|
||||||
let mut config_folder_path: PathBuf = config_path.clone();
|
let mut config_folder_path: PathBuf = config_path.clone();
|
||||||
config_folder_path.pop();
|
config_folder_path.pop();
|
||||||
|
let mut password_path = config_folder_path.clone();
|
||||||
|
password_path.push("password_spray.md");
|
||||||
let mut projects_conf_path = config_folder_path.clone();
|
let mut projects_conf_path = config_folder_path.clone();
|
||||||
let mut bell_file_path = config_folder_path.clone();
|
let mut bell_file_path = config_folder_path.clone();
|
||||||
let del_on_fail = config_folder_path.clone();
|
let del_on_fail = config_folder_path.clone();
|
||||||
projects_conf_path.push("projects.conf");
|
projects_conf_path.push("projects.conf");
|
||||||
fs::create_dir_all(&config_folder_path).expect("error creating config dir");
|
create_dir_all(&config_folder_path).expect("error creating config dir");
|
||||||
bell_file_path.push("bell.mp3");
|
bell_file_path.push("bell.mp3");
|
||||||
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
|
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
|
||||||
let response = get(bell_sound_url).unwrap();
|
let response = get(bell_sound_url).unwrap();
|
||||||
@@ -233,101 +48,194 @@ pub fn install(config_path: &PathBuf){
|
|||||||
let mut bell_file = File::create(bell_file_path).unwrap();
|
let mut bell_file = File::create(bell_file_path).unwrap();
|
||||||
copy(&mut response.take(response_length), &mut bell_file).unwrap();
|
copy(&mut response.take(response_length), &mut bell_file).unwrap();
|
||||||
println!("bell notification tone sucessfully downloaded!");
|
println!("bell notification tone sucessfully downloaded!");
|
||||||
let mut config_file = fs::File::create(config_path).expect("error creating file");
|
println!("creating new folders if needed...");
|
||||||
let mut projects_conf_file = fs::File::create(projects_conf_path).expect("error creating projects config file");
|
for folder in &folders{
|
||||||
projects_conf_file.write_all(b"customer:name:notes:files:active:box_name:stage\n").expect("error writing default project info");
|
if !Path::exists(folder){
|
||||||
let mut terminal_response = String::new();
|
let create_res = create_dir_all(folder);
|
||||||
let mut template_name = String::new();
|
if create_res.is_err(){
|
||||||
let mut have_template = String::new();
|
let error = create_res.err().unwrap();
|
||||||
println!("terminal you use? (example: konsole, xfce, gnome, etc)");
|
println!("error creating folder {}", folder.display());
|
||||||
std::io::stdin().read_line(&mut terminal_response).unwrap();
|
println!("{}", error);
|
||||||
let mut _terminal_command = String::new();
|
println!("you'll need to create this manually after the install is done!");
|
||||||
if terminal_response.contains("konsole"){
|
folder_creation = false;
|
||||||
let mut response_buffer = String::new();
|
|
||||||
println!("do you already have a custom profile setup?");
|
|
||||||
println!("this is pretty specific to pyro's setup, I do some special sauce for my konsole stuff");
|
|
||||||
std::io::stdin().read_line(&mut response_buffer).unwrap();
|
|
||||||
if response_buffer.to_lowercase().contains("y"){
|
|
||||||
let mut profile = String::new();
|
|
||||||
println!("konsole profile name?");
|
|
||||||
std::io::stdin().read_line(&mut profile).unwrap();
|
|
||||||
_terminal_command = format!("konsole --profile {}", profile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
let tool_volume = format!("{}:/tools:rw", &tools.display());
|
||||||
|
println!("sweet, now let's get some distrobox stuff out of the way!");
|
||||||
|
let distrobox_run_res = Command::new("distrobox").arg("list").arg("--root").output();
|
||||||
|
if distrobox_run_res.is_err(){
|
||||||
|
let error = distrobox_run_res.err().unwrap();
|
||||||
|
println!("Distrobox file was not found!");
|
||||||
|
println!("This usually means that distrobox is not installed.");
|
||||||
|
println!("please install distrobox, if you're on kali run `sudo apt install distrobox`");
|
||||||
|
println!("{}", error);
|
||||||
|
println!("this project heavily relies on distrobox, as its primarily a distrobox mangement tool.");
|
||||||
|
println!("cleaning up up configuration folders, please install distrobox and re-run this program.");
|
||||||
|
let cleanup = remove_dir_all(&del_on_fail);
|
||||||
|
if cleanup.is_err(){
|
||||||
|
println!("error cleaning up configuration folder!");
|
||||||
|
println!("please manually delete {} before re-running this install.", &del_on_fail.display());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cleanup.unwrap();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let distrobox_output = distrobox_run_res.unwrap().stdout;
|
||||||
|
let distrobox_string = String::from_utf8_lossy(&distrobox_output);
|
||||||
|
let mut distrobox_names = Vec::new();
|
||||||
|
let distrobox_output_lines: Vec<&str> = distrobox_string.split("\n").collect();
|
||||||
|
for line in distrobox_output_lines{
|
||||||
|
if line.len() > 1{
|
||||||
|
let name = line.split(" | ").collect::<Vec<&str>>()[1];
|
||||||
|
distrobox_names.push(name.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut have_box = false;
|
||||||
|
for name in distrobox_names{
|
||||||
|
if !name.contains("NAME"){
|
||||||
|
have_box = true;
|
||||||
|
println!("{}", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut template_box_name = String::new();
|
||||||
|
if have_box{
|
||||||
|
template_box_name = get_user_input("Name of the distrobox you want to use as a template?");
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
_terminal_command = _terminal_commands[terminal_response.trim_end()].to_owned();
|
println!("no exiting distroboxes created!");
|
||||||
}
|
println!("let's make one!");
|
||||||
let (files_response, notes_response, tools_response, project_folder_path, project_note_path, cracking_rig, cracking_user, rockyou, rule) = setup_folders(&config_path);
|
template_box_name = get_user_input("name of the distrobox you want to create?");
|
||||||
print!("
|
println!("review images listed here: https://distrobox.it/compatibility/#containers-distros");
|
||||||
This tool is mainly to handle distrobox creation and usage.
|
let box_image = get_user_input("image you want to base the template box on?");
|
||||||
It's expecting you to have a distrobox that you will use as a template.
|
let template_box_create_res = Command::new("distrobox")
|
||||||
Do you have a distrobox set up to function as your template for all new projects?
|
|
||||||
");
|
|
||||||
std::io::stdin().read_line(&mut have_template).unwrap();
|
|
||||||
if have_template.contains("n"){
|
|
||||||
println!("ooof buddy, should have had that already... no worries, we'll make one now.");
|
|
||||||
let new_boxname = get_user_input("name for your template box? (for exmaple I use atarchbox cause its my attacking archbox ;-)");
|
|
||||||
println!("please review the following link to select an image to use for your distrobox");
|
|
||||||
println!("https://distrobox.it/compatibility/#containers-distros");
|
|
||||||
let image_name = get_user_input("which image would you like to use?");
|
|
||||||
let tools_volume =format!("{}:/tools:rw", &tools_response);
|
|
||||||
let distrobox_create_res = Command::new("distrobox")
|
|
||||||
.arg("create")
|
.arg("create")
|
||||||
.arg("--root")
|
.arg("--root")
|
||||||
.arg("--name")
|
|
||||||
.arg(new_boxname)
|
|
||||||
.arg("--init")
|
|
||||||
.arg("--image")
|
.arg("--image")
|
||||||
.arg(image_name)
|
.arg(&box_image)
|
||||||
|
.arg("--name")
|
||||||
|
.arg(&template_box_name)
|
||||||
|
.arg("--init")
|
||||||
.arg("--volume")
|
.arg("--volume")
|
||||||
.arg(tools_volume)
|
.arg(&tool_volume)
|
||||||
.arg("--additional-packages")
|
|
||||||
.arg("systemd")
|
|
||||||
.arg("--")
|
|
||||||
.arg("exit")
|
|
||||||
.status();
|
.status();
|
||||||
if distrobox_create_res.is_err(){
|
if template_box_create_res.is_err(){
|
||||||
let error = distrobox_create_res.err().unwrap();
|
let error = template_box_create_res.err().unwrap();
|
||||||
println!("ooof we ran into a problem creating your distrobox....");
|
println!("error creating template box!");
|
||||||
println!("{}", error);
|
println!("{}", error);
|
||||||
println!("you'll have to make it manually, but remember the name you want to use for the next step.");
|
println!("\n\n\nplese create it yourself with the following command.");
|
||||||
|
println!("\n\ndistrobox create --root --image {}, --name {}, --init --volume {}", &box_image, &template_box_name, &tool_volume);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
distrobox_create_res.unwrap();
|
template_box_create_res.unwrap();
|
||||||
println!("nice, we created a distrobox, remeber the name of your box for the next step!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
|
let mut cracking_rig = String::from("nobody@nothing");
|
||||||
println!("distrobox template name?");
|
let mut rockyou = String::from("n/a");
|
||||||
std::io::stdin().read_line(&mut template_name).unwrap();
|
let mut rule = String::from("n/a");
|
||||||
let mut set_fprint = String::from("no");
|
let cracking_rig_response = get_user_input("do you have a separate machine to crack passwords on? (not the ambush cracking rig)");
|
||||||
let fprint_answer = get_user_input("do you want to use fingerprint authentication inside the distroboxes?").to_lowercase();
|
if cracking_rig_response.to_lowercase().contains("y"){
|
||||||
if fprint_answer.contains("y"){
|
let rig_ip = get_user_input("ip address or hostname of your cracking rig?");
|
||||||
set_fprint = "yes".to_owned();
|
let rig_user = get_user_input("username to log into your cracking rig with?");
|
||||||
|
rockyou = get_user_input("location of rockyou.txt on the cracking rig?");
|
||||||
|
rule = get_user_input("location of one rule to rule them all on the cracking rig?");
|
||||||
|
cracking_rig = format!("{}@{}", rig_user, rig_ip);
|
||||||
}
|
}
|
||||||
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}\nfingerprint:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end(), set_fprint);
|
else{
|
||||||
config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
|
println!("ok free loader");
|
||||||
let default_projectline = format!("default:default:{}:{}:yes:{}:current", ¬es_response.trim_end(), &files_response.trim_end(), &template_name.trim_end());
|
}
|
||||||
projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line");
|
let fingerprint = get_user_input("will you be using fingerprint authentication for your distroboxes?").to_lowercase();
|
||||||
println!("active project folders: {}", &files_response);
|
let mut terminal = String::new();
|
||||||
println!("upcomming project folders: {}", &project_folder_path);
|
for desktop in _terminal_commands.keys(){
|
||||||
println!("active project notes: {}", ¬es_response);
|
println!("{}", desktop);
|
||||||
println!("upcomming prjoect notes: {}", &project_note_path);
|
}
|
||||||
println!("tools folder: {}", &tools_response);
|
let desktop_response = get_user_input("do you use any of these desktops?").to_lowercase();
|
||||||
println!("distrobox template: {}", &template_name);
|
if desktop_response.contains("y"){
|
||||||
println!("terminal command: {}", &_terminal_command);
|
let default_response = get_user_input("do you use the default terminal for your desktop?").to_lowercase();
|
||||||
println!("config file generated and saved to {}\n", config_path.display());
|
if default_response.contains("y"){
|
||||||
|
let de = get_user_input("which desktop do you use?");
|
||||||
|
terminal = _terminal_commands[&de.as_str()].to_owned();
|
||||||
let config_path = &config_folder_path.clone();
|
}
|
||||||
let mut install_path = config_path.clone();
|
}
|
||||||
let mut password_spray_template_path = install_path.clone();
|
else{
|
||||||
install_path.push("new_projects.conf");
|
println!("OK, then please enter the command you'd use to launch a new terminal and run a command inside of it, replacing the command with three !s");
|
||||||
password_spray_template_path.push("passwordspray.md");
|
println!("for example for konsole you'd enter");
|
||||||
let pass_file_config_line = format!("\npass_file:{}", password_spray_template_path.display());
|
println!("konsole -e !!!");
|
||||||
config_file.write_all(pass_file_config_line.as_bytes()).expect("error writing password spray setting to config file");
|
terminal = get_user_input("");
|
||||||
let mut passpray_file = fs::File::create(password_spray_template_path).expect("error creating passwordspray file");
|
}
|
||||||
write!(passpray_file, "
|
if terminal.contains("konsole"){
|
||||||
|
println!("do you use a specific profile for your attack boxes?");
|
||||||
|
println!("this is pretty specific to Pyro's setup, so you probably don't");
|
||||||
|
if get_user_input("").to_lowercase().contains("y"){
|
||||||
|
let profile_name = get_user_input("what is the name of your profile?");
|
||||||
|
terminal = format!("konsole --profile {}", profile_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("many of the fuctions of this tool assume you're using obsidian or some other markdown editor for note taking");
|
||||||
|
let obsidian_used = get_user_input("do you use obsidian for your notes?");
|
||||||
|
if obsidian_used.to_lowercase().contains("y"){
|
||||||
|
vault_name = get_user_input("the name of the vault you're going to use?");
|
||||||
|
}
|
||||||
|
let configuration_string = format!("
|
||||||
|
Project_files:{}
|
||||||
|
Project_notes:{}
|
||||||
|
tools_folder:{}
|
||||||
|
upcoming_files:{}
|
||||||
|
upcoming_notes:{}
|
||||||
|
box_template:{}
|
||||||
|
terminal:{}
|
||||||
|
cracking_rig:{}
|
||||||
|
rockyou_location:{}
|
||||||
|
rule_location:{}
|
||||||
|
pass_file:{}
|
||||||
|
fingerprint:{}
|
||||||
|
vault_name:{}"
|
||||||
|
, ¤t_projects.display(), ¤t_notes.display(), &tools.display(), &upcoming_projects.display(), &upcoming_notes.display(), &template_box_name, &terminal, cracking_rig, rockyou, rule, &password_path.display(), fingerprint, &vault_name);
|
||||||
|
println!("cool everything, all folders and settings have been entered, now let's save this to a config file...");
|
||||||
|
thread::sleep(Duration::from_secs(3));
|
||||||
|
let mut config_file_res = File::create_new(config_path);
|
||||||
|
if config_file_res.is_err(){
|
||||||
|
println!("ooof error creating configuration file...");
|
||||||
|
println!("try creating it manually.");
|
||||||
|
println!("copy the following configuration and save it to {}", config_path.display());
|
||||||
|
print!("{}\n", configuration_string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut config_file = config_file_res.unwrap();
|
||||||
|
let config_write_res =write!(config_file, "{}", &configuration_string);
|
||||||
|
if config_write_res.is_err(){
|
||||||
|
println!("error writing configuration string to the configuration file!");
|
||||||
|
println!(" try creating it manually.");
|
||||||
|
println!("copy the following configuration and save it to {}", &configuration_string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
config_write_res.unwrap();
|
||||||
|
println!("nice the configuration file was written correctly!");
|
||||||
|
println!("creating project configuration file, and poplulating it with the default project...");
|
||||||
|
let project_conf_res = File::create_new(&projects_conf_path);
|
||||||
|
if project_conf_res.is_err(){
|
||||||
|
let error = project_conf_res.err().unwrap();
|
||||||
|
println!("ooof error creating the projects configuration file.");
|
||||||
|
println!("try creating it manually!");
|
||||||
|
println!("copy the following configuration and save it to {}", &projects_conf_path.display());
|
||||||
|
println!("customer:name:notes:files:active:time:box_name:stage");
|
||||||
|
println!("default:default:{}:{}:yes:{}:current", ¤t_notes.display(), ¤t_projects.display(), &template_box_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
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", ¤t_notes.display(), ¤t_projects.display(), &template_box_name);
|
||||||
|
if project_write_res.is_err(){
|
||||||
|
println!("error writing project config file.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
project_write_res.unwrap();
|
||||||
|
let password_file_res = File::create_new(password_path);
|
||||||
|
if password_file_res.is_err(){
|
||||||
|
println!("error creating password spray file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut password_file = password_file_res.unwrap();
|
||||||
|
let password_write_res = write!(password_file, "
|
||||||
- [ ] useraspass
|
- [ ] useraspass
|
||||||
- [ ] Seasonyear!
|
- [ ] Seasonyear!
|
||||||
- [ ] Service123!
|
- [ ] Service123!
|
||||||
@@ -357,7 +265,13 @@ Do you have a distrobox set up to function as your template for all new projects
|
|||||||
- [ ] P@55w0rd
|
- [ ] P@55w0rd
|
||||||
- [ ] Service
|
- [ ] Service
|
||||||
- [ ] Service!
|
- [ ] Service!
|
||||||
- [ ] Serviceyear!").expect("error writing password spray template");
|
- [ ] Serviceyear!
|
||||||
configure_distrobox();
|
");
|
||||||
std::process::exit(0);
|
if password_write_res.is_err(){
|
||||||
|
println!("error writing password file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
password_write_res.unwrap();
|
||||||
|
println!("install completed successfully!");
|
||||||
|
println!("re-run this to launch!");
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::{io::stdin, path::PathBuf};
|
use std::{io::stdin, path::PathBuf, process::Command};
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use reqwest::Response;
|
use reqwest::Response;
|
||||||
use std::fs;
|
use std::process::exit;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Project{
|
pub struct Project{
|
||||||
@@ -21,6 +22,35 @@ mod project_controls;
|
|||||||
mod box_controls;
|
mod box_controls;
|
||||||
mod info_controls;
|
mod info_controls;
|
||||||
mod start_pentest;
|
mod start_pentest;
|
||||||
|
mod cli;
|
||||||
|
|
||||||
|
pub fn open_overwrite(path: &PathBuf) -> Option<File>{
|
||||||
|
let file_create_res = fs::OpenOptions::new().create(true).write(true).open(path);
|
||||||
|
if file_create_res.is_err(){
|
||||||
|
let error = file_create_res.err().unwrap();
|
||||||
|
println!("error opening {} file!", path.display());
|
||||||
|
println!("{}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let file = file_create_res.unwrap();
|
||||||
|
return Some(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_append(path: &PathBuf) -> Option<File>{
|
||||||
|
let file_create_res = fs::OpenOptions::new().create(true).append(true).open(path);
|
||||||
|
if file_create_res.is_err(){
|
||||||
|
let error = file_create_res.err().unwrap();
|
||||||
|
println!("error opening {} file!", path.display());
|
||||||
|
println!("{}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let file = file_create_res.unwrap();
|
||||||
|
return Some(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_user_input(prompt: &str) -> String{
|
pub fn get_user_input(prompt: &str) -> String{
|
||||||
let mut response = String::new();
|
let mut response = String::new();
|
||||||
@@ -60,8 +90,23 @@ fn main() {
|
|||||||
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
");
|
");
|
||||||
let user_dirs = UserDirs::new().expect("error getting user directories");
|
let mut config_path = PathBuf::new();
|
||||||
let mut config_path = user_dirs.home_dir().to_path_buf();
|
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!!!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
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");
|
config_path.push(".config/pyro_pentest_tool/conf");
|
||||||
if config_path.as_path().exists() == false{
|
if config_path.as_path().exists() == false{
|
||||||
install::install(&config_path);
|
install::install(&config_path);
|
||||||
@@ -78,6 +123,7 @@ fn main() {
|
|||||||
let mut upcoming_notes = PathBuf::new();
|
let mut upcoming_notes = PathBuf::new();
|
||||||
let mut pass_spray_file = PathBuf::new();
|
let mut pass_spray_file = PathBuf::new();
|
||||||
let mut fingerprint = false;
|
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_string = fs::read_to_string(&config_path).expect("error reading config file");
|
||||||
let settings: Vec<&str> = settings_string.split("\n").collect();
|
let settings: Vec<&str> = settings_string.split("\n").collect();
|
||||||
@@ -97,6 +143,7 @@ fn main() {
|
|||||||
"rule_location" => rule = setting_vec[1].trim_end().to_owned(),
|
"rule_location" => rule = setting_vec[1].trim_end().to_owned(),
|
||||||
"pass_file"=> pass_spray_file.push(setting_vec[1]),
|
"pass_file"=> pass_spray_file.push(setting_vec[1]),
|
||||||
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}},
|
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}},
|
||||||
|
"vault_name" => vault_name = setting_vec[1].trim_end().to_owned(),
|
||||||
_ => println!("error unknown setting: {}", setting_vec[0])
|
_ => println!("error unknown setting: {}", setting_vec[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,9 +159,9 @@ fn main() {
|
|||||||
upcoming project notes: {}
|
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());
|
", &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...");
|
println!("loading project configs...");
|
||||||
let projects = project_controls::get_projects(&config_path);
|
let projects = project_controls::get_projects(&config_path, true);
|
||||||
println!("Enter to start main menu");
|
println!("Enter to start main menu");
|
||||||
let mut enter = String::new();
|
let mut enter = String::new();
|
||||||
std::io::stdin().read_line(&mut enter).unwrap();
|
std::io::stdin().read_line(&mut enter).unwrap();
|
||||||
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint);
|
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint, vault_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ 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::cli;
|
||||||
|
|
||||||
fn next_project_id(config_path: &PathBuf) -> i32{
|
pub fn next_project_id(config_path: &PathBuf) -> i32{
|
||||||
let projects = project_controls::get_projects(config_path);
|
let projects = project_controls::get_projects(config_path, false);
|
||||||
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{
|
||||||
@@ -21,7 +22,7 @@ fn next_project_id(config_path: &PathBuf) -> i32{
|
|||||||
return new_id;
|
return new_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_active_project(projects: &Vec<Project>) -> &Project{
|
pub fn get_active_project(projects: &Vec<Project>) -> &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{
|
||||||
@@ -31,12 +32,27 @@ fn get_active_project(projects: &Vec<Project>) -> &Project{
|
|||||||
return active_project
|
return active_project
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &PathBuf, base_notes: &PathBuf, tools_dir: &PathBuf, boxtemplate: String, terminal: String, cracking_rig: String, rockyou: String, rule: String, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, password_spray_file: &PathBuf, fingerprint: bool){
|
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &PathBuf, base_notes: &PathBuf, tools_dir: &PathBuf, boxtemplate: String, terminal: String, cracking_rig: String, rockyou: String, rule: String, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, password_spray_file: &PathBuf, fingerprint: bool, vault_name: String){
|
||||||
let mut loopize = true;
|
let mut loopize = true;
|
||||||
let mut new_id = next_project_id(&config_path);
|
let mut new_id = next_project_id(&config_path);
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
let active_project = get_active_project(&projects);
|
let active_project = get_active_project(&projects);
|
||||||
|
let mut notes_folder_string = format!("{}", &active_project.notes_folder.display());
|
||||||
|
let mut obsidian_folder_vec = PathBuf::new();
|
||||||
|
let mut reached_vault_folder = false;
|
||||||
|
for folder in notes_folder_string.split("/").collect::<Vec<&str>>(){
|
||||||
|
if !folder.contains(&vault_name){
|
||||||
|
reached_vault_folder = true;
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if reached_vault_folder{
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let obsidian_uri = format!("obsidian://open?vault={}&file={}", vault_name, obsidian_folder_vec.display().to_string().replace("/", "%2F"));
|
||||||
let mut response = String::new();
|
let mut response = String::new();
|
||||||
let now = Local::now();
|
let now = Local::now();
|
||||||
let month = now.month();
|
let month = now.month();
|
||||||
@@ -98,25 +114,26 @@ pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
NOTE OPTION 18 WILL SAVE YOUR PROJECTS BEFORE QUITTING
|
NOTE OPTION 29 WILL SAVE YOUR PROJECTS BEFORE QUITTING
|
||||||
|
|
||||||
base prject folder: {}
|
base prject folder: {}
|
||||||
upcoming project folder: {}
|
upcoming project folder: {}
|
||||||
Current Project: {} {}
|
Current Project: {} {}
|
||||||
Working Folder: {}
|
Working Folder: {}
|
||||||
Notes Folder: {}
|
Obsidian_uri: {}
|
||||||
Box Name: {}
|
Box Name: {}
|
||||||
Terminal Command: {}
|
Terminal Command: {}
|
||||||
Current Season: {}
|
Current Season: {}
|
||||||
Year: {}
|
Year: {}
|
||||||
|
General Notes: {}
|
||||||
|
|
||||||
Main Menu:
|
Main Menu:
|
||||||
1 .) Show Active Project
|
1 .) Show Active Project
|
||||||
2 .) List Projects
|
2 .) List Projects
|
||||||
3 .) Switch Active Project
|
3 .) Switch Active Project
|
||||||
4 .) create new project with Pyro's default tool
|
4 .) create new project with Pyro's default layout
|
||||||
5 .) Save Project Information
|
5 .) Save Project Information
|
||||||
6 .) Import New Project - and setup new Distrobox
|
6 .) Import New Project to Current projects list - and setup new Distrobox
|
||||||
7 .) Remove Project
|
7 .) Remove Project
|
||||||
8 .) Print upcoming projects
|
8 .) Print upcoming projects
|
||||||
9. ) promote project from upcoming to current
|
9. ) promote project from upcoming to current
|
||||||
@@ -124,51 +141,48 @@ Year: {}
|
|||||||
11.) Open A Terminal In this windows for the current active project
|
11.) Open A Terminal In this windows for the current active project
|
||||||
12.) open current project's cobalt strike
|
12.) open current project's cobalt strike
|
||||||
13.) re-create the distrobox for the current active project
|
13.) re-create the distrobox for the current active project
|
||||||
14.) Open Project Files Folder In Dolphin
|
14.) generate userpass file from your obsidian notes
|
||||||
15.) Open Project Notes Folder In Dolphin
|
15.) run pyro's initail enum script on a nessus csv for the current project
|
||||||
16.) generate userpass file from your obsidian notes
|
16.) build external attack notes from host notes
|
||||||
17.) run pyro's initail enum script on a nessus csv for the current project
|
17.) Build host discovery cmd command from scope in notes
|
||||||
18.) Print Project Info For Report
|
18.) build portscan command from scope in notes
|
||||||
19.) Build host discovery cmd command from scope in notes
|
19.) parse a cs portscan services.tsv file
|
||||||
20.) build portscan command from scope in notes
|
20.) Stop All Distroboxes
|
||||||
21.) Stop All Distroboxes
|
21.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||||
22.) Password Spray (will print password to spray, and wait the obervation window time)
|
22.) Launch bloodhound with the current project's distrobox
|
||||||
23.) crack password hashes on your cracking rig
|
23.) Parse GatherContacts output file
|
||||||
24.) Launch bloodhound with the current project's distrobox
|
24.) prune unused distroboxes (free up system storage)
|
||||||
25.) prune unused distroboxes (free up system storage)
|
25.) enter cli
|
||||||
26.) Quit Application
|
26.) Quit Application
|
||||||
\n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year);
|
\n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year, &obsidian_uri);
|
||||||
std::io::stdin().read_line(&mut response).expect("error getting menu input");
|
std::io::stdin().read_line(&mut response).expect("error getting menu input");
|
||||||
clear().expect("error clearing screen");
|
clear().expect("error clearing screen");
|
||||||
match response.as_str().trim_end(){
|
match response.as_str().trim_end(){
|
||||||
"1" => 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()),
|
"1" => {let cli_thread_option = cli::run_command(String::from("show active project"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"2" => {println!("+++++++++++++++++++++");
|
"2" => {let cli_thread_option = cli::run_command(String::from("list projects"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
for project in &projects{
|
"3" => {let cli_thread_option = cli::run_command(String::from("switch project"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)}
|
"4" => {let cli_thread_option = cli::run_command(String::from("new project"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
println!("++++++++++++++++++++")},
|
"5" => {let cli_thread_option = cli::run_command(String::from("save projects"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"3" => project_controls::switch_project(&mut projects),
|
"6" => {let cli_thread_option = cli::run_command(String::from("import projects"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)},
|
"7" => {let cli_thread_option = cli::run_command(String::from("remove project"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"5" => project_controls::save_projects(&projects, &config_path),
|
"8" => {let cli_thread_option = cli::run_command(String::from("show upcoming projects"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint)},
|
"9" => {let cli_thread_option = cli::run_command(String::from("promote project"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"7" => project_controls::remove_project(&mut projects, &config_path),
|
"10" => {let cli_thread_option = cli::run_command(String::from("new terminal"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"8" => project_controls::print_upcoming_projects(&projects),
|
"11" => {let cli_thread_option = cli::run_command(String::from("inline terminal"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint),
|
"12" => {let cli_thread_option = cli::run_command(String::from("cobalt strike"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
|
"13" => {let cli_thread_option = cli::run_command(String::from("recreate distrobox"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"11" => box_controls::project_inline_terminal(active_project.clone()),
|
"14" => {let cli_thread_option = cli::run_command(String::from("generate userpass"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}},
|
"15" => {let cli_thread_option = cli::run_command(String::from("initail enum"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint),
|
"16" => {let cli_thread_option = cli::run_command(String::from("build attack notes"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"14" => info_controls::open_in_dolphin("files", active_project.clone()),
|
"17" => {let cli_thread_option = cli::run_command(String::from("host discovery"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"15" => info_controls::open_in_dolphin("notes", active_project.clone()),
|
"18" => {let cli_thread_option = cli::run_command(String::from("port scan"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"16" => info_controls::generate_userpass(&active_project),
|
"19" => {let cli_thread_option = cli::run_command(String::from("parse port scan"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"17" => info_controls::run_initial_enum(&active_project),
|
"20" => {let cli_thread_option = cli::run_command(String::from("stop boxes"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"18" => info_controls::print_report_information(active_project.clone()),
|
"21" => {let cli_thread_option = cli::run_command(String::from("password spray"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"19" => info_controls::build_cmd_for_host_discovery(&active_project),
|
"22" => {let cli_thread_option = cli::run_command(String::from("bloodhound"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"20" => info_controls::build_cs_portscan_cmd(&active_project),
|
"23" => {let cli_thread_option = cli::run_command(String::from("parse gather contacts"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"21" => box_controls::stop_all_boxes(&projects),
|
"24" => {let cli_thread_option = cli::run_command(String::from("prun distroboxes"), projects.clone(), 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 cli_thread_option.is_some(){threads.push(cli_thread_option.unwrap());}},
|
||||||
"22" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
|
"25" => {let cli_threads_option = cli::cli(true, projects.clone(), 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 cli_threads_option.is_some(){for thread in cli_threads_option.unwrap(){threads.push(thread);}}},
|
||||||
"23" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
|
|
||||||
"24" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);},
|
|
||||||
"25" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
|
|
||||||
"26" => {project_controls::save_projects(&projects, &config_path);
|
"26" => {project_controls::save_projects(&projects, &config_path);
|
||||||
let mut stop = String::new();
|
let mut stop = String::new();
|
||||||
println!("stop all boxes?\ny/n");
|
println!("stop all boxes?\ny/n");
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use std::thread;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
use fs_extra::file;
|
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::box_controls::make_box;
|
use crate::box_controls::make_box;
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ pub fn switch_project(projects: &mut Vec<Project>){
|
|||||||
project.active = false;
|
project.active = false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
println!("error unknown project id")
|
println!("error unknown project id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,7 +289,7 @@ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
pub fn get_projects(config_path: &PathBuf, show: bool) -> 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");
|
||||||
@@ -327,7 +326,9 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
|||||||
}
|
}
|
||||||
let project_stage = settings[6].to_owned();
|
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};
|
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);
|
println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
|
||||||
|
}
|
||||||
projects.push(new_project);
|
projects.push(new_project);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,3 +446,10 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn list_projects(projects: &Vec<Project>){
|
||||||
|
println!("+++++++++++++++++++++");
|
||||||
|
for project in projects{
|
||||||
|
println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)}
|
||||||
|
println!("++++++++++++++++++++")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user