From 2346988e23337533f18231d73bf640727bd5e040 Mon Sep 17 00:00:00 2001 From: pyro57000 Date: Tue, 15 Apr 2025 13:08:48 -0500 Subject: [PATCH] added an option to parse cs portscann output --- pentest_tool/src/info_controls.rs | 267 ++++++++++++++++++++++++++++++ pentest_tool/src/main.rs | 30 +++- pentest_tool/src/menu.rs | 32 ++-- 3 files changed, 313 insertions(+), 16 deletions(-) diff --git a/pentest_tool/src/info_controls.rs b/pentest_tool/src/info_controls.rs index 879ecef..015faf1 100644 --- a/pentest_tool/src/info_controls.rs +++ b/pentest_tool/src/info_controls.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +use std::fmt::write; use std::fs; +use std::fs::create_dir_all; use std::fs::read_to_string; use std::fs::OpenOptions; use std::hash::Hash; @@ -13,12 +15,15 @@ use std::time::Duration; use std::io::stdin; use std::thread::JoinHandle; use chrono::format; +use fs_extra::file; use reqwest::dns::Name; use walkdir::WalkDir; use clearscreen::clear; use clearscreen; use rodio::{Decoder, OutputStream, Sink}; use crate::get_user_input; +use crate::open_overwrite; +use crate::open_append; use crate::Project; pub fn run_initial_enum(project: &Project){ @@ -889,4 +894,266 @@ last write!(email_note_file, "{}\n", outline).expect("error writing email notes file!"); write!(email_text_file, "{}\n", outline).expect("error writing email text file!"); } +} + +pub fn parse_csportscan(project: &Project){ + let mut tsv_path = project.files_folder.clone(); + tsv_path.push("working/tsvs/services.tsv"); + let mut outfile = tsv_path.clone(); + outfile.pop(); + outfile.pop(); + let mut windows_hosts = Vec::new(); + let mut ssh_hosts = Vec::new(); + let mut ftp_hosts = Vec::new(); + let mut rdp_hosts = Vec::new(); + let mut dns_hosts = Vec::new(); + let mut snmp_hosts = Vec::new(); + let mut web_hosts = Vec::new(); + let mut telnet_hosts = Vec::new(); + let mut unknown_ports = Vec::new(); + + if !get_user_input("do you have the tsv saved in the project folder under working/tsvs/services.tsv?").to_lowercase().contains("y"){ + tsv_path.clear(); + tsv_path.push(get_user_input("ooof ok, please enter the full path to your tsv file.")); + } + let tsv_read_res = read_to_string(tsv_path); + if tsv_read_res.is_err(){ + let error = tsv_read_res.err().unwrap(); + println!("ooof error reading tsv file!"); + println!("{}", error); + return; + } + println!("tsv read, parsing lines..."); + let tsv_string = tsv_read_res.unwrap(); + let lines: Vec<&str> = tsv_string.split("\n").collect(); + for line in lines{ + let words: Vec<&str> = line.split("\t").collect(); + if words.len() > 1{ + let host = words[0].to_lowercase().to_owned(); + let port = words[1].to_lowercase().to_owned(); + let host_entry = format!("{}:{}", &host, &port); + match words[1]{ + "135" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}}, + "445" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}}, + "22" => {if !ssh_hosts.contains(&host){ssh_hosts.push(host);}}, + "21" => {if !ftp_hosts.contains(&host){ftp_hosts.push(host);}}, + "23" => {if !telnet_hosts.contains(&host){telnet_hosts.push(host)}}, + "3389" => {if !rdp_hosts.contains(&host){rdp_hosts.push(host);}}, + "80" | "443" | "8080" | "8443" | "4433" | "8000" => {if !web_hosts.contains(&host_entry){web_hosts.push(host_entry);}}, + "53" => {if !dns_hosts.contains(&host){dns_hosts.push(host);}}, + "161" => {if !snmp_hosts.contains(&host){snmp_hosts.push(host);}}, + _ => { + if words.len() == 3{ + let banner = words[2].to_lowercase().to_owned(); + if words[2].to_lowercase().contains("ssh"){ + if !ssh_hosts.contains(&host_entry){ + ssh_hosts.push(host_entry); + } + } + else if banner.contains("ftp"){ + if !ftp_hosts.contains(&host_entry){ + ftp_hosts.push(host_entry); + } + } + else if banner.contains("nginx") || banner.contains("apache"){ + if !web_hosts.contains(&host_entry){ + web_hosts.push(host_entry); + } + } + else{ + continue; + } + } + else if words.len() == 2{ + unknown_ports.push(host_entry); + } + } + } + } + } + println!("is {} where you want to save your files?", outfile.display()); + if get_user_input("").to_lowercase().contains("n"){ + outfile.clear(); + outfile.push(get_user_input("ok, please enter the full path to the folder you want to save them to.")); + } + print!(" +{} Windows hosts found! +{} SSH hosts found! +{} FTP hosts found! +{} Telnet hosts found! +{} SNMP hosts found! +{} DNS hosts found! +{} RDP hosts found! +{} untagged hosts found! +", windows_hosts.len(), ssh_hosts.len(), ftp_hosts.len(), telnet_hosts.len(), snmp_hosts.len(), dns_hosts.len(), rdp_hosts.len(), unknown_ports.len()); + println!("lines parsed! creating output files..."); + outfile.push("windows_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut windows_file = file_option.unwrap(); + for host in windows_hosts{ + let write_res = write!(windows_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing windows_hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("ssh_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut ssh_file = file_option.unwrap(); + for host in ssh_hosts{ + let write_res = write!(ssh_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing ssh_hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("telnet_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut telnet_file = file_option.unwrap(); + for host in telnet_hosts{ + let write_res = write!(telnet_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("ftp_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut ftp_file = file_option.unwrap(); + for host in ftp_hosts{ + let write_res = write!(ftp_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("snmp_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut snmp_file = file_option.unwrap(); + for host in snmp_hosts{ + let write_res = write!(snmp_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("dns_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut dns_file = file_option.unwrap(); + for host in dns_hosts{ + let write_res = write!(dns_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("rdp_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut rdp_file = file_option.unwrap(); + for host in rdp_hosts{ + let write_res = write!(rdp_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + outfile.pop(); + outfile.push("web_hosts.txt"); + let file_option = open_overwrite(&outfile); + if file_option.is_some(){ + let mut web_file = file_option.unwrap(); + for host in web_hosts{ + let write_res = write!(web_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("oooof error writing _hosts.txt!!"); + println!("{}", error); + } + else{ + write_res.unwrap(); + } + } + } + println!("interesting ports have been written to... writing untagged port files..."); + outfile.pop(); + outfile.push("untagged ports"); + if !outfile.exists(){ + let untagged_res = create_dir_all(&outfile); + if untagged_res.is_err(){ + let error = untagged_res.err().unwrap(); + println!("ooof error creating untagged folder!"); + println!("{}", error); + } + else{ + untagged_res.unwrap(); + } + } + for line in unknown_ports{ + let line_vec:Vec<&str> = line.split(":").collect(); + let host = line_vec[0].to_owned(); + let port = line_vec[1].to_owned(); + let file_name = format!("{}_hosts.txt", port); + outfile.push(file_name); + let write_file_opt = open_append(&outfile); + if write_file_opt.is_some(){ + let mut write_file = write_file_opt.unwrap(); + let write_res = write!(write_file, "{}\n", host); + if write_res.is_err(){ + let error = write_res.err().unwrap(); + println!("ooof error writing to file..."); + println!("{}", error); + } + } + outfile.pop(); + } + println!("DONE all files saved to {}", outfile.display()); + println!("note if no hosts were found for a protocol their files will be empty."); } \ No newline at end of file diff --git a/pentest_tool/src/main.rs b/pentest_tool/src/main.rs index 6dd9b05..154bf49 100644 --- a/pentest_tool/src/main.rs +++ b/pentest_tool/src/main.rs @@ -2,7 +2,7 @@ use std::{io::stdin, path::PathBuf, process::Command}; use directories::UserDirs; use reqwest::Response; use std::process::exit; -use std::fs; +use std::fs::{self, File}; #[derive(Clone)] pub struct Project{ @@ -23,6 +23,34 @@ mod box_controls; mod info_controls; mod start_pentest; +pub fn open_overwrite(path: &PathBuf) -> Option{ + let file_create_res = fs::OpenOptions::new().create(true).write(true).open(path); + if file_create_res.is_err(){ + let error = file_create_res.err().unwrap(); + println!("error opening {} file!", path.display()); + println!("{}", error); + return None; + } + else { + let file = file_create_res.unwrap(); + return Some(file); + } +} + +pub fn open_append(path: &PathBuf) -> Option{ + let file_create_res = fs::OpenOptions::new().create(true).append(true).open(path); + if file_create_res.is_err(){ + let error = file_create_res.err().unwrap(); + println!("error opening {} file!", path.display()); + println!("{}", error); + return None; + } + else { + let file = file_create_res.unwrap(); + return Some(file); + } +} + pub fn get_user_input(prompt: &str) -> String{ let mut response = String::new(); loop{ diff --git a/pentest_tool/src/menu.rs b/pentest_tool/src/menu.rs index 7dcf23d..3ecbea2 100644 --- a/pentest_tool/src/menu.rs +++ b/pentest_tool/src/menu.rs @@ -113,7 +113,7 @@ pub fn main_menu(mut projects: Vec, config_path: PathBuf, base_files: & -NOTE OPTION 27 WILL SAVE YOUR PROJECTS BEFORE QUITTING +NOTE OPTION 28 WILL SAVE YOUR PROJECTS BEFORE QUITTING base prject folder: {} upcoming project folder: {} @@ -147,13 +147,14 @@ General Notes: {} 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.) Parse GatherContacts output file - 26.) prune unused distroboxes (free up system storage) - 27.) Quit Application + 21.) parse a cs portscan services.tsv file + 22.) Stop All Distroboxes + 23.) Password Spray (will print password to spray, and wait the obervation window time) + 24.) crack password hashes on your cracking rig + 25.) Launch bloodhound with the current project's distrobox + 26.) Parse GatherContacts output file + 27.) prune unused distroboxes (free up system storage) + 28.) Quit Application \n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year, &obsidian_uri); std::io::stdin().read_line(&mut response).expect("error getting menu input"); clear().expect("error clearing screen"); @@ -181,13 +182,14 @@ General Notes: {} "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" => info_controls::partse_gathercontacts(&active_project), - "26" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}}, - "27" => {project_controls::save_projects(&projects, &config_path); + "21" => info_controls::parse_csportscan(&active_project), + "22" => box_controls::stop_all_boxes(&projects), + "23" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path), + "24" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule), + "25" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);}, + "26" => info_controls::partse_gathercontacts(&active_project), + "27" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}}, + "28" => {project_controls::save_projects(&projects, &config_path); let mut stop = String::new(); println!("stop all boxes?\ny/n"); std::io::stdin().read_line(&mut stop).unwrap();