Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31dd862579 | ||
|
|
b85d0e5d79 | ||
|
|
477ac6e360 | ||
|
|
fe6524016f | ||
|
|
967052a4e2 | ||
|
|
2796d31f14 | ||
|
|
b137e0c34d | ||
|
|
8a1dca30e1 | ||
|
|
854feb2e2a | ||
|
|
bfa766a2c3 | ||
|
|
f7bdd0ad8a | ||
|
|
16706f8f6d | ||
|
|
b6ec849b36 | ||
|
|
69f5a4bd78 | ||
|
|
cad1f9d51c | ||
|
|
837012d163 |
@@ -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();
|
||||
@@ -71,7 +70,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,29 +91,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 --init --unshare-all --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(){
|
||||
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")
|
||||
@@ -122,19 +140,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,163 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::read_to_string;
|
||||
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 walkdir::WalkDir;
|
||||
use clearscreen::clear;
|
||||
use clearscreen;
|
||||
use rodio::{Decoder, OutputStream, Sink};
|
||||
use crate::get_user_input;
|
||||
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 +717,62 @@ 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);
|
||||
}
|
||||
@@ -5,10 +5,14 @@ use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::io::stdin;
|
||||
use std::io::copy;
|
||||
use std::process::Command;
|
||||
use reqwest::blocking::get;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::process::exit;
|
||||
use directories::UserDirs;
|
||||
|
||||
use crate::get_user_input;
|
||||
|
||||
|
||||
fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){
|
||||
@@ -166,6 +170,47 @@ fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, Stri
|
||||
}
|
||||
|
||||
|
||||
fn configure_distrobox(){
|
||||
let user_dirs_result = UserDirs::new();
|
||||
let mut success = false;
|
||||
let mut dbrcpath = PathBuf::new();
|
||||
if user_dirs_result.is_some(){
|
||||
let home = user_dirs_result.unwrap().home_dir().to_path_buf();
|
||||
dbrcpath.push(home);
|
||||
dbrcpath.push(".distroboxrc");
|
||||
let box_config_string = String::from("container_always_pull=\"0\"\ncontainer_generate_entry=1\ncontainer_manager=\"podman\"\ncontainer_name_default=\"ubuntu\"\ncontainer_image_default=\"ghcr.io/ublue-os/ubuntu-toolbox:latest\"\nnon_interactive=\"1\"\nxhost +si:localuser:$USER >/dev/null\nexport PIPEWIRE_RUNTIME_DIR=/dev/null\nexport PATH=$PATH:$HOME/.local/bin\n");
|
||||
let dbrc_file_res = fs::OpenOptions::new().write(true).create(true).open(dbrcpath);
|
||||
if dbrc_file_res.is_err(){
|
||||
let error = dbrc_file_res.err().unwrap();
|
||||
println!("error opening distroboxrc file!");
|
||||
println!("{}", error);
|
||||
}
|
||||
else{
|
||||
let mut dibrc_file = dbrc_file_res.unwrap();
|
||||
let dbrc_write_res = write!(dibrc_file, "{}",box_config_string);
|
||||
if dbrc_write_res.is_err(){
|
||||
println!("error writing config to distroboxrc file!");
|
||||
println!("{}", dbrc_write_res.err().unwrap());
|
||||
}
|
||||
else{
|
||||
let _dbrc_write = dbrc_write_res.unwrap();
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if success == false{
|
||||
println!("Error getting user dirs!");
|
||||
println!("distrobox config failed, please follow the following instructions...");
|
||||
print!("
|
||||
copy the distrobox config file to your home folder with the name .distroboxrc
|
||||
cp /usr/etc/distrobox/distrobox.conf ~/.distroboxrc
|
||||
|
||||
Then edit the file to change the line container_always_pull=\"1\" to container_always_pull=\"0\"
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn install(config_path: &PathBuf){
|
||||
let mut _terminal_commands = HashMap::from([
|
||||
@@ -220,18 +265,47 @@ Do you have a distrobox set up to function as your template for all new projects
|
||||
");
|
||||
std::io::stdin().read_line(&mut have_template).unwrap();
|
||||
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);
|
||||
println!("ooof buddy, should have had that already... no worries, we'll make one now.");
|
||||
let new_boxname = get_user_input("name for your template box? (for exmaple I use atarchbox cause its my attacking archbox ;-)");
|
||||
println!("please review the following link to select an image to use for your distrobox");
|
||||
println!("https://distrobox.it/compatibility/#containers-distros");
|
||||
let image_name = get_user_input("which image would you like to use?");
|
||||
let tools_volume =format!("{}:/tools:rw", &tools_response);
|
||||
let distrobox_create_res = Command::new("distrobox")
|
||||
.arg("create")
|
||||
.arg("--root")
|
||||
.arg("--name")
|
||||
.arg(new_boxname)
|
||||
.arg("--init")
|
||||
.arg("--image")
|
||||
.arg(image_name)
|
||||
.arg("--volume")
|
||||
.arg(tools_volume)
|
||||
.arg("--additional-packages")
|
||||
.arg("systemd")
|
||||
.arg("--")
|
||||
.arg("exit")
|
||||
.status();
|
||||
if distrobox_create_res.is_err(){
|
||||
let error = distrobox_create_res.err().unwrap();
|
||||
println!("ooof we ran into a problem creating your distrobox....");
|
||||
println!("{}", error);
|
||||
println!("you'll have to make it manually, but remember the name you want to use for the next step.");
|
||||
}
|
||||
else{
|
||||
distrobox_create_res.unwrap();
|
||||
println!("nice, we created a distrobox, remeber the name of your box for the next step!");
|
||||
}
|
||||
}
|
||||
let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
|
||||
println!("distrobox template name?");
|
||||
std::io::stdin().read_line(&mut template_name).unwrap();
|
||||
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end());
|
||||
let mut set_fprint = String::from("no");
|
||||
let fprint_answer = get_user_input("do you want to use fingerprint authentication inside the distroboxes?").to_lowercase();
|
||||
if fprint_answer.contains("y"){
|
||||
set_fprint = "yes".to_owned();
|
||||
}
|
||||
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}\nfingerprint:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end(), set_fprint);
|
||||
config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
|
||||
let default_projectline = format!("default:default:{}:{}:yes:{}:current", ¬es_response.trim_end(), &files_response.trim_end(), &template_name.trim_end());
|
||||
projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line");
|
||||
@@ -284,5 +358,6 @@ Do you have a distrobox set up to function as your template for all new projects
|
||||
- [ ] Service
|
||||
- [ ] Service!
|
||||
- [ ] Serviceyear!").expect("error writing password spray template");
|
||||
configure_distrobox();
|
||||
std::process::exit(0);
|
||||
}
|
||||
@@ -77,6 +77,7 @@ fn main() {
|
||||
let mut upcoming_files = PathBuf::new();
|
||||
let mut upcoming_notes = PathBuf::new();
|
||||
let mut pass_spray_file = PathBuf::new();
|
||||
let mut fingerprint = false;
|
||||
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();
|
||||
@@ -95,6 +96,7 @@ fn main() {
|
||||
"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}},
|
||||
_ => println!("error unknown setting: {}", setting_vec[0])
|
||||
}
|
||||
}
|
||||
@@ -114,5 +116,5 @@ fn main() {
|
||||
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, &upcoming_files, &upcoming_notes, &pass_spray_file);
|
||||
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
use std::clone;
|
||||
use std::path;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use chrono::Datelike;
|
||||
@@ -34,9 +31,10 @@ 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, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, password_spray_file: &PathBuf){
|
||||
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &PathBuf, base_notes: &PathBuf, tools_dir: &PathBuf, boxtemplate: String, terminal: String, cracking_rig: String, rockyou: String, rule: String, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, password_spray_file: &PathBuf, fingerprint: bool){
|
||||
let mut loopize = true;
|
||||
let mut new_id = next_project_id(&config_path);
|
||||
let mut threads = Vec::new();
|
||||
loop {
|
||||
let active_project = get_active_project(&projects);
|
||||
let mut response = String::new();
|
||||
@@ -124,18 +122,21 @@ Year: {}
|
||||
9. ) promote project from upcoming to current
|
||||
10.) Open A New Terminal in Current Active Project
|
||||
11.) Open A Terminal In this windows for the current active project
|
||||
12.) re-create the distrobox for the current active project
|
||||
13.) Open Project Files Folder In Dolphin
|
||||
14.) Open Project Notes Folder In Dolphin
|
||||
15.) generate userpass file from your obsidian notes
|
||||
16.) run pyro's initail enum script on a nessus csv for the current project
|
||||
17.) Print Project Info For Report
|
||||
18.) Build host discovery cmd command from scope in notes
|
||||
19.) build portscan command from scope in notes
|
||||
20.) Stop All Distroboxes
|
||||
21.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||
22.) crack password hashes on your cracking rig
|
||||
23.) Quit Application
|
||||
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.) 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.) Launch bloodhound with the current project's distrobox
|
||||
25.) prune unused distroboxes (free up system storage)
|
||||
26.) Quit Application
|
||||
\n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year);
|
||||
std::io::stdin().read_line(&mut response).expect("error getting menu input");
|
||||
clear().expect("error clearing screen");
|
||||
@@ -148,24 +149,27 @@ Year: {}
|
||||
"3" => project_controls::switch_project(&mut projects),
|
||||
"4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)},
|
||||
"5" => project_controls::save_projects(&projects, &config_path),
|
||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes)},
|
||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint)},
|
||||
"7" => project_controls::remove_project(&mut projects, &config_path),
|
||||
"8" => project_controls::print_upcoming_projects(&projects),
|
||||
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate),
|
||||
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint),
|
||||
"10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
|
||||
"11" => box_controls::project_inline_terminal(active_project.clone()),
|
||||
"12" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false),
|
||||
"13" => info_controls::open_in_dolphin("files", active_project.clone()),
|
||||
"14" => info_controls::open_in_dolphin("notes", active_project.clone()),
|
||||
"15" => info_controls::generate_userpass(&active_project),
|
||||
"16" => info_controls::run_initial_enum(&active_project),
|
||||
"17" => info_controls::print_report_information(active_project.clone()),
|
||||
"18" => info_controls::build_cmd_for_host_discovery(&active_project),
|
||||
"19" => info_controls::build_cs_portscan_cmd(&active_project),
|
||||
"20" => box_controls::stop_all_boxes(&projects),
|
||||
"21" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
|
||||
"22" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
|
||||
"23" => {project_controls::save_projects(&projects, &config_path);
|
||||
"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" => 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 bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);},
|
||||
"25" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
|
||||
"26" => {project_controls::save_projects(&projects, &config_path);
|
||||
let mut stop = String::new();
|
||||
println!("stop all boxes?\ny/n");
|
||||
std::io::stdin().read_line(&mut stop).unwrap();
|
||||
@@ -182,4 +186,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,10 +4,12 @@ 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 fs_extra::file;
|
||||
use crate::Project;
|
||||
use crate::box_controls::make_box;
|
||||
|
||||
@@ -66,7 +68,7 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf){
|
||||
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool){
|
||||
let mut new_project_dir = PathBuf::new();
|
||||
let mut new_note_dir = PathBuf::new();
|
||||
let mut existing_folders = String::new();
|
||||
@@ -227,7 +229,7 @@ pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir
|
||||
stage: project_stage.to_owned()
|
||||
};
|
||||
if project_stage.contains("current"){
|
||||
make_box(&new_project, &tools_dir, &boxtemplate, true);
|
||||
make_box(&new_project, &tools_dir, &boxtemplate, true, fingerprint);
|
||||
}
|
||||
projects.push(new_project);
|
||||
save_projects(projects, config_path);
|
||||
@@ -341,7 +343,7 @@ pub fn print_upcoming_projects(projects: &Vec<Project>){
|
||||
}
|
||||
}
|
||||
|
||||
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String){
|
||||
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool){
|
||||
let working_projects = projects.clone();
|
||||
for project in &working_projects{
|
||||
if project.stage.contains("upcoming"){
|
||||
@@ -365,6 +367,8 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
|
||||
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)
|
||||
@@ -377,21 +381,60 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
|
||||
.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);
|
||||
make_box(&promoted_project, tools_dir, boxtemplate, true, fingerprint);
|
||||
projects_to_save.push(promoted_project);
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -34,12 +34,17 @@ fn create_note_file(path: &PathBuf) -> Option<File>{
|
||||
fn external(passtemp: &PathBuf, project: &Project){
|
||||
// using a pathbuf to create files.
|
||||
let mut notes_path = project.notes_folder.clone();
|
||||
notes_path.push("general.md");
|
||||
let general_notes_result = fs::File::create(¬es_path);
|
||||
if general_notes_result.is_err(){
|
||||
println!("oof we ran into issues making the general notes! try to creat manually!");
|
||||
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 {
|
||||
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 project_type = "External";
|
||||
@@ -86,11 +91,8 @@ Planning call notes:
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("attacks.md");
|
||||
let attack_notes_result = fs::File::create(¬es_path);
|
||||
if attack_notes_result.is_err(){
|
||||
println!("oof we ran into issues making the general notes! try to creat manually!");
|
||||
}
|
||||
else {
|
||||
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,"
|
||||
@@ -124,21 +126,15 @@ passwords tried:
|
||||
}
|
||||
notes_path.pop();
|
||||
notes_path.push("host_notes.md");
|
||||
let host_notes_result = fs::File::create(¬es_path);
|
||||
if host_notes_result.is_err(){
|
||||
println!("error creating host notes, try manually!");
|
||||
}
|
||||
else{
|
||||
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 = fs::File::create(notes_path);
|
||||
if findings_notes_result.is_err(){
|
||||
println!("error creating host findings file, try manually!");
|
||||
}
|
||||
else{
|
||||
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");
|
||||
}
|
||||
@@ -335,6 +331,12 @@ pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32
|
||||
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;
|
||||
}
|
||||
let mut working = project_files.clone();
|
||||
create_project_folder(&mut working, "working");
|
||||
create_project_folder(&mut working, "writing");
|
||||
|
||||
Reference in New Issue
Block a user