Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2346988e23 | ||
|
|
5bfa645b3d | ||
|
|
012ba517ab | ||
|
|
649dad5e79 | ||
|
|
2e839adccf | ||
|
|
fc316c2a71 | ||
|
|
31dd862579 | ||
|
|
b85d0e5d79 | ||
|
|
477ac6e360 | ||
|
|
fe6524016f | ||
|
|
967052a4e2 | ||
|
|
2796d31f14 | ||
|
|
b137e0c34d | ||
|
|
8a1dca30e1 | ||
|
|
854feb2e2a | ||
|
|
bfa766a2c3 | ||
|
|
f7bdd0ad8a | ||
|
|
16706f8f6d | ||
|
|
b6ec849b36 | ||
|
|
69f5a4bd78 | ||
|
|
cad1f9d51c | ||
|
|
837012d163 | ||
|
|
4dba68cdcf | ||
|
|
7765640e0e | ||
|
|
d50625167b |
@@ -53,11 +53,11 @@ Current engagements: client1 internal pentest, client 2 internal pentest
|
||||
|
||||
This tool automatically creates the file structure, and if you use the start_pentest option populates the markdown note files with the templates I use.
|
||||
|
||||
For example if I get a new internal pentest engagement for client 3 but it hasn't started yet I'll start by creating the folder and note structure using option 4 in the menu system. This would create the folder structure and notes templates in the /home/pyro/pentests/upcomming/client3/internal_pentest and /home/pyro/notes/upcomming/client3/internal_pentest folders respectively. It does not create the distrobox or add it to the tracked project list yet.
|
||||
For example if I get a new internal pentest engagement for client 3 but it hasn't started yet I'll start by creating the folder and note structure using option 4 in the menu system. This would create the folder structure and notes templates in the /home/pyro/pentests/upcomming/client3/internal_pentest and /home/pyro/notes/upcomming/client3/internal_pentest folders respectively. It does not create the distrobox, but it does add it to the list of tracked projects, with a status of upcomming.
|
||||
|
||||
Once the engagement starts I'd run option 6 "import new project - and set up new distrobox" from the menu system. It will ask if you have an existing folder structure to copy over, since I created that structure before with option 4 I would answer y, yes, or anything with the letter y in it. Then it prompts you to past the path to the folders to copy over. Here I browse to /home/pyro/pentests/upcomming in dolphin. I right click on the client3 folder and select "copy path" and then paste that into the terminal. I repeat this process for the notes folder.
|
||||
Once the engagement starts I'd run option 9 to promote a project from upcomming status to current status. This will automatically copy the needed files over, and will clean up the empty directory in the upcomming files directory, but the empty folder in the upcomming notes folder is still not cleaning correctly, I'm working on that.
|
||||
|
||||
It then attempts to guess the client name and project name based on the folder structure, and asks you to confirm. If its correct the project object will be created, the folders will be copied, and a new distrobox will be set up. If it is not correct it will prompt you to correct it, then copy the files, create a new project object, and setup a new distrobox. At the moment it is not very fault tollerant and will fail if there is an existing folder with the same name. I plan to fix that later, but haven't gotten around to it yet. Once the distro box is set up (this takes a while) it will return you to the main menu.
|
||||
It then will create a new distrobox and ask you if you need to set up cobalt strike for the project. if so it'll ask you for the path to your cobalt strike, it'll copy that into the project files folder so that you can run it if needed.
|
||||
|
||||
During the test I use the menu system to spawn new terminals in the distrobox created for the engagement, use the various file generation options to get data in easily usable format for attack operations, etc.
|
||||
|
||||
|
||||
6
ToDo.md
6
ToDo.md
@@ -3,11 +3,11 @@
|
||||
|
||||
2.) cracte hash cracking with current computer code.
|
||||
|
||||
3.) adapt new project code to searh the upcomming folder before prompting for a path.
|
||||
|
||||
4.) create code that moves projects to a "writing" state and folder.
|
||||
|
||||
5.) create code that tracks "current, upcomming, and writing" states, maybe automatic zipping of folders after writing is done?
|
||||
upcoming and current are done, but need to add writing yet...
|
||||
|
||||
# Unplanned, but would be cool
|
||||
1.) create a "server" and "Client" infrastructure that can help manage the distrobox clients and the main server
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
4.) implement a function to execute those copied exploits.
|
||||
|
||||
5.) add a "client" model for compromised internal hosts, this would likely need to be a server from a networking perspective that listens on 127.0.0.1 and then have the main interface connect to that over a proxy to run jobs. a good starting point would be to run some of our enumeration commands and scripts and save the output to the notes directly.
|
||||
|
||||
6.) add the ability to interact with the cobalt strike beacons... would need to learn agressor script... what a pain...
|
||||
|
||||
|
||||
# NOTE
|
||||
if you wish to contribute, please do! just fix a bug or implement any of the above features and make a pull request!!
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use std::process::Command;
|
||||
use std::{path::PathBuf, process};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::stdin;
|
||||
use std::io::Write;
|
||||
use std::thread;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use std::str::FromStr;
|
||||
use crate::Project;
|
||||
use crate::{get_user_input, Project};
|
||||
|
||||
pub fn stop_all_boxes(projects: &Vec<Project>){
|
||||
let mut problem_childs: Vec<Project> = Vec::new();
|
||||
@@ -44,6 +43,10 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String){
|
||||
if terminal.contains("profile"){
|
||||
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 mut terminal_start = process::Command::new(terminal_vec[0]);
|
||||
let mut first = true;
|
||||
@@ -71,7 +74,12 @@ pub fn project_inline_terminal(project: Project){
|
||||
process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
|
||||
}
|
||||
|
||||
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool){
|
||||
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool){
|
||||
println!("stopping template box to ensure we can clone it!");
|
||||
let stop_result = Command::new("distrobox").arg("stop").arg("--root").arg(boxtemplate).status();
|
||||
if stop_result.is_err(){
|
||||
println!("error stopping template!");
|
||||
}
|
||||
if !new{
|
||||
let _distrobox_stop_status = process::Command::new("distrobox").arg("stop").arg("--root").arg(&project.boxname).status().expect("error stopping distrobox");
|
||||
let distrobox_rm_status = process::Command::new("distrobox-rm")
|
||||
@@ -87,27 +95,43 @@ pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, ne
|
||||
}
|
||||
}
|
||||
let mut box_name_path = project.files_folder.clone();
|
||||
let mut box_name = format!("atarchbox_{}", &project.customer);
|
||||
let box_name = format!("{}_{}", &boxtemplate, &project.customer);
|
||||
box_name_path.push("boxname");
|
||||
let mut box_name_file = fs::File::create(box_name_path).expect("Error creating box name file");
|
||||
box_name_file.write_all(&box_name.as_bytes()).expect("error writing boxname to box file");
|
||||
let pentest_volume = format!("{}:/pentest:rw", &project.files_folder.display());
|
||||
let toold_volume = format!("{}:/tools:rw", tools_dir.display());
|
||||
println!("distrobox create --root --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
|
||||
let distrobox_result = process::Command::new("distrobox")
|
||||
.arg("create")
|
||||
.arg("--root")
|
||||
.arg("--clone")
|
||||
.arg(boxtemplate)
|
||||
.arg("--volume")
|
||||
.arg(&toold_volume)
|
||||
.arg("--volume")
|
||||
.arg(&pentest_volume)
|
||||
.arg("--name")
|
||||
.arg(&box_name)
|
||||
.status()
|
||||
.expect("error getting distrobox status");
|
||||
if distrobox_result.success(){
|
||||
let mut distrobox_cmd = String::new();
|
||||
if fingerprint{
|
||||
println!("creating box with shared volume for fingerprints... note you will still need to set up fingerprint authentication in your distrobox");
|
||||
println!("\nfor example, you may need to install fprintd and imagemegick on your template box, and set up the pam files to utilize finger print auth");
|
||||
println!("\nsee https://wiki.archlinux.org/title/Fprint for more information and instructions");
|
||||
distrobox_cmd = format!("distrobox create --root --init --clone {} --volume {} --volume {} --volume /var/lib/fprint:/var/lib/fprint:rw --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
|
||||
}
|
||||
else {
|
||||
distrobox_cmd = format!("distrobox create --root --init --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
|
||||
}
|
||||
println!("{}", distrobox_cmd);
|
||||
let distrobox_cmd_vec: Vec<&str> = distrobox_cmd.split_whitespace().collect();
|
||||
let mut distrobox_cmd_build = process::Command::new("distrobox");
|
||||
let mut first = true;
|
||||
for word in &distrobox_cmd_vec{
|
||||
if first == false{
|
||||
println!("adding {} as an argument for the creation command...", word);
|
||||
distrobox_cmd_build.arg(word);
|
||||
}
|
||||
else{
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
let distrobox_result = distrobox_cmd_build.status();
|
||||
if distrobox_result.is_err(){
|
||||
println!("oooof we ran into trouble creating your distrobox!!");
|
||||
println!("try creating it manually!");
|
||||
println!("{}", distrobox_cmd);
|
||||
}
|
||||
else{
|
||||
if distrobox_result.unwrap().success(){
|
||||
println!("we made a distrobox oh boy!");
|
||||
let distrobox_start_result = process::Command::new("distrobox")
|
||||
.arg("enter")
|
||||
@@ -120,19 +144,143 @@ pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, ne
|
||||
.arg("-sf")
|
||||
.arg("/pentest/boxname")
|
||||
.arg("/etc/boxname")
|
||||
.status()
|
||||
.expect("error getting response from distrobox start");
|
||||
if distrobox_start_result.success(){
|
||||
.status();
|
||||
if distrobox_start_result.is_err(){
|
||||
println!("ooof did not start successfully try entering it yoruself");
|
||||
println!("distrobox enter --root {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
|
||||
}
|
||||
else if distrobox_start_result.unwrap().success(){
|
||||
println!("distrobox was started as well!!!! good job me!");
|
||||
}
|
||||
else{
|
||||
else {
|
||||
println!("ooof did not start successfully try entering it yoruself");
|
||||
println!("distrobox enter --rrot {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
|
||||
println!("distrobox enter --root {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
|
||||
}
|
||||
}
|
||||
else{
|
||||
println!("ooof distrobox did not work.... try creating it yourself");
|
||||
println!("distrobox create --root --clone {} --volume {} --volume {} --name {}", boxtemplate, &toold_volume, &pentest_volume, &box_name);
|
||||
println!("distrobox enter --rrot {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn clean_unused_boxes(projects: &Vec<Project>, boxtemplate: &String) -> Option<JoinHandle<()>>{
|
||||
println!("starting template box: {}", boxtemplate);
|
||||
let template_status = process::Command::new("distrobox").arg("enter").arg("--root").arg(boxtemplate).arg("--").arg("exit").status();
|
||||
if template_status.is_err(){
|
||||
let start_error = template_status.err().unwrap();
|
||||
println!("OOOF issue starting template box, cancelling...");
|
||||
println!("ERROR: {}", start_error);
|
||||
return None;
|
||||
}
|
||||
println!("starting project boxes...");
|
||||
for project in projects{
|
||||
if project.stage.contains("current"){
|
||||
let start_status = process::Command::new("distrobox").arg("enter").arg("--root").arg(&project.boxname).arg("--").arg("exit").status();
|
||||
if start_status.is_err(){
|
||||
let start_error = start_status.err().unwrap();
|
||||
println!("OOOF issue starting {}, cancelling...", project.boxname);
|
||||
println!("ERROR: {}", start_error);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("pruning unused containers...");
|
||||
let handle = thread::spawn(move ||{
|
||||
let spawn_result = process::Command::new("sudo").arg("podman").arg("system").arg("prune").arg("-a").arg("-f").output();
|
||||
if spawn_result.is_err(){
|
||||
let spawn_error = spawn_result.err().unwrap();
|
||||
println!("oof trouble spawing prune command!, try manually");
|
||||
println!("ERROR: {}", spawn_error);
|
||||
}
|
||||
println!("PRUNING COMPLETE!");
|
||||
});
|
||||
thread::sleep(Duration::from_secs(3));
|
||||
println!("this will take some time, but its running on a different thread so you can continue working!");
|
||||
return Some(handle);
|
||||
}
|
||||
|
||||
pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
|
||||
let mut check_path = PathBuf::new();
|
||||
check_path.push(&project.files_folder);
|
||||
check_path.push("cobaltstrike/client");
|
||||
if check_path.as_path().exists() == false{
|
||||
println!("looks like you don't have cobalt strike set up on this beacon... try copying your cobalt strike folder to the following path!");
|
||||
println!("{}", &check_path.display());
|
||||
return None;
|
||||
}
|
||||
println!("you will need to enter your sudo password shortly, when you've done that successfully please type END and hit enter");
|
||||
let handle = thread::spawn(move ||{
|
||||
let mut cs_dir = PathBuf::new();
|
||||
cs_dir.push(project.files_folder);
|
||||
cs_dir.push("cobaltstrike/client");
|
||||
let cd_res = env::set_current_dir(&cs_dir);
|
||||
if cd_res.is_ok(){
|
||||
let cobalt_strike_launch_result = Command::new("distrobox")
|
||||
.arg("enter")
|
||||
.arg("--root").arg(project.boxname)
|
||||
.arg("--")
|
||||
.arg("./cobaltstrike")
|
||||
.output();
|
||||
if cobalt_strike_launch_result.is_err(){
|
||||
let error = cobalt_strike_launch_result.err().unwrap();
|
||||
println!("error launching cobalt strike!");
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
loop{
|
||||
let end = get_user_input("please enter END if the sudo password was enter correctly!");
|
||||
if end == "END".to_string(){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Some(handle);
|
||||
}
|
||||
|
||||
pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
|
||||
let mut bloodhound_command = String::new();
|
||||
let version_response = get_user_input("do you want to use a specific bloodhound version?");
|
||||
if version_response.to_lowercase().contains("y"){
|
||||
bloodhound_command = get_user_input("path to the bloodhound binary you want to use?");
|
||||
}
|
||||
else{
|
||||
bloodhound_command = "bloodhound".to_owned();
|
||||
}
|
||||
let mut neo4j_started = false;
|
||||
let neo4jstart_res = Command::new("distrobox")
|
||||
.arg("enter")
|
||||
.arg("--root")
|
||||
.arg(&project.boxname)
|
||||
.arg("--")
|
||||
.arg("sudo")
|
||||
.arg("neo4j")
|
||||
.arg("start")
|
||||
.status();
|
||||
if neo4jstart_res.is_err(){
|
||||
let error = neo4jstart_res.err().unwrap();
|
||||
println!("errror starting neo4j...");
|
||||
println!("{}", error);
|
||||
}
|
||||
else{
|
||||
neo4j_started = true;
|
||||
thread::sleep(Duration::from_secs(3));
|
||||
}
|
||||
if neo4j_started == false{
|
||||
println!("review previous errors, not spawning bloodhound thread...");
|
||||
return None;
|
||||
}
|
||||
let handle = thread::spawn(move ||{
|
||||
let bloodhound_res = Command::new("distrobox")
|
||||
.arg("enter")
|
||||
.arg("--root")
|
||||
.arg(&project.boxname)
|
||||
.arg("--")
|
||||
.arg(bloodhound_command)
|
||||
.output();
|
||||
if bloodhound_res.is_err(){
|
||||
let error = bloodhound_res.err().unwrap();
|
||||
println!("error starting bloodhound!");
|
||||
println!("{}", error);
|
||||
}
|
||||
});
|
||||
return Some(handle);
|
||||
}
|
||||
@@ -1,28 +1,172 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::write;
|
||||
use std::fs;
|
||||
use std::fs::create_dir_all;
|
||||
use std::fs::read_to_string;
|
||||
use std::fs::OpenOptions;
|
||||
use std::hash::Hash;
|
||||
use std::io::BufReader;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::process::Command;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::io::stdin;
|
||||
use std::thread::JoinHandle;
|
||||
use chrono::format;
|
||||
use fs_extra::file;
|
||||
use reqwest::dns::Name;
|
||||
use walkdir::WalkDir;
|
||||
use clearscreen::clear;
|
||||
use clearscreen;
|
||||
use rodio::{Decoder, OutputStream, Sink};
|
||||
use crate::get_user_input;
|
||||
use crate::open_overwrite;
|
||||
use crate::open_append;
|
||||
use crate::Project;
|
||||
|
||||
pub fn run_initial_enum(project: &Project){
|
||||
let mut csv = String::new();
|
||||
println!("path to the csv?");
|
||||
std::io::stdin().read_line(&mut csv).unwrap();
|
||||
let status = process::Command::new("initial_recon").arg(&csv).arg(&project.customer).arg(&project.project_name).status().expect("error running initial_recon program");
|
||||
if status.success(){
|
||||
println!("execllent! hosts should be imported to {}/host_notes.md", &project.notes_folder.display());
|
||||
#[derive(Clone)]
|
||||
struct Target {
|
||||
address: String,
|
||||
ports: Vec<String>
|
||||
}
|
||||
|
||||
let mut targets:Vec<Target> = Vec::new();
|
||||
println!("log into nessus and export a report, only checking the host, protocol, and port boxes");
|
||||
let mut host_notes_path = project.notes_folder.clone();
|
||||
let mut attack_notes_path = project.notes_folder.clone();
|
||||
host_notes_path.push("host_notes.md");
|
||||
attack_notes_path.push("attacks");
|
||||
let csv_path = get_user_input("path to nessus report CSV?");
|
||||
let csv_read_res = fs::read_to_string(&csv_path);
|
||||
if csv_read_res.is_err(){
|
||||
let error = csv_read_res.err().unwrap();
|
||||
println!("error reading csv!");
|
||||
println!("{}", error);
|
||||
return;
|
||||
}
|
||||
let csv_data = csv_read_res.unwrap();
|
||||
for line in csv_data.split("\n").collect::<Vec<&str>>(){
|
||||
if line.len() > 1{
|
||||
let data: Vec<&str> = line.split(",").collect();
|
||||
let address = data[0].replace("\"", "").trim().to_owned();
|
||||
let port = data[2].replace("\"", "").trim().to_owned();
|
||||
let protocol = data[1].replace("\"", "").trim().to_owned();
|
||||
if &address == &"Host"{
|
||||
continue;
|
||||
}
|
||||
else if &port == &"0"{
|
||||
continue;
|
||||
}
|
||||
let port_entry = format!("{}:{}", &protocol, &port);
|
||||
let mut is_new = true;
|
||||
for target in &mut targets{
|
||||
if target.address == address{
|
||||
if !target.ports.contains(&port_entry){
|
||||
target.ports.push(port_entry.clone());
|
||||
}
|
||||
is_new = false;
|
||||
}
|
||||
}
|
||||
if is_new{
|
||||
let new_target = Target{address: address.to_owned(), ports: vec![port_entry.clone()]};
|
||||
targets.push(new_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
for target in &targets{
|
||||
let host_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&host_notes_path);
|
||||
if host_notes_open_res.is_err(){
|
||||
let error = host_notes_open_res.err().unwrap();
|
||||
println!("error opening host notes file!");
|
||||
println!("{}", error);
|
||||
return;
|
||||
}
|
||||
let host_notes = host_notes_open_res.unwrap();
|
||||
let attack_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&attack_notes_path);
|
||||
if attack_notes_open_res.is_err(){
|
||||
let error = attack_notes_open_res.err().unwrap();
|
||||
println!("error opening attack notes!");
|
||||
println!("{}", error);
|
||||
return;
|
||||
}
|
||||
for target in targets.clone(){
|
||||
let mut output = format!("# {}\n## Ports\n| port | service | attack notes |\n| ----- | ------- | ------------ |\n", target.address);
|
||||
for port in target.ports{
|
||||
output.push_str(format!("| {} | | [[attacks]]\n", port).as_str());
|
||||
}
|
||||
output.push_str("\n");
|
||||
write!(&host_notes, "{}", output).expect("error writing host_notes");
|
||||
println!("{} notes written!", target.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_external_attack_notes(project: &Project){
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Port{
|
||||
number: String,
|
||||
hosts: Vec<String>,
|
||||
}
|
||||
|
||||
let mut ports: Vec<Port> = Vec::new();
|
||||
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");
|
||||
attack_notes_path.push("attacks.md");
|
||||
let host_notes_read_res = fs::read_to_string(host_notes_path);
|
||||
if host_notes_read_res.is_err(){
|
||||
let error = host_notes_read_res.err().unwrap();
|
||||
println!("error reading host notes!");
|
||||
println!("{}", error);
|
||||
return;
|
||||
}
|
||||
let host_notes = host_notes_read_res.unwrap();
|
||||
let attack_open_res = fs::OpenOptions::new().append(true).create(true).open(attack_notes_path);
|
||||
if attack_open_res.is_err(){
|
||||
let error = attack_open_res.err().unwrap();
|
||||
println!("error opening attack notes!");
|
||||
println!("{}", error);
|
||||
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("##"){
|
||||
current_host = line.split_whitespace().collect::<Vec<&str>>()[1].trim().to_owned();
|
||||
}
|
||||
}
|
||||
if line.contains("|"){
|
||||
let table_data:Vec <&str> = line.split("|").collect();
|
||||
for item in table_data{
|
||||
let mut is_new = true;
|
||||
if item.contains(":"){
|
||||
for port in &mut ports{
|
||||
if port.number == item.trim(){
|
||||
if port.hosts.contains(¤t_host){
|
||||
port.hosts.push(current_host.clone());
|
||||
}
|
||||
is_new = false;
|
||||
}
|
||||
}
|
||||
if is_new{
|
||||
let new_port = Port{number: line.trim().to_owned(), hosts:vec![current_host.clone()]};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for port in ports{
|
||||
let output = format!("# {}\nHOSTS:\n", port.number);
|
||||
for host in port.hosts{
|
||||
// output.push_str("## {}");
|
||||
}
|
||||
else{
|
||||
println!("ooof something went wrong, host notes may not have saved correctly!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,3 +726,434 @@ pub fn crack_hashes(cracking_rig: &String, project: &Project, terminal: &String,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_mssql_column_names(project: &Project) -> Option<JoinHandle<()>>{
|
||||
let mut notes_file = project.notes_folder.clone();
|
||||
notes_file.push("l00t/db_stuff");
|
||||
println!("NOTE: this funtion relies on netexec, make sure its installed properly!");
|
||||
let mut servers = Vec::new();
|
||||
let username = get_user_input("username for the databases?");
|
||||
let password = get_user_input("password for the databases?");
|
||||
let local_auth = get_user_input("Will you be using Windows Authentication for this?").to_lowercase();
|
||||
loop{
|
||||
for server in &servers{
|
||||
println!("{}", server);
|
||||
}
|
||||
let new_server = get_user_input("server to add? (enter DONE when you're finished)");
|
||||
if new_server == "DONE".to_owned(){
|
||||
break;
|
||||
}
|
||||
servers.push(new_server);
|
||||
}
|
||||
let db_handle = thread::spawn(move ||{
|
||||
for server in servers{
|
||||
let mut db_notes_path = notes_file.clone();
|
||||
let mut dbs = Vec::new();
|
||||
if local_auth.contains("n"){
|
||||
let netexec_cmd_res = Command::new("proxychains")
|
||||
.arg("netexec")
|
||||
.arg("mssql")
|
||||
.arg(&server)
|
||||
.arg("-u")
|
||||
.arg(&username)
|
||||
.arg("-p")
|
||||
.arg(&password)
|
||||
.arg("--local-auth")
|
||||
.arg("-q")
|
||||
.arg("\"SELECT name FROM master.sys.databases\"")
|
||||
.output();
|
||||
if netexec_cmd_res.is_err(){
|
||||
let error = netexec_cmd_res.err().unwrap();
|
||||
println!("error running netexec command!");
|
||||
println!("{}", error);
|
||||
}
|
||||
else{
|
||||
let output_string = String::from_utf8(netexec_cmd_res.unwrap().stdout).unwrap();
|
||||
let words: Vec<&str> = output_string.split_whitespace().collect();
|
||||
for word in words {
|
||||
if word.contains("name:"){
|
||||
let db = word.split(":").collect::<Vec<&str>>()[1].to_owned();
|
||||
db_notes_path.push(&db);
|
||||
dbs.push(db);
|
||||
fs::create_dir_all(&db_notes_path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
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.");
|
||||
}
|
||||
@@ -1,184 +1,46 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::env::home_dir;
|
||||
use std::fs::{File, create_dir_all, remove_dir_all};
|
||||
use std::io::{read_to_string, Read};
|
||||
use std::io::Write;
|
||||
use std::io::stdin;
|
||||
use std::io::copy;
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
use reqwest::blocking::get;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::{path::Path, path::PathBuf};
|
||||
use std::{process, thread};
|
||||
use std::process::exit;
|
||||
use directories::UserDirs;
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
let new_notes_path = PathBuf::from(&new_notes_folder);
|
||||
let upcomming_files_path = PathBuf::from(&upcomming_files_folder);
|
||||
let upcomming_notes_path = PathBuf::from(&upcomming_notes_folder);
|
||||
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);
|
||||
}
|
||||
|
||||
use crate::get_user_input;
|
||||
|
||||
|
||||
pub fn install(config_path: &PathBuf){
|
||||
let mut _terminal_commands = HashMap::from([
|
||||
("konsole", "konsole -e !!!"),
|
||||
("kde", "konsole -e !!!"),
|
||||
("plasma", "konsole -e !!!"),
|
||||
("gnome", "gnome-terminal -- bash !!!"),
|
||||
("xfce", "xfce4-terminal --execute '!!!'"),
|
||||
("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();
|
||||
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 bell_file_path = config_folder_path.clone();
|
||||
let del_on_fail = config_folder_path.clone();
|
||||
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");
|
||||
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
|
||||
let response = get(bell_sound_url).unwrap();
|
||||
@@ -186,100 +48,230 @@ pub fn install(config_path: &PathBuf){
|
||||
let mut bell_file = File::create(bell_file_path).unwrap();
|
||||
copy(&mut response.take(response_length), &mut bell_file).unwrap();
|
||||
println!("bell notification tone sucessfully downloaded!");
|
||||
let mut config_file = fs::File::create(config_path).expect("error creating file");
|
||||
let mut projects_conf_file = fs::File::create(projects_conf_path).expect("error creating projects config file");
|
||||
projects_conf_file.write_all(b"customer:name:notes:files:active:box_name\n").expect("error writing default project info");
|
||||
let mut terminal_response = String::new();
|
||||
let mut template_name = String::new();
|
||||
let mut have_template = String::new();
|
||||
println!("terminal you use? (example: konsole, xfce, gnome, etc)");
|
||||
std::io::stdin().read_line(&mut terminal_response).unwrap();
|
||||
let mut _terminal_command = String::new();
|
||||
if terminal_response.contains("konsole"){
|
||||
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);
|
||||
println!("creating new folders if needed...");
|
||||
for folder in &folders{
|
||||
if !Path::exists(folder){
|
||||
let create_res = create_dir_all(folder);
|
||||
if create_res.is_err(){
|
||||
let error = create_res.err().unwrap();
|
||||
println!("error creating folder {}", folder.display());
|
||||
println!("{}", error);
|
||||
println!("you'll need to create this manually after the install is done!");
|
||||
folder_creation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
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{
|
||||
println!("no exiting distroboxes created!");
|
||||
println!("let's make one!");
|
||||
template_box_name = get_user_input("name of the distrobox you want to create?");
|
||||
println!("review images listed here: https://distrobox.it/compatibility/#containers-distros");
|
||||
let box_image = get_user_input("image you want to base the template box on?");
|
||||
let template_box_create_res = Command::new("distrobox")
|
||||
.arg("create")
|
||||
.arg("--root")
|
||||
.arg("--image")
|
||||
.arg(&box_image)
|
||||
.arg("--name")
|
||||
.arg(&template_box_name)
|
||||
.arg("--init")
|
||||
.arg("--volume")
|
||||
.arg(&tool_volume)
|
||||
.status();
|
||||
if template_box_create_res.is_err(){
|
||||
let error = template_box_create_res.err().unwrap();
|
||||
println!("error creating template box!");
|
||||
println!("{}", error);
|
||||
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{
|
||||
template_box_create_res.unwrap();
|
||||
}
|
||||
}
|
||||
let mut cracking_rig = String::from("nobody@nothing");
|
||||
let mut rockyou = String::from("n/a");
|
||||
let mut rule = String::from("n/a");
|
||||
let cracking_rig_response = get_user_input("do you have a separate machine to crack passwords on? (not the ambush cracking rig)");
|
||||
if cracking_rig_response.to_lowercase().contains("y"){
|
||||
let rig_ip = get_user_input("ip address or hostname of your cracking rig?");
|
||||
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);
|
||||
}
|
||||
else{
|
||||
println!("ok free loader");
|
||||
}
|
||||
let fingerprint = get_user_input("will you be using fingerprint authentication for your distroboxes?").to_lowercase();
|
||||
let mut terminal = String::new();
|
||||
for desktop in _terminal_commands.keys(){
|
||||
println!("{}", desktop);
|
||||
}
|
||||
let desktop_response = get_user_input("do you use any of these desktops?").to_lowercase();
|
||||
if desktop_response.contains("y"){
|
||||
let default_response = get_user_input("do you use the default terminal for your desktop?").to_lowercase();
|
||||
if default_response.contains("y"){
|
||||
let de = get_user_input("which desktop do you use?");
|
||||
terminal = _terminal_commands[&de.as_str()].to_owned();
|
||||
}
|
||||
}
|
||||
else{
|
||||
_terminal_command = _terminal_commands[terminal_response.trim_end()].to_owned();
|
||||
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");
|
||||
println!("for example for konsole you'd enter");
|
||||
println!("konsole -e !!!");
|
||||
terminal = get_user_input("");
|
||||
}
|
||||
let (files_response, notes_response, tools_response, project_folder_path, project_note_path, cracking_rig, cracking_user, rockyou, rule) = setup_folders(&config_path);
|
||||
print!("
|
||||
This tool is mainly to handle distrobox creation and usage.
|
||||
It's expecting you to have a distrobox that you will use as a template.
|
||||
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!("please set up a distrobox with root as a template and re-run this tool");
|
||||
println!("example distrobox setup command:");
|
||||
println!("distrobox create --root --image archlinux --name template");
|
||||
println!("then enter that distrobox and install all the tools you want and do what ever setup you need");
|
||||
println!("and re-run this tool.");
|
||||
process::Command::new("rm").arg(del_on_fail).spawn().expect("ERROR deleting config folder, please manually clean up");
|
||||
std::process::exit(1);
|
||||
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);
|
||||
}
|
||||
let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
|
||||
println!("distrobox template name?");
|
||||
std::io::stdin().read_line(&mut template_name).unwrap();
|
||||
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.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());
|
||||
config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
|
||||
let default_projectline = format!("default:default:{}:{}:yes:{}", ¬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");
|
||||
println!("active project folders: {}", &files_response);
|
||||
println!("upcomming project folders: {}", &project_folder_path);
|
||||
println!("active project notes: {}", ¬es_response);
|
||||
println!("upcomming prjoect notes: {}", &project_note_path);
|
||||
println!("tools folder: {}", &tools_response);
|
||||
println!("distrobox template: {}", &template_name);
|
||||
println!("terminal command: {}", &_terminal_command);
|
||||
println!("config file generated and saved to {}\n", config_path.display());
|
||||
|
||||
|
||||
let config_path = &config_folder_path.clone();
|
||||
let mut install_path = config_path.clone();
|
||||
let mut password_spray_template_path = install_path.clone();
|
||||
install_path.push("new_projects.conf");
|
||||
password_spray_template_path.push("passwordspray.md");
|
||||
let password_spray_template_path = install_path.clone();
|
||||
let mut passpray_file = fs::File::create(password_spray_template_path).expect("error creating passwordspray file");
|
||||
write!(passpray_file, "
|
||||
- [ ] useraspass
|
||||
- [ ] Seasonyear!
|
||||
- [ ] Service123!
|
||||
- [ ] admin
|
||||
- [ ] Admin
|
||||
- [ ] Admin123!
|
||||
- [ ] admin123
|
||||
- [ ] admin1
|
||||
- [ ] 1234567
|
||||
- [ ] Seasonyear
|
||||
- [ ] seasonyear!
|
||||
- [ ] seasonyear
|
||||
- [ ] COMPANYYEAR!
|
||||
- [ ] COMPANYYEAR
|
||||
- [ ] November2024!
|
||||
- [ ] September2024!
|
||||
- [ ] October2024!
|
||||
- [ ] COMPANYfoundingyear!
|
||||
- [ ] COMPANYfoundingyear
|
||||
- [ ] COMPANYstreetnumber!
|
||||
- [ ] COMPANYstreetnumber
|
||||
- [ ] Password
|
||||
- [ ] P@ssw0rd
|
||||
- [ ] Password1!
|
||||
- [ ] Password123!
|
||||
- [ ] Passwordyear!
|
||||
- [ ] P@55w0rd
|
||||
- [ ] Service
|
||||
- [ ] Service!
|
||||
- [ ] Serviceyear!").expect("error writing password spray template");
|
||||
std::process::exit(0);
|
||||
}
|
||||
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
|
||||
- [ ] Seasonyear!
|
||||
- [ ] Service123!
|
||||
- [ ] admin
|
||||
- [ ] Admin
|
||||
- [ ] Admin123!
|
||||
- [ ] admin123
|
||||
- [ ] admin1
|
||||
- [ ] 1234567
|
||||
- [ ] Seasonyear
|
||||
- [ ] seasonyear!
|
||||
- [ ] seasonyear
|
||||
- [ ] COMPANYYEAR!
|
||||
- [ ] COMPANYYEAR
|
||||
- [ ] November2024!
|
||||
- [ ] September2024!
|
||||
- [ ] October2024!
|
||||
- [ ] COMPANYfoundingyear!
|
||||
- [ ] COMPANYfoundingyear
|
||||
- [ ] COMPANYstreetnumber!
|
||||
- [ ] COMPANYstreetnumber
|
||||
- [ ] Password
|
||||
- [ ] P@ssw0rd
|
||||
- [ ] Password1!
|
||||
- [ ] Password123!
|
||||
- [ ] Passwordyear!
|
||||
- [ ] P@55w0rd
|
||||
- [ ] Service
|
||||
- [ ] Service!
|
||||
- [ ] Serviceyear!
|
||||
");
|
||||
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,6 +1,8 @@
|
||||
use std::path::PathBuf;
|
||||
use std::{io::stdin, path::PathBuf, process::Command};
|
||||
use directories::UserDirs;
|
||||
use std::fs;
|
||||
use reqwest::Response;
|
||||
use std::process::exit;
|
||||
use std::fs::{self, File};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Project{
|
||||
@@ -10,6 +12,7 @@ pub struct Project{
|
||||
pub files_folder: PathBuf,
|
||||
pub active: bool,
|
||||
pub boxname: String,
|
||||
pub stage: String,
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
@@ -20,6 +23,50 @@ mod box_controls;
|
||||
mod info_controls;
|
||||
mod start_pentest;
|
||||
|
||||
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{
|
||||
let mut response = String::new();
|
||||
loop{
|
||||
println!("{}", prompt);
|
||||
let result = stdin().read_line(&mut response);
|
||||
if result.is_err(){
|
||||
println!("we need input here dummy! try again...");
|
||||
}
|
||||
else{
|
||||
result.unwrap();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return response.trim_end().to_owned();
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
print!("
|
||||
@@ -42,8 +89,23 @@ fn main() {
|
||||
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
");
|
||||
let user_dirs = UserDirs::new().expect("error getting user directories");
|
||||
let mut config_path = user_dirs.home_dir().to_path_buf();
|
||||
let mut config_path = PathBuf::new();
|
||||
let user_dirs_res = UserDirs::new();
|
||||
if user_dirs_res.is_none(){
|
||||
println!("oof couldn't get the config directory the right way, falling back to the stpuid way...");
|
||||
let get_home_res = Command::new("echo").arg("$HOME").output();
|
||||
if get_home_res.is_err(){
|
||||
println!("ooof the stupid way didn't work... this is a bruh moment, gotta fix your environment variabls!!!");
|
||||
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");
|
||||
if config_path.as_path().exists() == false{
|
||||
install::install(&config_path);
|
||||
@@ -56,6 +118,11 @@ fn main() {
|
||||
let mut cracking_rig = String::new();
|
||||
let mut rockyou = String::new();
|
||||
let mut rule = String::new();
|
||||
let mut upcoming_files = PathBuf::new();
|
||||
let mut upcoming_notes = PathBuf::new();
|
||||
let mut pass_spray_file = PathBuf::new();
|
||||
let mut fingerprint = false;
|
||||
let mut vault_name = String::new();
|
||||
println!("\nconfig already generated\nloading config file...\n");
|
||||
let settings_string = fs::read_to_string(&config_path).expect("error reading config file");
|
||||
let settings: Vec<&str> = settings_string.split("\n").collect();
|
||||
@@ -66,11 +133,16 @@ fn main() {
|
||||
"Project_files" => project_base_folder.push(setting_vec[1].trim_end()),
|
||||
"Project_notes" => project_base_notes.push(setting_vec[1].trim_end()),
|
||||
"tools_folder" => tools_folder.push(setting_vec[1].trim_end()),
|
||||
"upcoming_files" => upcoming_files.push(setting_vec[1].trim_end()),
|
||||
"upcoming_notes" => upcoming_notes.push(setting_vec[1].trim_end()),
|
||||
"box_template" => box_template = setting_vec[1].trim_end().to_owned(),
|
||||
"terminal" => terminal_command = setting_vec[1].trim_end().to_owned(),
|
||||
"cracking_rig" => cracking_rig = setting_vec[1].trim_end().to_owned(),
|
||||
"rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(),
|
||||
"rule_location" => rule = setting_vec[1].trim_end().to_owned(),
|
||||
"pass_file"=> pass_spray_file.push(setting_vec[1]),
|
||||
"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])
|
||||
}
|
||||
}
|
||||
@@ -82,11 +154,13 @@ fn main() {
|
||||
distrobox template: {}
|
||||
terminal_command: {}
|
||||
cracking_rig: {}\n
|
||||
", project_base_folder.display(), project_base_notes.display(), tools_folder.display(), box_template, terminal_command, cracking_rig);
|
||||
upcoming project folders: {}
|
||||
upcoming project notes: {}
|
||||
", &project_base_folder.display(), &project_base_notes.display(), &tools_folder.display(), box_template, terminal_command, cracking_rig, &upcoming_files.display(), &upcoming_notes.display());
|
||||
println!("loading project configs...");
|
||||
let projects = project_controls::get_projects(&config_path);
|
||||
println!("Enter to start main menu");
|
||||
let mut enter = String::new();
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -31,11 +31,27 @@ fn get_active_project(projects: &Vec<Project>) -> &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){
|
||||
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 new_id = next_project_id(&config_path);
|
||||
let mut threads = Vec::new();
|
||||
loop {
|
||||
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 now = Local::now();
|
||||
let month = now.month();
|
||||
@@ -97,66 +113,83 @@ pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &
|
||||
|
||||
|
||||
|
||||
NOTE OPTION 18 WILL SAVE YOUR PROJECTS BEFORE QUITTING
|
||||
NOTE OPTION 28 WILL SAVE YOUR PROJECTS BEFORE QUITTING
|
||||
|
||||
base prject folder: {}
|
||||
upcoming project folder: {}
|
||||
Current Project: {} {}
|
||||
Working Folder: {}
|
||||
Notes Folder: {}
|
||||
Obsidian_uri: {}
|
||||
Box Name: {}
|
||||
Terminal Command: {}
|
||||
Current Season: {}
|
||||
Year: {}
|
||||
General Notes: {}
|
||||
|
||||
Main Menu:
|
||||
1 .) Show Active Project
|
||||
2 .) List Projects
|
||||
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
|
||||
6 .) Import New Project - and setup new Distrobox
|
||||
6 .) Import New Project to Current projects list - and setup new Distrobox
|
||||
7 .) Remove Project
|
||||
8 .) Open A New Terminal in Current Active Project
|
||||
9 .) Open A Terminal In this windows for the current active project
|
||||
10.) re-create the distrobox for the current active project
|
||||
11.) Open Project Files Folder In Dolphin
|
||||
12.) Open Project Notes Folder In Dolphin
|
||||
13.) generate userpass file from your obsidian notes
|
||||
14.) run pyro's initail enum script on a nessus csv for the current project
|
||||
15.) Print Project Info For Report
|
||||
16.) Build host discovery cmd command from scope in notes
|
||||
17.) build portscan command from scope in notes
|
||||
18.) Stop All Distroboxes
|
||||
19.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||
20.) crack password hashes on your cracking rig
|
||||
21.) Quit Application
|
||||
\n", active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year);
|
||||
8 .) Print upcoming projects
|
||||
9. ) promote project from upcoming to current
|
||||
10.) Open A New Terminal in Current Active Project
|
||||
11.) Open A Terminal In this windows for the current active project
|
||||
12.) open current project's cobalt strike
|
||||
13.) re-create the distrobox for the current active project
|
||||
14.) Open Project Files Folder In Dolphin
|
||||
15.) Open Project Notes Folder In Dolphin
|
||||
16.) generate userpass file from your obsidian notes
|
||||
17.) run pyro's initail enum script on a nessus csv for the current project
|
||||
18.) Print Project Info For Report
|
||||
19.) Build host discovery cmd command from scope in notes
|
||||
20.) build portscan command from scope in notes
|
||||
21.) parse a cs portscan services.tsv file
|
||||
22.) Stop All Distroboxes
|
||||
23.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||
24.) crack password hashes on your cracking rig
|
||||
25.) Launch bloodhound with the current project's distrobox
|
||||
26.) Parse GatherContacts output file
|
||||
27.) prune unused distroboxes (free up system storage)
|
||||
28.) 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, &obsidian_uri);
|
||||
std::io::stdin().read_line(&mut response).expect("error getting menu input");
|
||||
clear().expect("error clearing screen");
|
||||
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()),
|
||||
"2" => {println!("+++++++++++++++++++++");
|
||||
for project in &projects{
|
||||
println!("++{}|{}++",project.customer ,project.project_name)}
|
||||
println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)}
|
||||
println!("++++++++++++++++++++")},
|
||||
"3" => project_controls::switch_project(&mut projects),
|
||||
"4" => start_pentest::start_pentest(&config_path),
|
||||
"4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)},
|
||||
"5" => project_controls::save_projects(&projects, &config_path),
|
||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id)},
|
||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint)},
|
||||
"7" => project_controls::remove_project(&mut projects, &config_path),
|
||||
"8" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
|
||||
"9" => box_controls::project_inline_terminal(active_project.clone()),
|
||||
"10" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false),
|
||||
"11" => info_controls::open_in_dolphin("files", active_project.clone()),
|
||||
"12" => info_controls::open_in_dolphin("notes", active_project.clone()),
|
||||
"13" => info_controls::generate_userpass(&active_project),
|
||||
"14" => info_controls::run_initial_enum(&active_project),
|
||||
"15" =>info_controls::print_report_information(active_project.clone()),
|
||||
"16" => info_controls::build_cmd_for_host_discovery(&active_project),
|
||||
"17" => info_controls::build_cs_portscan_cmd(&active_project),
|
||||
"18" => box_controls::stop_all_boxes(&projects),
|
||||
"19" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
|
||||
"20" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
|
||||
"21" => {project_controls::save_projects(&projects, &config_path);
|
||||
"8" => project_controls::print_upcoming_projects(&projects),
|
||||
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint),
|
||||
"10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
|
||||
"11" => box_controls::project_inline_terminal(active_project.clone()),
|
||||
"12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}},
|
||||
"13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint),
|
||||
"14" => info_controls::open_in_dolphin("files", active_project.clone()),
|
||||
"15" => info_controls::open_in_dolphin("notes", active_project.clone()),
|
||||
"16" => info_controls::generate_userpass(&active_project),
|
||||
"17" => info_controls::run_initial_enum(&active_project),
|
||||
"18" => info_controls::print_report_information(active_project.clone()),
|
||||
"19" => info_controls::build_cmd_for_host_discovery(&active_project),
|
||||
"20" => info_controls::build_cs_portscan_cmd(&active_project),
|
||||
"21" => info_controls::parse_csportscan(&active_project),
|
||||
"22" => box_controls::stop_all_boxes(&projects),
|
||||
"23" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
|
||||
"24" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
|
||||
"25" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);},
|
||||
"26" => info_controls::partse_gathercontacts(&active_project),
|
||||
"27" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
|
||||
"28" => {project_controls::save_projects(&projects, &config_path);
|
||||
let mut stop = String::new();
|
||||
println!("stop all boxes?\ny/n");
|
||||
std::io::stdin().read_line(&mut stop).unwrap();
|
||||
@@ -173,4 +206,9 @@ Year: {}
|
||||
let mut enter = String::new();
|
||||
std::io::stdin().read_line(&mut enter).unwrap();
|
||||
}
|
||||
println!("this will hang until all threads are finished.");
|
||||
println!("make sure to close all programs opened with this menu, like cobalt strike or bloodhound.");
|
||||
for thread in threads{
|
||||
thread.join().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,11 @@ use std::io::stdin;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::process::Command;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::str::FromStr;
|
||||
use crate::get_user_input;
|
||||
use crate::Project;
|
||||
use crate::box_controls::make_box;
|
||||
|
||||
@@ -47,30 +49,62 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
|
||||
save_file_path.pop();
|
||||
save_file_path.push("projects.conf");
|
||||
let mut save_file = fs::File::create(save_file_path).expect("error creating save_file");
|
||||
save_file.write_all(b"customer:name:notes:files:active:time:box_name\n").expect("error writing first line to file");
|
||||
save_file.write_all(b"customer:name:notes:files:active:time:box_name:stage\n").expect("error writing first line to file");
|
||||
for project in projects{
|
||||
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
|
||||
let mut _outline = String::new();
|
||||
if project.active{
|
||||
if active_set == false{
|
||||
_outline = format!("{}yes:{}\n", default, project.boxname);
|
||||
_outline = format!("{}yes:{}:{}\n", default, project.boxname, project.stage);
|
||||
active_set = true;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
_outline = format!("{}no:{}\n", default, project.boxname);
|
||||
_outline = format!("{}no:{}:{}\n", default, project.boxname, project.stage);
|
||||
}
|
||||
save_file.write_all(_outline.as_bytes()).expect("error writing outline");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32){
|
||||
let mut new_project_dir = project_dir.clone();
|
||||
let mut new_note_dir = notes_dir.clone();
|
||||
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool){
|
||||
let mut new_project_dir = PathBuf::new();
|
||||
let mut new_note_dir = PathBuf::new();
|
||||
let mut existing_folders = String::new();
|
||||
let mut customer_name = String::new();
|
||||
let mut project_name = String::new();
|
||||
let mut project_stage = String::new();
|
||||
loop{
|
||||
let mut stage_response = String::new();
|
||||
println!("what stage is this project in?");
|
||||
print!("
|
||||
1.) current
|
||||
2.) upcoming
|
||||
");
|
||||
let stage_result = stdin().read_line(&mut stage_response);
|
||||
if stage_result.is_err(){
|
||||
println!("we need input here dummy, try again...");
|
||||
}
|
||||
else{
|
||||
match &stage_response.trim_end(){
|
||||
&"1" => {project_stage = "current".to_owned(); break;},
|
||||
&"2" => {project_stage = "upcoming".to_owned(); break;},
|
||||
_ => println!("unknown option, try again...")
|
||||
}
|
||||
}
|
||||
}
|
||||
if project_stage.contains("current"){
|
||||
new_project_dir = project_dir.clone();
|
||||
new_note_dir = notes_dir.clone();
|
||||
}
|
||||
else if project_stage.contains("upcoming"){
|
||||
new_project_dir = upcoming_files.clone();
|
||||
new_note_dir = upcoming_notes.clone();
|
||||
}
|
||||
else{
|
||||
println!("unknown stage!!")
|
||||
}
|
||||
println!("{}", new_project_dir.display());
|
||||
println!("do you have an existing notes and folder structure to copy over?\ny/n");
|
||||
std::io::stdin().read_line(&mut existing_folders).unwrap();
|
||||
if existing_folders.contains("y") || existing_folders.contains("Y"){
|
||||
@@ -191,8 +225,11 @@ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir
|
||||
active: false,
|
||||
id: new_id,
|
||||
boxname: box_name,
|
||||
stage: project_stage.to_owned()
|
||||
};
|
||||
make_box(&new_project, &tools_dir, &boxtemplate, true);
|
||||
if project_stage.contains("current"){
|
||||
make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint);
|
||||
}
|
||||
projects.push(new_project);
|
||||
save_projects(projects, config_path);
|
||||
|
||||
@@ -266,6 +303,12 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
||||
if first != 1{
|
||||
if line.len() > 1{
|
||||
let settings: Vec<&str> = line.split(":").collect();
|
||||
//debug config file...
|
||||
/*let mut count = 0;
|
||||
for settin in &settings{
|
||||
println!("{}: {}", count, settin);
|
||||
count = count + 1;
|
||||
}*/
|
||||
let customer = settings[0].to_owned();
|
||||
let project = settings[1].to_owned();
|
||||
let notes_string = settings[2].to_owned();
|
||||
@@ -281,7 +324,8 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname};
|
||||
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};
|
||||
println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
|
||||
projects.push(new_project);
|
||||
}
|
||||
@@ -289,3 +333,114 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
||||
}
|
||||
return projects
|
||||
}
|
||||
|
||||
pub fn print_upcoming_projects(projects: &Vec<Project>){
|
||||
for project in projects{
|
||||
if project.stage.contains("upcoming"){
|
||||
println!("{}:{}", project.customer, project.project_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool){
|
||||
let working_projects = projects.clone();
|
||||
for project in &working_projects{
|
||||
if project.stage.contains("upcoming"){
|
||||
println!("{}.) {}:{}", project.id, project.customer, project.project_name);
|
||||
}
|
||||
}
|
||||
println!("which project to promote?");
|
||||
let mut selection = String::new();
|
||||
let result = stdin().read_line(&mut selection);
|
||||
if result.is_err(){
|
||||
println!("we need input here dummy try again....");
|
||||
}
|
||||
result.unwrap();
|
||||
println!("{}", project_dir.display());
|
||||
let promote_id: i32 = selection.trim_end().parse().unwrap();
|
||||
let mut projects_to_save = Vec::new();
|
||||
for project in &working_projects{
|
||||
if project.id == promote_id{
|
||||
let mut promoted_project = project.clone();
|
||||
let mut new_files_dir = project_dir.clone();
|
||||
let mut new_notes_dir = notes_dir.clone();
|
||||
new_files_dir.push(&promoted_project.customer);
|
||||
new_notes_dir.push(&promoted_project.customer);
|
||||
fs::create_dir_all(&new_files_dir).unwrap();
|
||||
fs::create_dir_all(&new_notes_dir).unwrap();
|
||||
let folder_move_success = process::Command::new("mv")
|
||||
.arg("-i")
|
||||
.arg(&project.files_folder)
|
||||
.arg(&new_files_dir.display().to_string())
|
||||
.status().expect("unable to call the system mv command");
|
||||
let note_move_success = process::Command::new("mv")
|
||||
.arg("-i")
|
||||
.arg(&project.notes_folder)
|
||||
.arg(&new_notes_dir.display().to_string())
|
||||
.status().expect("unable to call the system mv command");
|
||||
if folder_move_success.success(){
|
||||
println!("we copied the project folder correctly!!");
|
||||
let mut remove_folder = PathBuf::new();
|
||||
remove_folder.push(&project.files_folder);
|
||||
remove_folder.pop();
|
||||
let remove_files_res = fs::remove_dir_all(remove_folder);
|
||||
if remove_files_res.is_err(){
|
||||
println!("error removing the original files folder form the upcomming folder, manual cleanup required");
|
||||
}
|
||||
else{
|
||||
remove_files_res.unwrap();
|
||||
println!("upcoming files folder cleanup successful!");
|
||||
}
|
||||
}
|
||||
else{
|
||||
println!("failed to copy the project folder, try to move it manually!");
|
||||
}
|
||||
if note_move_success.success(){
|
||||
println!("we copied the notes folder correctly!!");
|
||||
let mut remove_folder = PathBuf::new();
|
||||
remove_folder.push(&project.files_folder);
|
||||
remove_folder.pop();
|
||||
let remove_notes_res = fs::remove_dir_all(remove_folder);
|
||||
if remove_notes_res.is_err(){
|
||||
println!("error removing the original notes folder form the upcomming folder, manual cleanup required");
|
||||
}
|
||||
else{
|
||||
remove_notes_res.unwrap();
|
||||
println!("upcoming notes folder cleanup successful!");
|
||||
}
|
||||
}
|
||||
else{
|
||||
println!("failed to copy the notes folder, try to move it manually!");
|
||||
}
|
||||
new_files_dir.push(&promoted_project.project_name);
|
||||
new_notes_dir.push(&promoted_project.project_name);
|
||||
promoted_project.files_folder = new_files_dir;
|
||||
promoted_project.notes_folder = new_notes_dir;
|
||||
promoted_project.stage = "current".to_owned();
|
||||
let cs_response = get_user_input("will you need to be using cobalt strike for this project?");
|
||||
if cs_response.to_lowercase().contains("y"){
|
||||
let cs_path = get_user_input("path to your current cobalt strike directory?");
|
||||
let copy_result = Command::new("cp").arg("-R").arg(&cs_path).arg(&promoted_project.files_folder).status();
|
||||
if copy_result.is_err(){
|
||||
println!("oof we had an error copying... you'll have to copy this manually");
|
||||
}
|
||||
else{
|
||||
let copy_exit = copy_result.unwrap();
|
||||
if copy_exit.success() == false{
|
||||
println!("oof we had an error copying... you'll have to copy this manually");
|
||||
println!("run cp -R {} {}", &cs_path, &promoted_project.files_folder.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
thread::sleep(Duration::from_secs(3));
|
||||
make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint);
|
||||
projects_to_save.push(promoted_project);
|
||||
}
|
||||
else{
|
||||
projects_to_save.push(project.clone());
|
||||
}
|
||||
}
|
||||
projects.clear();
|
||||
projects.append(&mut projects_to_save);
|
||||
save_projects(&projects_to_save, config_path);
|
||||
}
|
||||
@@ -1,25 +1,59 @@
|
||||
use std::fs;
|
||||
use std::io::stdin;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use crate::Project;
|
||||
use crate::project_controls;
|
||||
use crate::get_user_input;
|
||||
|
||||
fn external(project_folder_path: String,comapny_name: &String, project_name: &String, passtemp: PathBuf){
|
||||
let mut general_notes = fs::File::create(format!("{}/general.md", &project_folder_path)).expect("error creating general notes file");
|
||||
let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file");
|
||||
let mut host_notes = fs::File::create(format!("{}/host_notes.md", &project_folder_path)).expect("error creating host notes file");
|
||||
let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file");
|
||||
|
||||
fn create_project_folder(path: &mut PathBuf, folder: &str){
|
||||
path.push(folder);
|
||||
let result = fs::create_dir_all(&path);
|
||||
if result.is_err(){
|
||||
println!("error creating {} directory!", folder);
|
||||
}
|
||||
else{
|
||||
result.unwrap();
|
||||
}
|
||||
path.pop();
|
||||
}
|
||||
|
||||
fn create_note_file(path: &PathBuf) -> Option<File>{
|
||||
let result = fs::File::create(path);
|
||||
if result.is_err(){
|
||||
println!("error creating {} try manually!", path.display());
|
||||
return None;
|
||||
}
|
||||
else{
|
||||
let file = result.unwrap();
|
||||
return Some(file);
|
||||
}
|
||||
}
|
||||
|
||||
fn external(passtemp: &PathBuf, project: &Project){
|
||||
// using a pathbuf to create files.
|
||||
let mut notes_path = project.notes_folder.clone();
|
||||
let file_creation_res = fs::create_dir_all(¬es_path);
|
||||
if file_creation_res.is_err(){
|
||||
let error = file_creation_res.err().unwrap();
|
||||
println!("error creating notes folder! {}", error);
|
||||
}
|
||||
else{
|
||||
file_creation_res.unwrap();
|
||||
}
|
||||
notes_path.push("general.md");
|
||||
let general_notes_result = create_note_file(¬es_path);
|
||||
if general_notes_result.is_some(){
|
||||
let mut general_notes = general_notes_result.unwrap();
|
||||
// for tagging
|
||||
let year = project_name.split("_").collect::<Vec<&str>>()[1];
|
||||
let project_type = "External";
|
||||
writeln!(&mut general_notes, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing to general notes file");
|
||||
writeln!(&mut attack_notes, "#{} #{} #{} #attack", comapny_name, project_type, year).expect("error writing tags on attack notes");
|
||||
writeln!(&mut host_notes, "##{} #{} #{} #host_notes", comapny_name, project_type, year).expect("error writing tag lin in host notes");
|
||||
writeln!(&mut finding_notes, "#{} #{} #{} #findings", comapny_name, project_type, year).expect("error writing tag line on findings");
|
||||
writeln!(&mut general_notes, "#{} #{} #general", project.customer, project_type).expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "# Scope").expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "\n| IP | Third Party | Approval |").expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "| -- | ----------- | -------- |").expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "# PPC").expect("failed to write general notes");
|
||||
write!(&mut general_notes, "
|
||||
writeln!(&mut general_notes, "# PPC").expect("failed to write general notes");
|
||||
write!(&mut general_notes, "
|
||||
Planning call notes:
|
||||
* methodolgy
|
||||
* whole month testing window
|
||||
@@ -54,8 +88,14 @@ Planning call notes:
|
||||
| IP | host notes | needs? |
|
||||
| -- | ---------- | ------ |\n").expect("faile to write pentest notes");
|
||||
|
||||
// set up the basics for our attack notes
|
||||
write!(&mut attack_notes,"
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("attacks.md");
|
||||
let attack_notes_result = create_note_file(¬es_path);
|
||||
if attack_notes_result.is_some(){
|
||||
let mut attack_notes = attack_notes_result.unwrap();
|
||||
writeln!(&mut attack_notes, "#{} #{} #attack", project.customer, "external").expect("error writing tags on attack notes");
|
||||
write!(&mut attack_notes,"
|
||||
# Directory Bruteforcing
|
||||
- [ ] example.com
|
||||
|
||||
@@ -74,39 +114,61 @@ write!(&mut attack_notes,"
|
||||
passwords tried:
|
||||
* password\n
|
||||
" ).expect("failed to write attack notes template");
|
||||
let new_spray_path = format!("{}/passwordspray.md", &project_folder_path);
|
||||
fs::copy(passtemp,new_spray_path).unwrap();
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("password_spray.md");
|
||||
let pass_result = fs::copy(&passtemp, ¬es_path);
|
||||
if pass_result.is_err(){
|
||||
println!("error copying password spray file! try manually");
|
||||
}
|
||||
else{
|
||||
pass_result.unwrap();
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("host_notes.md");
|
||||
let host_notes_result = create_note_file(¬es_path);
|
||||
if host_notes_result.is_some(){
|
||||
let mut host_notes = host_notes_result.unwrap();
|
||||
writeln!(&mut host_notes, "##{} #{} #host_notes", project.customer, "external").expect("error writing tag lin in host notes");
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("findings.md");
|
||||
let findings_notes_result = create_note_file(¬es_path);
|
||||
if findings_notes_result.is_some(){
|
||||
let mut finding_notes = findings_notes_result.unwrap();
|
||||
writeln!(&mut finding_notes, "#{} #{} #findings", project.customer, "external").expect("error writing tag line on findings");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn internal(project_folder_path: String, comapny_name: &String, project_name: &String, passtemp: PathBuf){
|
||||
let loot_folder = format!("{}/l00t", project_folder_path);
|
||||
fs::create_dir_all(&loot_folder).expect("error creating loot directory");
|
||||
let mut general_notes = fs::File::create(format!("{}/general.md", &project_folder_path)).expect("error creating general notes file");
|
||||
let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file");
|
||||
let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file");
|
||||
let mut systeminfo = fs::File::create(format!("{}/systeminfo", &project_folder_path)).expect("error creating systeminfo note file");
|
||||
let mut netsta = fs::File::create(format!("{}/netstat", &project_folder_path)).expect("error creating netstat file");
|
||||
let mut creds_notes = fs::File::create(format!("{}/creds.md", &loot_folder)).expect("error creating creds note");
|
||||
let mut todo_notes = fs::File::create(format!("{}/todo.md", &project_folder_path)).expect("error creating todo notes");
|
||||
let mut cleanup_notes = fs::File::create(format!("{}/cleanup.md", &project_folder_path)).expect("error creating cleanup notes");
|
||||
let mut dump_notes = fs::File::create(format!("{}/dumps.md", &loot_folder)).expect("error creating password spray notes");
|
||||
let mut enum_notes = fs::File::create(format!("{}/initial_enum.md", &project_folder_path)).expect("error creating password spray notes");
|
||||
let enum_obsidian_path = format!("Hack_Notes/pentest_notes/upcomming/{customer}//initial_enum.md", customer = comapny_name);
|
||||
// for tagging notes
|
||||
let oyear = project_name.split("_").collect::<Vec<&str>>()[0];
|
||||
let year = format!("year-{}", oyear);
|
||||
let project_type = "Internal";
|
||||
writeln!(&mut creds_notes, "#{} #{} #{} #l00t #creds", comapny_name, project_type, year).expect("error writing creds notes");
|
||||
writeln!(&mut dump_notes, "#{} #{} #{} #l00t #dumps", comapny_name, project_type, year).expect("error writing creds notes");
|
||||
writeln!(&mut cleanup_notes, "#{} #{} #{} #cleanup", comapny_name, project_type, year).expect("error writing to cleanup notes");
|
||||
writeln!(&mut general_notes, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing to general notes file");
|
||||
writeln!(&mut attack_notes, "#{} #{} #{} #attack", comapny_name, project_type, year).expect("error writing attack note tags");
|
||||
writeln!(&mut todo_notes, "#{} #{} #{} #todo", comapny_name, project_type, year).expect("error writing tag line on todo");
|
||||
writeln!(&mut finding_notes, "#{} #{} #{} #findings", comapny_name, project_type, year).expect("error writing tags line on findings");
|
||||
writeln!(&mut systeminfo, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tag line for system info");
|
||||
writeln!(&mut systeminfo, "#{} #{} #{} #Password_sprays", comapny_name, project_type, year).expect("error writing tag line for password spraying");
|
||||
writeln!(&mut netsta, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tagline in the netstat file");
|
||||
writeln!(&mut enum_notes, "#{} #{} #{} #enum", comapny_name, project_type, year).expect("error writing tagline in the netstat file");
|
||||
fn internal(passtemp: &PathBuf, project: &Project){
|
||||
let mut notes_path = project.notes_folder.clone();
|
||||
let file_creation_res = fs::create_dir_all(¬es_path);
|
||||
if file_creation_res.is_err(){
|
||||
let error = file_creation_res.err().unwrap();
|
||||
println!("error creating notes folder! {}", error);
|
||||
}
|
||||
else{
|
||||
file_creation_res.unwrap();
|
||||
}
|
||||
notes_path.push("password_spray.md");
|
||||
println!("copying from {} to {}", passtemp.display(), ¬es_path.display());
|
||||
let pass_result = fs::copy(&passtemp, ¬es_path);
|
||||
if pass_result.is_err(){
|
||||
let error = pass_result.err().unwrap();
|
||||
println!("error copying password spray file, try again manually! {}", error);
|
||||
}
|
||||
else{
|
||||
pass_result.unwrap();
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("l00t");
|
||||
fs::create_dir_all(¬es_path).expect("error creating loot directory");
|
||||
notes_path.push("creds.md");
|
||||
let creds_notes_result = create_note_file(¬es_path);
|
||||
if creds_notes_result.is_some(){
|
||||
let mut creds_notes = creds_notes_result.unwrap();
|
||||
writeln!(&mut creds_notes, "#{} #{} #l00t #creds", project.customer, "internal").expect("error writing creds notes");
|
||||
writeln!(&mut creds_notes, "# CREDS").expect("error writing creds notes");
|
||||
writeln!(&mut creds_notes, "\n| System | username | password |").expect("error writing creds notes");
|
||||
writeln!(&mut creds_notes, "| ------ | -------- | -------- |").expect("error writing creds notes");
|
||||
@@ -114,18 +176,16 @@ fn internal(project_folder_path: String, comapny_name: &String, project_name: &S
|
||||
writeln!(&mut creds_notes, "# HASHES\n\n").expect("error writing creds notes");
|
||||
writeln!(&mut creds_notes, "| TYPE | USER | HASH |").expect("error writing creds notes");
|
||||
writeln!(&mut creds_notes, "| ---- | ---- | ---- |").expect("error writing creds notes");
|
||||
writeln!(&mut cleanup_notes, "- [ ] Breach machine C-temp-fr").expect("error writing to cleanup notes");
|
||||
writeln!(&mut cleanup_notes, "- [ ] (continue to add as needed").expect("error writing ot cleanup notes");
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.pop();
|
||||
notes_path.push("general.md");
|
||||
let general_result = create_note_file(¬es_path);
|
||||
if general_result.is_some(){
|
||||
let mut general_notes = general_result.unwrap();
|
||||
writeln!(&mut general_notes, "#{} #{} #general", project.customer, "internal").expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "# Scope\n").expect("error writing to general notes file");
|
||||
writeln!(&mut general_notes, "PASTE SCOPE FROM EXCELL HERE (THE EXCEL TO MARKDOWN TABLE PLUGIN WILL FORMAT FOR YOU").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "# SAM\n\n").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "## system name\n").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "```").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "```\n\n").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "# LSASS\n\n").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "## system name\n").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "```").expect("shouldn't ever fail");
|
||||
writeln!(&mut dump_notes, "```").expect("shouldn't ever fail");
|
||||
write!(&mut general_notes, "
|
||||
On the call:
|
||||
|
||||
@@ -151,6 +211,14 @@ Do they have a specific contact
|
||||
|
||||
Email any follow-up items from the call to the PM
|
||||
").expect("error writing PPC text");
|
||||
}
|
||||
notes_path.pop();
|
||||
let enum_path = format!("{}/initial_enum.md", notes_path.display());
|
||||
notes_path.push("attacks.md");
|
||||
let attack_result = create_note_file(¬es_path);
|
||||
if attack_result.is_some(){
|
||||
let mut attack_notes = attack_result.unwrap();
|
||||
writeln!(&mut attack_notes, "#{} #{} #attack", project.customer, "internal").expect("error writing attack note tags");
|
||||
write!(&mut attack_notes,"
|
||||
# current dat (ex: 7/5)
|
||||
Got Persistence via (schtasks, bat schtasks, startup folder)
|
||||
@@ -206,14 +274,28 @@ powerup.ps1/sharpup.exe notes.
|
||||
|
||||
|
||||
|
||||
", enum = enum_obsidian_path).expect("error writing to attack notes for internal tests");
|
||||
", enum = enum_path).expect("error writing to attack notes for internal tests");
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("findings.md");
|
||||
let findings_result = create_note_file(¬es_path);
|
||||
if findings_result.is_some(){
|
||||
let mut finding_notes = findings_result.unwrap();
|
||||
writeln!(&mut finding_notes, "#{} #{} #findings", project.customer, "internal").expect("error writing tags line on findings");
|
||||
write!(&mut finding_notes, "
|
||||
# normal findings
|
||||
# normal findings
|
||||
|
||||
# data exfil
|
||||
## [Sarting Username]
|
||||
# data exfil
|
||||
## [Sarting Username]
|
||||
|
||||
").expect("error writing to findings notes on internal");
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("todo.md");
|
||||
let todo_result = create_note_file(¬es_path);
|
||||
if todo_result.is_some(){
|
||||
let mut todo_notes = todo_result.unwrap();
|
||||
writeln!(&mut todo_notes, "#{} #{} #todo", project.customer, "internal").expect("error writing tag line on todo");
|
||||
write!(&mut todo_notes, "
|
||||
|
||||
- [ ] local checks
|
||||
@@ -227,94 +309,47 @@ powerup.ps1/sharpup.exe notes.
|
||||
- [ ] passwords in AD Descriptions?
|
||||
- [ ] password spray
|
||||
").expect("error writing todo list");
|
||||
write!(&mut netsta,"
|
||||
```
|
||||
|
||||
```").expect("error writing code block to system info");
|
||||
write!(&mut systeminfo,"
|
||||
```
|
||||
|
||||
```").expect("error writing code block to system info");
|
||||
let new_pass_path = format!("{}/passwordspray.md", &project_folder_path);
|
||||
println!("{} | {}", passtemp.display(), new_pass_path);
|
||||
fs::copy(passtemp, new_pass_path).unwrap();
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("cleanup.md");
|
||||
let cleanup_result = create_note_file(¬es_path);
|
||||
if cleanup_result.is_some(){
|
||||
let mut cleanup_notes = cleanup_result.unwrap();
|
||||
writeln!(&mut cleanup_notes, "#{} #{} #cleanup", project.customer, "internal").expect("error writing to cleanup notes");
|
||||
writeln!(&mut cleanup_notes, "- [ ] Breach machine C-temp-fr").expect("error writing to cleanup notes");
|
||||
writeln!(&mut cleanup_notes, "- [ ] (continue to add as needed").expect("error writing ot cleanup notes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn start_pentest(config_path: &PathBuf) {
|
||||
let mut pentest_notes = String::new();
|
||||
let mut project_files = String::new();
|
||||
let mut company_name = String::new();
|
||||
let mut project_name = String::new();
|
||||
let mut config_file_path_buf = config_path.clone();
|
||||
config_file_path_buf.pop();
|
||||
let mut passpray_path = config_file_path_buf.clone();
|
||||
passpray_path.push("passwordspray.md");
|
||||
config_file_path_buf.push("new_projects.conf");
|
||||
let config_string = fs::read_to_string(config_file_path_buf).expect("error reading ");
|
||||
if config_string.contains("folder_path") && config_string.contains("notes_path"){
|
||||
let config_string_vec: Vec<&str> = config_string.split("\n").collect();
|
||||
for line in config_string_vec{
|
||||
if line.contains("project_folder_path"){
|
||||
let line_vec: Vec<&str> = line.split(":").collect();
|
||||
project_files = line_vec[1].to_owned();
|
||||
pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, boxtemplate: &String, password_spray_file: &PathBuf) {
|
||||
let mut project_files = upcoming_files.clone();
|
||||
let mut project_notes = upcoming_notes.clone();
|
||||
let customer_name = get_user_input("Customer name?");
|
||||
let project_name = get_user_input("Project Name?");
|
||||
project_files.push(&customer_name);
|
||||
project_files.push(&project_name);
|
||||
project_notes.push(&customer_name);
|
||||
project_notes.push(&project_name);
|
||||
println!("Files: {}\nNotes: {}\n\n", project_files.display(), project_notes.display());
|
||||
let confirm_response = get_user_input("does this look ok?");
|
||||
if confirm_response.to_lowercase().contains("n"){
|
||||
println!("oof sorry");
|
||||
return;
|
||||
}
|
||||
else if line.contains("project_notes_path"){
|
||||
let line_vec: Vec<&str> = line.split(":").collect();
|
||||
pentest_notes = line_vec[1].to_owned();
|
||||
let mut working = project_files.clone();
|
||||
create_project_folder(&mut working, "working");
|
||||
create_project_folder(&mut working, "writing");
|
||||
create_project_folder(&mut working, "delivery");
|
||||
let project_boxname = format!("{}_{}", boxtemplate, customer_name);
|
||||
let new_prject = Project{customer:customer_name.clone(), project_name:project_name.clone(), notes_folder:project_notes.clone(), files_folder:project_files.clone(),active:false, boxname:project_boxname.clone(),stage:"upcoming".to_owned(), id};
|
||||
if project_name.contains("external"){
|
||||
external(password_spray_file, &new_prject);
|
||||
}
|
||||
else if project_name.contains("internal"){
|
||||
internal(password_spray_file, &new_prject);
|
||||
}
|
||||
}
|
||||
println!("Project files path: {}\nProject Notes path: {}", project_files, pentest_notes);
|
||||
println!("Comapny Name?");
|
||||
match std::io::stdin().read_line(&mut company_name){
|
||||
Ok(_result) => (),
|
||||
Err(_e) => {println!("we need input here dummy!"); return;}
|
||||
}
|
||||
println!("project Name?");
|
||||
match stdin().read_line(&mut project_name){
|
||||
Ok(_result) => (),
|
||||
Err(_e) => {println!("we need input here dummy!"); return;}
|
||||
}
|
||||
//remove new lines from input
|
||||
company_name = company_name.trim_end().to_owned();
|
||||
project_name = project_name.trim_end().to_owned();
|
||||
let project_folder_path = format!("{}/{}/{}", pentest_notes, company_name,project_name);
|
||||
println!("setting folder creation paths...");
|
||||
let project_files_folder_path = format!("{}/{}/{}", project_files, company_name, project_name);
|
||||
let working_folder = format!("{}/working", &project_files_folder_path);
|
||||
let writing_folder = format!("{}/writing", &project_files_folder_path);
|
||||
let screeenshot_folder = format!("{}/screenshots",&writing_folder);
|
||||
let delivery_folder = format!("{}/delivery", &project_files_folder_path);
|
||||
// make the folders for this project's notes and files
|
||||
println!("creating directory structure for notes and file folders...");
|
||||
fs::create_dir_all(&project_folder_path).expect("Error creating project folder");
|
||||
fs::create_dir_all(&project_files_folder_path).expect("Error creating project file folder");
|
||||
fs::create_dir_all(&working_folder).expect("error creating working directory");
|
||||
fs::create_dir_all(&writing_folder).expect("Error creating writing direcotry");
|
||||
fs::create_dir(&screeenshot_folder).expect("error creating screenshots folder");
|
||||
fs::create_dir_all(&delivery_folder).expect("Error creating delivery direcotry");
|
||||
if project_name.contains("internal"){
|
||||
println!("internal pentest type detected, auto populating notes with internal layout...");
|
||||
internal(project_folder_path,&company_name, &project_name, passpray_path);
|
||||
}
|
||||
else if project_name.contains("external") {
|
||||
println!("external pentest type detected, auto populating notes with external layout...");
|
||||
external(project_folder_path, &company_name, &project_name, passpray_path);
|
||||
}
|
||||
else if project_name.contains("webapp") {
|
||||
println!("not implemented yet sorry");
|
||||
println!("default file folder structure used, and empty notes folder created...")
|
||||
}
|
||||
else{
|
||||
println!("unknown project type detected, default folder strucutre and empty note folder created...");
|
||||
print!("
|
||||
Known project types:
|
||||
Internal Penetration Test
|
||||
External Penetartion Test
|
||||
|
||||
If this test is actually one of these types please include the type in the project name parameter, example: 2023_internal_pentest.
|
||||
If this test is a common test and you would like a default note structure implemented in this script let Kevin \"Kage\" Gunter know and supply an example markdown note sheet.");
|
||||
}
|
||||
|
||||
projects.push(new_prject);
|
||||
project_controls::save_projects(projects, config_path);
|
||||
println!("project created and saved to the projects config file!");
|
||||
}
|
||||
Reference in New Issue
Block a user