28 Commits
2.1.1 ... 2.1.9

Author SHA1 Message Date
pyro57000
b137e0c34d switched the cobalt strike command to be
.output instead of .status to prevent
it from locking you out of returning to the
main menu.
2025-03-12 12:52:02 -05:00
pyro57000
8a1dca30e1 added logic to copy the cobaltstrike
folder into your project directory
and an option to launch that cobaltstrike
instance within the distrobox of your project
this should help keep cobalt strike data separate
also took a stab at cleaning up the left over
folders in the upcomming files and notes directories
the files folder cleans up now, but the notes folder
still needs work.
2025-03-12 12:48:21 -05:00
pyro57000
854feb2e2a added install logic to configure distrobox
to not pull the container image always.
this should save space, and fix cloning on
universal blue distros.
2025-03-12 10:50:37 -05:00
pyro57000
bfa766a2c3 fixed the new folders not being created first 2025-03-12 09:56:54 -05:00
pyro57000
f7bdd0ad8a fixed promotion function to use the project name
folder as well!
2025-03-12 09:49:15 -05:00
pyro57000
16706f8f6d fixed some stuff with box creation. 2025-03-12 09:39:19 -05:00
pyro57000
b6ec849b36 added some ideas for future development 2025-03-06 12:22:54 -06:00
pyro57000
69f5a4bd78 added stopping the template box to ensure
that cloning operations works
2025-03-06 11:53:11 -06:00
pyro57000
cad1f9d51c removed one redundant line 2025-03-06 09:24:33 -06:00
pyro57000
837012d163 fixed note folder creation with new pentest option 2025-03-06 09:22:15 -06:00
pyro57000
4dba68cdcf refactor for upcomming project management 2025-03-05 14:56:17 -06:00
pyro57000
7765640e0e refactor for managing upcoming and current
projects!
2025-03-05 14:55:56 -06:00
pyro57000
d50625167b added --init to distrobox creation
this will allow us to do things like docker
inside of distroboxes
2025-02-20 13:20:02 -06:00
pyro57000
a798e39461 did the distrobox stuff 2025-02-20 13:09:12 -06:00
pyro57000
4e1ab4c30f split making a distrobox into its own function
this will allow us to write more functions
like the newly added one to re-create the
current project's distrobox
2025-02-20 13:08:20 -06:00
pyro57000
ac037a15a9 fixed the start_pentest function 2025-02-13 14:14:00 -06:00
Pyro57000
345124baf1 Update README.md 2025-01-21 10:57:15 -06:00
Pyro57000
a9a451a8cf Update ToDo.md 2025-01-21 10:52:12 -06:00
Pyro57000
7081280247 Update ToDo.md 2025-01-21 10:51:57 -06:00
Pyro57000
2d97e81920 Create ToDo.md 2025-01-21 10:51:28 -06:00
pyro57000
761f71c6c1 modified the install to avoid the newlines
in folder names

added hash cracking function, though this doesn't
work yet...
2025-01-21 10:31:03 -06:00
pyro57000
882afe0f67 added logic to save already sprayed passwords
based on passwordspray markdown file.
2025-01-16 13:43:08 -06:00
pyro57000
1f47ff8229 just cleaned up a mutable 2025-01-15 15:58:11 -06:00
pyro57000
f40c0e31c1 added logic to save and come back to a password
spray.
2025-01-15 13:56:09 -06:00
pyro57000
bf95a375fb added logic to do msolspray as well!
this isn't tested very well, but give it a shot!
2025-01-15 13:28:12 -06:00
pyro57000
00e19bc1b4 added logic to display correct command for
user as pass sprays.
2025-01-15 12:07:41 -06:00
pyro57000
fd64caefc1 forgot to add execute-assembly to one line 2025-01-09 14:13:44 -06:00
pyro57000
e8b557bb4e edited install function to actually work right
the bell file was trying to be written
too soon, this has been fixed.
2025-01-09 14:08:46 -06:00
9 changed files with 1059 additions and 293 deletions

View File

@@ -75,7 +75,8 @@ Once the project is done and I'm ready to clean up the distrobox I use option 7
1. clone this repository `git clone https://github.com/Pyro57000/pentest_tool.git` 1. clone this repository `git clone https://github.com/Pyro57000/pentest_tool.git`
2. cd into the nested "pentest_tool" folder `cd pentest_tool/pentest_tool` 2. cd into the nested "pentest_tool" folder `cd pentest_tool/pentest_tool`
3. use cargo to build the release binary `cargo build --release` 3. use cargo to build the release binary `cargo build --release`
4. follow the same installation instructions, skipping the step where you download the release binary. 4. copy the compiled binary to a folder on your path `sudo cp ./target/release/pentest_tool /usr/bin/`
5. follow the same installation instructions, skipping the step where you download the release binary.

29
ToDo.md Normal file
View File

@@ -0,0 +1,29 @@
# planned features
1.) finish hash cracking with a dedictated cracking rig code.
2.) cracte hash cracking with current computer code.
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
2.) maybe expand this server client model to interact with cracking rigs and what not.
3.) implment a function to searchsploit and copy wanted exploits to the project folder.
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!!
I'll keep plugging away as I have time throughout my days as well.

View File

@@ -1,4 +1,14 @@
use std::process; use core::error;
use std::os::unix::thread::JoinHandleExt;
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::{self, JoinHandle, Thread};
use std::time::Duration;
use std::str::FromStr;
use crate::Project; use crate::Project;
pub fn stop_all_boxes(projects: &Vec<Project>){ pub fn stop_all_boxes(projects: &Vec<Project>){
@@ -63,3 +73,136 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String){
pub fn project_inline_terminal(project: Project){ pub fn project_inline_terminal(project: Project){
process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole"); process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
} }
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool){
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")
.arg("--root")
.arg("-f")
.arg(&project.boxname)
.status().expect("error calling distrobox");
if distrobox_rm_status.success(){
println!("Distrobox Removal Successful!!!");
}
else{
println!("Distrobox Removal Failed, manual removal required!");
}
}
let mut box_name_path = project.files_folder.clone();
let mut box_name = format!("atarchbox_{}", &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 --init --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume, pentest_volume, box_name);
let distrobox_result = process::Command::new("distrobox")
.arg("create")
.arg("--root")
.arg("--init")
.arg("--unshare-all")
.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(){
println!("we made a distrobox oh boy!");
let distrobox_start_result = process::Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&box_name)
.arg("--")
.arg("sudo")
.arg("-s")
.arg("ln")
.arg("-sf")
.arg("/pentest/boxname")
.arg("/etc/boxname")
.status()
.expect("error getting response from distrobox start");
if distrobox_start_result.success(){
println!("distrobox was started as well!!!! good job me!");
}
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);
}
}
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 --root {} -- 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 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);
}
}
});
return Some(handle);
}

View File

@@ -1,7 +1,6 @@
use std::fs; use std::fs;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
@@ -201,14 +200,10 @@ fn find_file(dir: &PathBuf, file_name: &str) -> Option<String>{
return None; return None;
} }
pub fn password_spray_help(project: &Project, season: String, lseason: String, year: i32, tools_dir: &PathBuf, config_path: &PathBuf){ fn nefarious_config(tools_dir: &PathBuf) -> String{
let mut wait_time:u64 = 0;
let mut wait_time_response = String::new();
let mut exemethod = String::new();
let mut bell_path = config_path.clone();
bell_path.pop();
bell_path.push("bell.mp3");
let nefarious_spray_path = find_file(tools_dir, "obf-NefariousSpray.exe"); let nefarious_spray_path = find_file(tools_dir, "obf-NefariousSpray.exe");
let mut outline = String::new();
let mut exemethod = String::new();
loop { loop {
println!("how do you need to run it?"); println!("how do you need to run it?");
print!(" print!("
@@ -221,6 +216,123 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
if exemethod_result.is_err(){ if exemethod_result.is_err(){
println!("we need input here dummy!"); println!("we need input here dummy!");
} }
else{
match exemethod.as_str(){
"1\n" => outline = format!("execute-assembly {} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", nefarious_spray_path.map_or("".to_string(), |s| s)),
"2\n" => outline = format!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt --etw --amsi --pipe totallyawesomepipeyo", nefarious_spray_path.map_or("".to_string(), |s| s)),
"3\n" => outline = {let mut path = String::new(); println!("path to nefarious spray.exe"); stdin().read_line(&mut path).unwrap(); format!("run {} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", path.trim_ascii_end())},
"4\n" => outline = {let mut path = String::new(); println!("path to nefarious spray.exe"); stdin().read_line(&mut path).unwrap(); format!("{} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", path.trim_ascii_end())},
_ => println!("unknown exec method... try again")
}
return outline;
}
}
}
fn msolspray_config(tools_dir: &PathBuf) -> String{
let mut msolspray_path = String::new();
let mut outline = String::new();
let mut userlist = String::new();
let mut spray_target = String::new();
loop{
println!("path to your users list?");
let result = stdin().read_line(&mut userlist);
if result.is_err(){
println!("we need input here dummy!");
}
else{
break;
}
}
loop{
println!("target URL (probably a fireprox url)");
let result = stdin().read_line(&mut spray_target);
if result.is_err(){
println!("we need input here dummy!");
}
else{
break;
}
}
loop {
let mut response = String::new();
println!("is MSOLSpray.py in your path? (for example installed via pipx or pip)");
let path_result = stdin().read_line(&mut response);
if path_result.is_err(){
println!("we need input here dummy!!");
}
else{
response = response.to_lowercase();
if response.contains("y"){
msolspray_path = "MSOLSpray".to_owned();
}
else if response.contains("n"){
println!("trying to automatically find msolspray.py in your tools folder...");
let find_result = find_file(tools_dir, "MSOLSpray.py");
if find_result.is_some(){
msolspray_path = find_result.unwrap();
loop {
let mut response = String::new();
println!("Found it! located at {}", msolspray_path);
println!("is that correct?");
let result = stdin().read_line(&mut response);
if result.is_err(){
println!("we need input here bruv, try again...");
continue;
}
response = response.to_lowercase();
if response.contains("n"){
loop{
msolspray_path = "".to_owned();
println!("ok, so where is msolspray.py then?");
let result = stdin().read_line(&mut msolspray_path);
if result.is_err(){
println!("we need input here burv...");
continue;
}
else{
break;
}
}
}
msolspray_path = format!("python {}", msolspray_path);
break;
}
}
else {
loop {
println!("OOOOF we didn't find it burh... where is MSOLSpray.py located?");
match stdin().read_line(&mut msolspray_path){
Ok(_response) => break,
Err(_e) => println!("we need input here bruv... try again")
}
}
}
}
}
break;
}
outline = format!("{} {} -p ||PASSWORD|| --url {}", msolspray_path.trim_end(), userlist.trim_end(), spray_target.trim_end());
return outline;
}
pub fn password_spray_help(project: &Project, season: String, lseason: String, year: i32, tools_dir: &PathBuf, config_path: &PathBuf){
let mut wait_time:u64 = 0;
let mut wait_time_response = String::new();
let mut bell_path = config_path.clone();
bell_path.pop();
bell_path.push("bell.mp3");
let mut tool_to_use = String::new();
loop {
println!("which tool?");
print!("
1.) nefarious spray
2.) msolspray.py
");
let exemethod_result = stdin().read_line(&mut tool_to_use);
if exemethod_result.is_err(){
println!("we need input here dummy!");
}
else{ else{
break break
} }
@@ -243,12 +355,12 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
Err(_e) => println!("we need you to put in the minutes for the obervation window please!") Err(_e) => println!("we need you to put in the minutes for the obervation window please!")
} }
} }
let mut wait_dur = Duration::from_secs(wait_time); let wait_dur = Duration::from_secs(wait_time);
let mut password_spray_file = project.notes_folder.clone(); let mut password_spray_file = project.notes_folder.clone();
password_spray_file.push("password_spray.md"); password_spray_file.push("password_spray.md");
println!("{}", password_spray_file.display()); println!("{}", password_spray_file.display());
let mut password_spray_string = String::new(); let mut password_spray_string = String::new();
let password_spray_read_result = fs::read_to_string(password_spray_file); let password_spray_read_result = fs::read_to_string(&password_spray_file);
if password_spray_read_result.is_err(){ if password_spray_read_result.is_err(){
println!("error reading password spray file!!!"); println!("error reading password spray file!!!");
return; return;
@@ -257,6 +369,7 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
password_spray_string = password_spray_read_result.unwrap(); password_spray_string = password_spray_read_result.unwrap();
} }
let mut passwords = Vec::new(); let mut passwords = Vec::new();
let mut sprayed_passwords = Vec::new();
println!("loading lines to parse..."); println!("loading lines to parse...");
for line in password_spray_string.split("\n"){ for line in password_spray_string.split("\n"){
if line.len() > 3{ if line.len() > 3{
@@ -281,23 +394,60 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
} }
passwords.push(password); passwords.push(password);
} }
else{
let words: Vec<&str> = line.split_whitespace().collect();
let password = words.last().unwrap().to_string();
println!("{} already sprayed, making note...", &password);
sprayed_passwords.push(password);
}
} }
} }
println!("passwords loaded, and parsed!"); println!("passwords loaded, and parsed!");
println!("starting password display and timer operations..."); println!("starting password display and timer operations...");
let mut outline = String::new(); let mut outline = String::new();
match exemethod.as_str(){ match tool_to_use.as_str(){
"1\n" => outline = format!("{} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", nefarious_spray_path.map_or("".to_string(), |s| s)), "1\n" => outline = nefarious_config(tools_dir),
"2\n" => outline = format!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt --etw --amsi --pipe totallyawesomepipeyo", nefarious_spray_path.map_or("".to_string(), |s| s)), "2\n" => outline = msolspray_config(tools_dir),
"3\n" => outline = {let mut path = String::new(); println!("path to nefarious spray.exe"); stdin().read_line(&mut path).unwrap(); format!("run {} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", path.trim_ascii_end())}, _ => println!("unkown tool to use, try again...")
"4\n" => outline = {let mut path = String::new(); println!("path to nefarious spray.exe"); stdin().read_line(&mut path).unwrap(); format!("{} spray -p ||PASSWORD|| -o C:\\temp\\fr\\||PASSWORD||.txt", path.trim_ascii_end())},
_ => {println!("unknown exec method... try again"); return;}
} }
for password in &passwords{ for password in &passwords{
let mut _spraycontinue = String::new(); let mut _spraycontinue = String::new();
println!("\n{}\n", outline.replace("||PASSWORD||", password)); let mut printline = outline.replace("||PASSWORD||", password);
println!("press enter to start timer"); if password.contains("useraspass"){
printline = printline.replace("-p useraspass", "--UserAsPass")
}
println!("\n{}\n", printline);
println!("enter s to save an return to main menu, or just enter to start timer");
stdin().read_line(&mut _spraycontinue).unwrap(); stdin().read_line(&mut _spraycontinue).unwrap();
sprayed_passwords.push(password.to_owned());
if _spraycontinue.contains("s"){
let new_spray_file = fs::OpenOptions::new().write(true).truncate(true).open(&password_spray_file);
if new_spray_file.is_err(){
println!("error saving progress, please make note of where you are and update the file accordingly");
}
else{
let mut open_spray_file = new_spray_file.unwrap();
let mut new_file_text = String::new();
for sprayed_pass in &sprayed_passwords{
new_file_text = format!("{}\n- [x] {}", new_file_text, sprayed_pass);
}
for password in &passwords{
if sprayed_passwords.contains(password) == false{
new_file_text = format!("{}\n- [ ] {}", new_file_text, password);
}
}
let save_result = open_spray_file.write_all(new_file_text.as_bytes());
if save_result.is_err(){
println!("saving failed!\nplease copy the below lines into your password spray notes!");
println!("{}", new_file_text);
}
else{
println!("password saved complete!!!");
println!("returning to main menu...");
return;
}
}
}
println!("waiting for {} minutes...", wait_dur.as_secs()); println!("waiting for {} minutes...", wait_dur.as_secs());
thread::sleep(wait_dur * 60); thread::sleep(wait_dur * 60);
let (_stream, stream_handle) = OutputStream::try_default().unwrap(); let (_stream, stream_handle) = OutputStream::try_default().unwrap();
@@ -309,3 +459,126 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
clear().unwrap(); clear().unwrap();
} }
} }
pub fn crack_hashes(cracking_rig: &String, project: &Project, terminal: &String, rockyou: &String, rule: &String){
let mut hash_file = String::new();
println!("trying to automatically find hashes.txt file...");
let find_result = find_file(&project.files_folder, "hashes.txt");
if find_result.is_some(){
hash_file = find_result.unwrap();
println!("hash file found!");
let mut res = String::new();
println!("is {} the file you want to crack?", hash_file);
match stdin().read_line(&mut res){
Ok(_r) => (),
Err(_e) => {println!("we need input here dummy! returning..."); return;}
}
res = res.to_lowercase();
if res.contains("n"){
println!("ooof ok, where is the file you want then?");
loop{
match stdin().read_line(&mut hash_file){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy! try again...")
}
}
}
if res.contains("y"){
println!("nice! checking for cracking directory...");
let listing_res = process::Command::new("ssh").arg(&cracking_rig).arg("'ls ~'").output();
if listing_res.is_err(){
println!("Error checking for cracking directory!");
println!("Error: {}", listing_res.unwrap_err());
}
else{
let listing_stdout = listing_res.unwrap().stdout;
let listing = String::from_utf8_lossy(&listing_stdout);
if listing.contains("hash_cracking") == false{
println!("no folder found, creating it...");
let mkdir = process::Command::new("ssh").arg(&cracking_rig).arg("'mkdir ~/hash_cracking'").status();
if mkdir.is_err(){
println!("error creating directory! try again...");
println!("Error: {}", mkdir.unwrap_err());
return;
}
}
let scp_arg = format!("'scp {} {}:~/hash_cracking/{}'", &hash_file, cracking_rig, &hash_file);
let scp_res = process::Command::new("ssh").arg(&cracking_rig).arg(scp_arg).status();
if scp_res.is_err(){
println!("error uploading hashes file!");
println!("Error: {}", scp_res.unwrap_err());
return;
}
println!("nice, hach file uploaded! determining correct terminal command...");
let terminal = terminal.split(" ").collect::<Vec<&str>>()[0];
process::Command::new(terminal).arg("-e").arg("ssh").arg(&cracking_rig);
let mut hash_type_res = String::new();
let mut cracking_arg = String::new();
let mut crack_box = String::new();
let mut crack_box_res = String::new();
println!("do you use a distrobox to crack passwords?");
loop{
match stdin().read_line(&mut crack_box_res){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy, try again")
}
}
crack_box_res = crack_box_res.to_lowercase();
if crack_box_res.contains("y"){
println!("What's the distrobox's name?");
loop{
match stdin().read_line(&mut crack_box){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy, try again!")
}
}
}
else{
crack_box = "no".to_owned();
}
if crack_box == "no".to_owned(){
cracking_arg = format!("sudo hashcat -m ||MODE|| -a 0 -r {} /home/{}/hash_cracking/{} {}", rule, cracking_rig.split("@").collect::<Vec<&str>>()[1], &hash_file, &rockyou);
}
else{
cracking_arg = format!("distrobox enter --root {} -- sudo -S hashcat -m ||MODE|| -a 0 -r {} /home/{}/hash_cracking/{} {}", crack_box, rule, cracking_rig.split("@").collect::<Vec<&str>>()[1], &hash_file, &rockyou);
}
loop{
println!("Hash type?");
print!("
1.) kerberos
2.) ntlm
3.) other
");
let _res = stdin().read_line(&mut hash_type_res);
if _res.is_err(){
println!("we need input here dummy! try again...");
}
else{
match hash_type_res.as_str(){
"1\n" => {cracking_arg = cracking_arg.replace("||MODE||", "19700"); break;},
"2\n" => {cracking_arg = cracking_arg.replace("||MODE||", "1000"); break;},
"3\n" => {let mut mode = String::new();
println!("code for the mode you want to use?");
loop{
match stdin().read_line(&mut mode){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy, try again...")
}
}
cracking_arg = cracking_arg.replace("||MODE||", &mode);
break;
},
_ => println!("unknown selection... try again...")
}
}
}
let spaw_res = process::Command::new(terminal).arg("-e").arg("ssh").arg(&cracking_rig).arg(cracking_arg).spawn();
if spaw_res.is_err(){
println!("error spawing new terminal to ssh with!");
println!("ERROR: {}", spaw_res.unwrap_err());
}
}
}
}
}

View File

@@ -9,9 +9,10 @@ use reqwest::blocking::get;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::process::exit; use std::process::exit;
use directories::UserDirs;
fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String){ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){
let mut delete_for_cleanup = config_path.clone(); let mut delete_for_cleanup = config_path.clone();
delete_for_cleanup.pop(); delete_for_cleanup.pop();
let mut failed = false; let mut failed = false;
@@ -20,6 +21,10 @@ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, Stri
let mut upcomming_files_folder = String::new(); let mut upcomming_files_folder = String::new();
let mut upcomming_notes_folder = String::new(); let mut upcomming_notes_folder = String::new();
let mut tools_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(){ while new_files_folder.is_empty() || new_notes_folder.is_empty() || tools_folder.is_empty(){
if new_files_folder.is_empty(){ if new_files_folder.is_empty(){
println!("path to save active project files?"); println!("path to save active project files?");
@@ -56,12 +61,64 @@ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, Stri
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...") 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...")
} }
let new_files_path = PathBuf::from(&new_files_folder); have_rig = have_rig.to_lowercase();
let new_notes_path = PathBuf::from(&new_notes_folder); if have_rig.contains("y"){
let upcomming_files_path = PathBuf::from(&upcomming_files_folder); println!("excellent! Whats the IP or hostname?");
let upcomming_notes_path = PathBuf::from(&upcomming_notes_folder); loop{
let tools_path = PathBuf::from(&tools_folder); match stdin().read_line(&mut cracking_rig){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy, try again...")
}
}
println!("user to ssh as for the cracking rig?");
loop{
match stdin().read_line(&mut cracking_user){
Ok(_r) => break,
Err(_e) => println!("we need input here dummy, try again...")
}
}
println!("Path to rockyou.txt on the cracking rig?");
loop{
match stdin().read_line(&mut rockyou){
Ok(_r) => break,
Err(_e) => println!("we need input here dummyu try again...")
}
}
println!("Path to one rule to rule them all on the cracking rig?");
loop{
match stdin().read_line(&mut rule){
Ok(_r) => break,
Err(_e) => println!("we need input here dummyu try again...")
}
}
}
else if have_rig.contains("n"){
println!("ooof ok freeloader");
cracking_rig = "n".to_owned();
rule = "n".to_owned();
rockyou = "n".to_owned();
}
}
}
new_files_folder = new_files_folder.trim_end().to_owned();
new_notes_folder = new_notes_folder.trim_end().to_owned();
upcomming_files_folder = upcomming_files_folder.trim_end().to_owned();
upcomming_notes_folder = upcomming_notes_folder.trim_end().to_owned();
tools_folder = tools_folder.trim_end().to_owned();
cracking_rig = cracking_rig.trim_end().to_owned();
cracking_user = cracking_user.trim_end().to_owned();
let new_files_path = PathBuf::from(&new_files_folder.trim_end());
let new_notes_path = PathBuf::from(&new_notes_folder.trim_end());
let upcomming_files_path = PathBuf::from(&upcomming_files_folder.trim_end());
let upcomming_notes_path = PathBuf::from(&upcomming_notes_folder.trim_end());
let tools_path = PathBuf::from(&tools_folder.trim_end());
if new_files_path.exists() == false{ if new_files_path.exists() == false{
println!("active project file folder does not exist, creating..."); println!("active project file folder does not exist, creating...");
match fs::create_dir_all(&new_files_folder){ match fs::create_dir_all(&new_files_folder){
@@ -106,7 +163,72 @@ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, Stri
} }
exit(1); exit(1);
} }
return (new_files_folder, new_notes_folder, tools_folder, upcomming_files_folder, upcomming_notes_folder); return (new_files_folder, new_notes_folder, tools_folder, upcomming_files_folder, upcomming_notes_folder, cracking_rig, cracking_user, rockyou, rule);
}
fn configure_distrobox(){
let user_dirs_result = UserDirs::new();
let mut success = false;
let mut dbrcpath = PathBuf::new();
if user_dirs_result.is_some(){
let home = user_dirs_result.unwrap().home_dir().to_path_buf();
dbrcpath.push(home);
dbrcpath.push(".distroboxrc");
let box_config_string_result = fs::read_to_string("/usr/etc/distrobox/distrobox.conf");
if box_config_string_result.is_err(){
println!("error reading distrobox config file");
}
else{
let box_rc_file_res = fs::File::create(&dbrcpath);
if box_rc_file_res.is_err(){
println!("error creating {}", &dbrcpath.display());
}
else{
let mut box_rc_file = box_rc_file_res.unwrap();
let box_config_string = box_config_string_result.unwrap();
let box_config_lines: Vec<&str> = box_config_string.split("\n").collect();
let mut line_write_result = true;
while line_write_result{
for line in &box_config_lines{
let mut _outline = String::new();
if line.contains("container_always_pull"){
_outline = "container_always_pull=\"0\"".to_owned();
}
else{
_outline = line.to_string();
}
let box_rc_file_result = box_rc_file.write(_outline.as_bytes());
if box_rc_file_result.is_ok(){
box_rc_file_result.unwrap();
line_write_result = true;
}
else{
line_write_result = false;
}
}
if line_write_result == false{
success = false;
break;
}
else{
success = true;
break;
}
}
}
}
}
if success == false{
println!("Error getting user dirs!");
println!("distrobox config failed, please follow the following instructions...");
print!("
copy the distrobox config file to your home folder with the name .distroboxrc
cp /usr/etc/distrobox/distrobox.conf ~/.distroboxrc
Then edit the file to change the line container_always_pull=\"1\" to container_always_pull=\"0\"
");
}
} }
@@ -122,6 +244,9 @@ pub fn install(config_path: &PathBuf){
config_folder_path.pop(); config_folder_path.pop();
let mut projects_conf_path = config_folder_path.clone(); let mut projects_conf_path = config_folder_path.clone();
let mut bell_file_path = config_folder_path.clone(); let mut bell_file_path = config_folder_path.clone();
let del_on_fail = config_folder_path.clone();
projects_conf_path.push("projects.conf");
fs::create_dir_all(&config_folder_path).expect("error creating config dir");
bell_file_path.push("bell.mp3"); bell_file_path.push("bell.mp3");
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3"; let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
let response = get(bell_sound_url).unwrap(); let response = get(bell_sound_url).unwrap();
@@ -129,12 +254,9 @@ pub fn install(config_path: &PathBuf){
let mut bell_file = File::create(bell_file_path).unwrap(); let mut bell_file = File::create(bell_file_path).unwrap();
copy(&mut response.take(response_length), &mut bell_file).unwrap(); copy(&mut response.take(response_length), &mut bell_file).unwrap();
println!("bell notification tone sucessfully downloaded!"); println!("bell notification tone sucessfully downloaded!");
let 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");
let mut config_file = fs::File::create(config_path).expect("error creating file"); 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"); 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"); projects_conf_file.write_all(b"customer:name:notes:files:active:box_name:stage\n").expect("error writing default project info");
let mut terminal_response = String::new(); let mut terminal_response = String::new();
let mut template_name = String::new(); let mut template_name = String::new();
let mut have_template = String::new(); let mut have_template = String::new();
@@ -156,7 +278,7 @@ pub fn install(config_path: &PathBuf){
else{ else{
_terminal_command = _terminal_commands[terminal_response.trim_end()].to_owned(); _terminal_command = _terminal_commands[terminal_response.trim_end()].to_owned();
} }
let (files_response, notes_response, tools_response, project_folder_path, project_note_path) = setup_folders(&config_path); let (files_response, notes_response, tools_response, project_folder_path, project_note_path, cracking_rig, cracking_user, rockyou, rule) = setup_folders(&config_path);
print!(" print!("
This tool is mainly to handle distrobox creation and usage. 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. It's expecting you to have a distrobox that you will use as a template.
@@ -175,9 +297,9 @@ Do you have a distrobox set up to function as your template for all new projects
let _list = process::Command::new("distrobox").arg("list").arg("--root").status(); let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
println!("distrobox template name?"); println!("distrobox template name?");
std::io::stdin().read_line(&mut template_name).unwrap(); std::io::stdin().read_line(&mut template_name).unwrap();
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nbox_template:{}\nterminal:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(),template_name.trim_end(), _terminal_command.trim_end()); let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end());
config_file.write_all(config_string.as_bytes()).expect("error writing to config file"); config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
let default_projectline = format!("default:default:{}:{}:yes:{}", &notes_response.trim_end(), &files_response.trim_end(), &template_name.trim_end()); let default_projectline = format!("default:default:{}:{}:yes:{}:current", &notes_response.trim_end(), &files_response.trim_end(), &template_name.trim_end());
projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line"); projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line");
println!("active project folders: {}", &files_response); println!("active project folders: {}", &files_response);
println!("upcomming project folders: {}", &project_folder_path); println!("upcomming project folders: {}", &project_folder_path);
@@ -194,11 +316,8 @@ Do you have a distrobox set up to function as your template for all new projects
let mut password_spray_template_path = install_path.clone(); let mut password_spray_template_path = install_path.clone();
install_path.push("new_projects.conf"); install_path.push("new_projects.conf");
password_spray_template_path.push("passwordspray.md"); password_spray_template_path.push("passwordspray.md");
let password_spray_template_path = install_path.clone(); let pass_file_config_line = format!("\npass_file:{}", password_spray_template_path.display());
let mut conf_file = fs::File::create(install_path).expect("error creating config file"); config_file.write_all(pass_file_config_line.as_bytes()).expect("error writing password spray setting to config file");
write!(conf_file, "project_folder_path:{}
project_notes_path:{}
", project_folder_path.trim_end(), project_note_path.trim_end()).expect("error writing config file");
let mut passpray_file = fs::File::create(password_spray_template_path).expect("error creating passwordspray file"); let mut passpray_file = fs::File::create(password_spray_template_path).expect("error creating passwordspray file");
write!(passpray_file, " write!(passpray_file, "
- [ ] useraspass - [ ] useraspass
@@ -231,5 +350,6 @@ project_notes_path:{}
- [ ] Service - [ ] Service
- [ ] Service! - [ ] Service!
- [ ] Serviceyear!").expect("error writing password spray template"); - [ ] Serviceyear!").expect("error writing password spray template");
configure_distrobox();
std::process::exit(0); std::process::exit(0);
} }

View File

@@ -1,5 +1,6 @@
use std::path::PathBuf; use std::{io::stdin, path::PathBuf};
use directories::UserDirs; use directories::UserDirs;
use reqwest::Response;
use std::fs; use std::fs;
#[derive(Clone)] #[derive(Clone)]
@@ -10,6 +11,7 @@ pub struct Project{
pub files_folder: PathBuf, pub files_folder: PathBuf,
pub active: bool, pub active: bool,
pub boxname: String, pub boxname: String,
pub stage: String,
pub id: i32, pub id: i32,
} }
@@ -20,6 +22,22 @@ mod box_controls;
mod info_controls; mod info_controls;
mod start_pentest; mod start_pentest;
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() { fn main() {
print!(" print!("
@@ -53,6 +71,12 @@ fn main() {
let mut tools_folder = PathBuf::new(); let mut tools_folder = PathBuf::new();
let mut terminal_command = String::new(); let mut terminal_command = String::new();
let mut box_template = String::new(); let mut box_template = String::new();
let mut cracking_rig = String::new();
let mut rockyou = String::new();
let mut rule = String::new();
let mut upcoming_files = PathBuf::new();
let mut upcoming_notes = PathBuf::new();
let mut pass_spray_file = PathBuf::new();
println!("\nconfig already generated\nloading config file...\n"); println!("\nconfig already generated\nloading config file...\n");
let settings_string = fs::read_to_string(&config_path).expect("error reading config file"); let settings_string = fs::read_to_string(&config_path).expect("error reading config file");
let settings: Vec<&str> = settings_string.split("\n").collect(); let settings: Vec<&str> = settings_string.split("\n").collect();
@@ -63,8 +87,14 @@ fn main() {
"Project_files" => project_base_folder.push(setting_vec[1].trim_end()), "Project_files" => project_base_folder.push(setting_vec[1].trim_end()),
"Project_notes" => project_base_notes.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()), "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(), "box_template" => box_template = setting_vec[1].trim_end().to_owned(),
"terminal" => terminal_command = 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]),
_ => println!("error unknown setting: {}", setting_vec[0]) _ => println!("error unknown setting: {}", setting_vec[0])
} }
} }
@@ -74,12 +104,15 @@ fn main() {
Note Folders: {} Note Folders: {}
Tools Folder: {} Tools Folder: {}
distrobox template: {} distrobox template: {}
terminal_command: {}\n terminal_command: {}
", project_base_folder.display(), project_base_notes.display(), tools_folder.display(), box_template, terminal_command); cracking_rig: {}\n
upcoming project folders: {}
upcoming project notes: {}
", &project_base_folder.display(), &project_base_notes.display(), &tools_folder.display(), box_template, terminal_command, cracking_rig, &upcoming_files.display(), &upcoming_notes.display());
println!("loading project configs..."); println!("loading project configs...");
let projects = project_controls::get_projects(&config_path); let projects = project_controls::get_projects(&config_path);
println!("Enter to start main menu"); println!("Enter to start main menu");
let mut enter = String::new(); let mut enter = String::new();
std::io::stdin().read_line(&mut enter).unwrap(); std::io::stdin().read_line(&mut enter).unwrap();
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command); 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);
} }

View File

@@ -1,3 +1,6 @@
use std::clone;
use std::path;
use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use chrono::Datelike; use chrono::Datelike;
@@ -31,9 +34,10 @@ fn get_active_project(projects: &Vec<Project>) -> &Project{
return active_project return active_project
} }
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &PathBuf, base_notes: &PathBuf, tools_dir: &PathBuf, boxtemplate: String, terminal: String){ 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){
let mut loopize = true; let mut loopize = true;
let mut new_id = next_project_id(&config_path); let mut new_id = next_project_id(&config_path);
let mut threads = Vec::new();
loop { loop {
let active_project = get_active_project(&projects); let active_project = get_active_project(&projects);
let mut response = String::new(); let mut response = String::new();
@@ -99,6 +103,8 @@ pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &
NOTE OPTION 18 WILL SAVE YOUR PROJECTS BEFORE QUITTING NOTE OPTION 18 WILL SAVE YOUR PROJECTS BEFORE QUITTING
base prject folder: {}
upcoming project folder: {}
Current Project: {} {} Current Project: {} {}
Working Folder: {} Working Folder: {}
Notes Folder: {} Notes Folder: {}
@@ -115,44 +121,56 @@ Year: {}
5 .) Save Project Information 5 .) Save Project Information
6 .) Import New Project - and setup new Distrobox 6 .) Import New Project - and setup new Distrobox
7 .) Remove Project 7 .) Remove Project
8 .) Open A New Terminal in Current Active Project 8 .) Print upcoming projects
9 .) Open A Terminal In this windows for the current active project 9. ) promote project from upcoming to current
10.) Open Project Files Folder In Dolphin 10.) Open A New Terminal in Current Active Project
11.) Open Project Notes Folder In Dolphin 11.) Open A Terminal In this windows for the current active project
12.) generate userpass file from your obsidian notes 12.) open current project's cobalt strike
13.) run pyro's initail enum script on a nessus csv for the current project 13.) re-create the distrobox for the current active project
14.) Print Project Info For Report 14.) Open Project Files Folder In Dolphin
15.) Build host discovery cmd command from scope in notes 15.) Open Project Notes Folder In Dolphin
16.) build portscan command from scope in notes 16.) generate userpass file from your obsidian notes
17.) Stop All Distroboxes 17.) run pyro's initail enum script on a nessus csv for the current project
18.) Password Spray (will print password to spray, and wait the obervation window time) 18.) Print Project Info For Report
19.) Quit Application 19.) Build host discovery cmd command from scope in notes
\n", active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year); 20.) build portscan command from scope in notes
21.) Stop All Distroboxes
22.) Password Spray (will print password to spray, and wait the obervation window time)
23.) crack password hashes on your cracking rig
24.) prune unused distroboxes (free up system storage)
25.) 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);
std::io::stdin().read_line(&mut response).expect("error getting menu input"); std::io::stdin().read_line(&mut response).expect("error getting menu input");
clear().expect("error clearing screen"); clear().expect("error clearing screen");
match response.as_str().trim_end(){ match response.as_str().trim_end(){
"1" => println!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()), "1" => 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!("+++++++++++++++++++++"); "2" => {println!("+++++++++++++++++++++");
for project in &projects{ for project in &projects{
println!("++{}|{}++",project.customer ,project.project_name)} println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)}
println!("++++++++++++++++++++")}, println!("++++++++++++++++++++")},
"3" => project_controls::switch_project(&mut projects), "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), "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)},
"7" => project_controls::remove_project(&mut projects, &config_path), "7" => project_controls::remove_project(&mut projects, &config_path),
"8" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()), "8" => project_controls::print_upcoming_projects(&projects),
"9" => box_controls::project_inline_terminal(active_project.clone()), "9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate),
"10" => info_controls::open_in_dolphin("files", active_project.clone()), "10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
"11" => info_controls::open_in_dolphin("notes", active_project.clone()), "11" => box_controls::project_inline_terminal(active_project.clone()),
"12" => info_controls::generate_userpass(&active_project), "12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}},
"13" => info_controls::run_initial_enum(&active_project), "13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false),
"14" =>info_controls::print_report_information(active_project.clone()), "14" => info_controls::open_in_dolphin("files", active_project.clone()),
"15" => info_controls::build_cmd_for_host_discovery(&active_project), "15" => info_controls::open_in_dolphin("notes", active_project.clone()),
"16" => info_controls::build_cs_portscan_cmd(&active_project), "16" => info_controls::generate_userpass(&active_project),
"17" => box_controls::stop_all_boxes(&projects), "17" => info_controls::run_initial_enum(&active_project),
"18" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path), "18" => info_controls::print_report_information(active_project.clone()),
"19" => {project_controls::save_projects(&projects, &config_path); "19" => info_controls::build_cmd_for_host_discovery(&active_project),
"20" => info_controls::build_cs_portscan_cmd(&active_project),
"21" => box_controls::stop_all_boxes(&projects),
"22" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
"23" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
"24" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
"25" => {project_controls::save_projects(&projects, &config_path);
let mut stop = String::new(); let mut stop = String::new();
println!("stop all boxes?\ny/n"); println!("stop all boxes?\ny/n");
std::io::stdin().read_line(&mut stop).unwrap(); std::io::stdin().read_line(&mut stop).unwrap();
@@ -169,4 +187,7 @@ Year: {}
let mut enter = String::new(); let mut enter = String::new();
std::io::stdin().read_line(&mut enter).unwrap(); std::io::stdin().read_line(&mut enter).unwrap();
} }
for thread in threads{
thread.join().unwrap();
}
} }

View File

@@ -4,10 +4,14 @@ use std::io::stdin;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::process::Command;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::str::FromStr; use std::str::FromStr;
use crate::get_user_input;
use fs_extra::file;
use crate::Project; use crate::Project;
use crate::box_controls::make_box;
pub fn switch_project(projects: &mut Vec<Project>){ pub fn switch_project(projects: &mut Vec<Project>){
for project in projects.clone(){ for project in projects.clone(){
@@ -46,30 +50,62 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
save_file_path.pop(); save_file_path.pop();
save_file_path.push("projects.conf"); save_file_path.push("projects.conf");
let mut save_file = fs::File::create(save_file_path).expect("error creating save_file"); let 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{ for project in projects{
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()}; let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
let mut _outline = String::new(); let mut _outline = String::new();
if project.active{ if project.active{
if active_set == false{ if active_set == false{
_outline = format!("{}yes:{}\n", default, project.boxname); _outline = format!("{}yes:{}:{}\n", default, project.boxname, project.stage);
active_set = true; active_set = true;
} }
} }
else{ 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"); 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){ 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){
let mut new_project_dir = project_dir.clone(); let mut new_project_dir = PathBuf::new();
let mut new_note_dir = notes_dir.clone(); let mut new_note_dir = PathBuf::new();
let mut existing_folders = String::new(); let mut existing_folders = String::new();
let mut customer_name = String::new(); let mut customer_name = String::new();
let mut project_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"); println!("do you have an existing notes and folder structure to copy over?\ny/n");
std::io::stdin().read_line(&mut existing_folders).unwrap(); std::io::stdin().read_line(&mut existing_folders).unwrap();
if existing_folders.contains("y") || existing_folders.contains("Y"){ if existing_folders.contains("y") || existing_folders.contains("Y"){
@@ -183,54 +219,6 @@ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir
} }
thread::sleep(Duration::from_secs(2)); thread::sleep(Duration::from_secs(2));
let box_name = format!("atarchbox_{}", customer_name); let box_name = format!("atarchbox_{}", customer_name);
let mut box_name_path = new_project_dir.clone();
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", new_project_dir.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(){
println!("we made a distrobox oh boy!");
let distrobox_start_result = process::Command::new("distrobox")
.arg("enter")
.arg("--root")
.arg(&box_name)
.arg("--")
.arg("sudo")
.arg("-s")
.arg("ln")
.arg("-sf")
.arg("/pentest/boxname")
.arg("/etc/boxname")
.status()
.expect("error getting response from distrobox start");
if distrobox_start_result.success(){
println!("distrobox was started as well!!!! good job me!");
}
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);
}
}
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);
}
let new_project = Project{customer: customer_name.trim_end().to_owned(), let new_project = Project{customer: customer_name.trim_end().to_owned(),
project_name: project_name.trim_end().to_owned(), project_name: project_name.trim_end().to_owned(),
notes_folder: new_note_dir, notes_folder: new_note_dir,
@@ -238,7 +226,11 @@ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir
active: false, active: false,
id: new_id, id: new_id,
boxname: box_name, boxname: box_name,
stage: project_stage.to_owned()
}; };
if project_stage.contains("current"){
make_box(&new_project, &tools_dir, &boxtemplate, true);
}
projects.push(new_project); projects.push(new_project);
save_projects(projects, config_path); save_projects(projects, config_path);
@@ -312,6 +304,12 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
if first != 1{ if first != 1{
if line.len() > 1{ if line.len() > 1{
let settings: Vec<&str> = line.split(":").collect(); let settings: Vec<&str> = line.split(":").collect();
//debug config file...
/*let mut count = 0;
for settin in &settings{
println!("{}: {}", count, settin);
count = count + 1;
}*/
let customer = settings[0].to_owned(); let customer = settings[0].to_owned();
let project = settings[1].to_owned(); let project = settings[1].to_owned();
let notes_string = settings[2].to_owned(); let notes_string = settings[2].to_owned();
@@ -327,7 +325,8 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
active = true; 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); println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
projects.push(new_project); projects.push(new_project);
} }
@@ -335,3 +334,114 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
} }
return projects 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){
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);
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);
}

View File

@@ -1,20 +1,54 @@
use std::fs; use std::fs;
use std::io::stdin; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; 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"); fn create_project_folder(path: &mut PathBuf, folder: &str){
let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file"); path.push(folder);
let mut host_notes = fs::File::create(format!("{}/host_notes.md", &project_folder_path)).expect("error creating host notes file"); let result = fs::create_dir_all(&path);
let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file"); 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(&notes_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(&notes_path);
if general_notes_result.is_some(){
let mut general_notes = general_notes_result.unwrap();
// for tagging // for tagging
let year = project_name.split("_").collect::<Vec<&str>>()[1];
let project_type = "External"; let project_type = "External";
writeln!(&mut general_notes, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing to general notes file"); writeln!(&mut general_notes, "#{} #{} #general", project.customer, project_type).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, "# Scope").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, "\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, "| -- | ----------- | -------- |").expect("error writing to general notes file");
@@ -54,7 +88,13 @@ Planning call notes:
| IP | host notes | needs? | | IP | host notes | needs? |
| -- | ---------- | ------ |\n").expect("faile to write pentest notes"); | -- | ---------- | ------ |\n").expect("faile to write pentest notes");
// set up the basics for our attack notes }
notes_path.pop();
notes_path.push("attacks.md");
let attack_notes_result = create_note_file(&notes_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," write!(&mut attack_notes,"
# Directory Bruteforcing # Directory Bruteforcing
- [ ] example.com - [ ] example.com
@@ -74,39 +114,61 @@ write!(&mut attack_notes,"
passwords tried: passwords tried:
* password\n * password\n
" ).expect("failed to write attack notes template"); " ).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, &notes_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(&notes_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(&notes_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"); fn internal(passtemp: &PathBuf, project: &Project){
let mut general_notes = fs::File::create(format!("{}/general.md", &project_folder_path)).expect("error creating general notes file"); let mut notes_path = project.notes_folder.clone();
let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file"); let file_creation_res = fs::create_dir_all(&notes_path);
let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file"); if file_creation_res.is_err(){
let mut systeminfo = fs::File::create(format!("{}/systeminfo", &project_folder_path)).expect("error creating systeminfo note file"); let error = file_creation_res.err().unwrap();
let mut netsta = fs::File::create(format!("{}/netstat", &project_folder_path)).expect("error creating netstat file"); println!("error creating notes folder! {}", error);
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"); else{
let mut cleanup_notes = fs::File::create(format!("{}/cleanup.md", &project_folder_path)).expect("error creating cleanup notes"); file_creation_res.unwrap();
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"); notes_path.push("password_spray.md");
let enum_obsidian_path = format!("Hack_Notes/pentest_notes/upcomming/{customer}//initial_enum.md", customer = comapny_name); println!("copying from {} to {}", passtemp.display(), &notes_path.display());
// for tagging notes let pass_result = fs::copy(&passtemp, &notes_path);
let oyear = project_name.split("_").collect::<Vec<&str>>()[0]; if pass_result.is_err(){
let year = format!("year-{}", oyear); let error = pass_result.err().unwrap();
let project_type = "Internal"; println!("error copying password spray file, try again manually! {}", error);
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"); else{
writeln!(&mut cleanup_notes, "#{} #{} #{} #cleanup", comapny_name, project_type, year).expect("error writing to cleanup notes"); pass_result.unwrap();
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"); notes_path.pop();
writeln!(&mut todo_notes, "#{} #{} #{} #todo", comapny_name, project_type, year).expect("error writing tag line on todo"); notes_path.push("l00t");
writeln!(&mut finding_notes, "#{} #{} #{} #findings", comapny_name, project_type, year).expect("error writing tags line on findings"); fs::create_dir_all(&notes_path).expect("error creating loot directory");
writeln!(&mut systeminfo, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tag line for system info"); notes_path.push("creds.md");
writeln!(&mut systeminfo, "#{} #{} #{} #Password_sprays", comapny_name, project_type, year).expect("error writing tag line for password spraying"); let creds_notes_result = create_note_file(&notes_path);
writeln!(&mut netsta, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tagline in the netstat file"); if creds_notes_result.is_some(){
writeln!(&mut enum_notes, "#{} #{} #{} #enum", comapny_name, project_type, year).expect("error writing tagline in the netstat file"); 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, "# CREDS").expect("error writing creds notes");
writeln!(&mut creds_notes, "\n| System | username | password |").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"); 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, "# HASHES\n\n").expect("error writing creds notes");
writeln!(&mut creds_notes, "| TYPE | USER | HASH |").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 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(&notes_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, "# 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 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, " write!(&mut general_notes, "
On the call: On the call:
@@ -151,6 +211,14 @@ Do they have a specific contact
Email any follow-up items from the call to the PM Email any follow-up items from the call to the PM
").expect("error writing PPC text"); ").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(&notes_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," write!(&mut attack_notes,"
# current dat (ex: 7/5) # current dat (ex: 7/5)
Got Persistence via (schtasks, bat schtasks, startup folder) Got Persistence via (schtasks, bat schtasks, startup folder)
@@ -206,7 +274,14 @@ 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(&notes_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, " write!(&mut finding_notes, "
# normal findings # normal findings
@@ -214,6 +289,13 @@ powerup.ps1/sharpup.exe notes.
## [Sarting Username] ## [Sarting Username]
").expect("error writing to findings notes on internal"); ").expect("error writing to findings notes on internal");
}
notes_path.pop();
notes_path.push("todo.md");
let todo_result = create_note_file(&notes_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, " write!(&mut todo_notes, "
- [ ] local checks - [ ] local checks
@@ -227,93 +309,47 @@ powerup.ps1/sharpup.exe notes.
- [ ] passwords in AD Descriptions? - [ ] passwords in AD Descriptions?
- [ ] password spray - [ ] password spray
").expect("error writing todo list"); ").expect("error writing todo list");
write!(&mut netsta," }
``` notes_path.pop();
notes_path.push("cleanup.md");
```").expect("error writing code block to system info"); let cleanup_result = create_note_file(&notes_path);
write!(&mut systeminfo," 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");
```").expect("error writing code block to system info"); writeln!(&mut cleanup_notes, "- [ ] Breach machine C-temp-fr").expect("error writing to cleanup notes");
let new_pass_path = format!("{}/passwordspray.md", &project_folder_path); writeln!(&mut cleanup_notes, "- [ ] (continue to add as needed").expect("error writing ot cleanup notes");
println!("{} | {}", passtemp.display(), new_pass_path); }
fs::copy(passtemp, new_pass_path).unwrap();
} }
pub fn start_pentest(config_path: &PathBuf) { 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 pentest_notes = String::new(); let mut project_files = upcoming_files.clone();
let mut project_files = String::new(); let mut project_notes = upcoming_notes.clone();
let mut company_name = String::new(); let customer_name = get_user_input("Customer name?");
let mut project_name = String::new(); let project_name = get_user_input("Project Name?");
let mut config_file_path_buf = config_path.clone(); project_files.push(&customer_name);
let mut passpray_path = config_file_path_buf.clone(); project_files.push(&project_name);
passpray_path.push("passwordspray.md"); project_notes.push(&customer_name);
config_file_path_buf.push("new_projects.conf"); project_notes.push(&project_name);
let config_string = fs::read_to_string(config_file_path_buf).expect("error reading "); println!("Files: {}\nNotes: {}\n\n", project_files.display(), project_notes.display());
if config_string.contains("folder_path") && config_string.contains("notes_path"){ let confirm_response = get_user_input("does this look ok?");
let config_string_vec: Vec<&str> = config_string.split("\n").collect(); if confirm_response.to_lowercase().contains("n"){
for line in config_string_vec{ println!("oof sorry");
if line.contains("project_folder_path"){ return;
let line_vec: Vec<&str> = line.split(":").collect();
project_files = line_vec[1].to_owned();
} }
else if line.contains("project_notes_path"){ let mut working = project_files.clone();
let line_vec: Vec<&str> = line.split(":").collect(); create_project_folder(&mut working, "working");
pentest_notes = line_vec[1].to_owned(); 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);
} }
} projects.push(new_prject);
println!("Project files path: {}\nProject Notes path: {}", project_files, pentest_notes); project_controls::save_projects(projects, config_path);
println!("Comapny Name?"); println!("project created and saved to the projects config file!");
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.");
}
} }