From 1a5c05cf8ca621f1a80ea3b093a4627406d7215c Mon Sep 17 00:00:00 2001 From: Pyro57000 <147988717+Pyro57000@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:19:13 -0600 Subject: [PATCH] uploaded the start of the pentest script. --- start_pentest/Cargo.lock | 213 +++++++++++++++++++++ start_pentest/Cargo.toml | 10 + start_pentest/src/main.rs | 384 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 607 insertions(+) create mode 100644 start_pentest/Cargo.lock create mode 100644 start_pentest/Cargo.toml create mode 100644 start_pentest/src/main.rs diff --git a/start_pentest/Cargo.lock b/start_pentest/Cargo.lock new file mode 100644 index 0000000..427a949 --- /dev/null +++ b/start_pentest/Cargo.lock @@ -0,0 +1,213 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "proc-macro2" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "start_pentest" +version = "0.1.0" +dependencies = [ + "dirs", +] + +[[package]] +name = "syn" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/start_pentest/Cargo.toml b/start_pentest/Cargo.toml new file mode 100644 index 0000000..d97a511 --- /dev/null +++ b/start_pentest/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "start_pentest" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dirs = "5.0.1" + diff --git a/start_pentest/src/main.rs b/start_pentest/src/main.rs new file mode 100644 index 0000000..ec0c08b --- /dev/null +++ b/start_pentest/src/main.rs @@ -0,0 +1,384 @@ +/* +Auther: Pyro +Purpose: To automate setting up my notes at the start of a pentest project +Install Instructions: Change the "Pentest_notes" variable below to the directory you keep your pentest notes in. Then run cargo build to compile and copy the binary at ./target/debug/start_pentest to something like /usr/bin + +some special instructions for the file formats +the scope.txt file should be in the following format +host 3rd_party approval +example: +192.168.1.1 no yes +192.168.1.2 yes no +etc etc. + +*/ +use std::fs; +use std::env; +use std::fs::create_dir_all; +use std::io::Write; +use std::path::{Path, PathBuf}; +use dirs::home_dir; + +fn install(){ + let mut install_path: PathBuf = PathBuf::new(); + install_path.push(home_dir().expect("error getting home dir")); + install_path.push(".config/pyro_pentest_tools/"); + fs::create_dir_all(&install_path).expect("error creating config directory"); + install_path.push("start_pentest.conf"); + let mut conf_file = fs::File::create(install_path).expect("error creating config file"); + let mut project_folder_path = String::new(); + let mut porject_note_path = String::new(); + println!("path to the project folders directory?"); + std::io::stdin().read_line(&mut project_folder_path).expect("error reading project folder from stdin"); + println!("path to the project notes directory"); + std::io::stdin().read_line(&mut porject_note_path).expect("error reading project note folder form stdin"); + write!(conf_file, "project_folder_path:{} +project_notes_path:{} +", project_folder_path.trim_end(), porject_note_path.trim_end()).expect("error writing config file"); + std::process::exit(0); +} + + +fn external(project_folder_path: String,comapny_name: &String, project_name: &String, scope: Vec<&str>){ + let mut general_notes = fs::File::create(format!("{}/general.md", &project_folder_path)).expect("error creating general notes file"); + let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file"); + let mut host_notes = fs::File::create(format!("{}/host_notes.md", &project_folder_path)).expect("error creating host notes file"); + let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file"); + // for tagging + let year = project_name.split("_").collect::>()[1]; + let project_type = "External"; + writeln!(&mut general_notes, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing to general notes file"); + writeln!(&mut attack_notes, "#{} #{} #{} #attack", comapny_name, project_type, year).expect("error writing tags on attack notes"); + writeln!(&mut host_notes, "#{} #{} #{} #host_notes", comapny_name, project_type, year).expect("error writing tag lin in host notes"); + writeln!(&mut finding_notes, "#{} #{} #{} #findings", comapny_name, project_type, year).expect("error writing tag line on findings"); + writeln!(&mut general_notes, "# Scope").expect("error writing to general notes file"); + writeln!(&mut general_notes, "| IP | Third Party | Approval |").expect("error writing to general notes file"); + writeln!(&mut general_notes, "| -- | ----------- | -------- |").expect("error writing to general notes file"); + for address in &scope{ + if address.len() > 0{ + let address_vec: Vec<&str> = address.split(" ").collect(); + let address_line = format!("| {} | {} | {} |", address_vec[0], address_vec[1], address_vec[2]); + writeln!(&mut general_notes, "{}", address_line).expect("error writing to General Notes File"); + } +} +writeln!(&mut general_notes, "# PPC").expect("failed to write general notes"); +write!(&mut general_notes, " +Planning call notes: +* methodolgy +* whole month testing window +* start with a vuln scan in nessus pro +* pentesting execution standard framework +* info gathering +* recon +* exlpoitation +* reporting +* primary objective + * reasonable and expected protections are in place + * see if we can get access to the internal network + * if we do get inside + * reach out to the contact and see what they'd want us to know +* questions to ask +* custom objectives + * +* testing main website +* password attacks + * password sprays 3-12 hours + * lock out policy - + +## Enumeration in progress + +### DNS Bruteforcing +| domain name | IP | inscope? | +| ----------- | -- | -------- | + +# Attack Surface Enumeration +| IP | host notes | needs? | +| -- | ---------- | ------ |\n").expect("faile to write pentest notes"); + +// set up the basics for our attack notes +write!(&mut attack_notes," +# Directory Bruteforcing +- [ ] example.com + +---- + +# Login attacks +## examle.com/login +- [ ] stuffed +- [ ] sprayed +- [ ] bruteforced +- [ ] default + +---- + +# MSOLspray.py +passwords tried: +* password\n +" ).expect("failed to write attack notes template"); + +for host in scope{ +write!(&mut host_notes, " +# {} +Domain Name: +| port | service | attack_notes | +| ---- | ------- | ------------ | + +---- + + +", host).expect("faield to write host notes"); + write!(&mut finding_notes, " +# Critical + +# High + +# Medium + +# Low + +# informational + + ").expect("errror writing to findings for external"); + } +} + +fn internal(project_folder_path: String, comapny_name: &String, project_name: &String, scope: Vec<&str>){ + let loot_folder = format!("{}/l00t", project_folder_path); + create_dir_all(&loot_folder).expect("error creating loot directory"); + let mut general_notes = fs::File::create(format!("{}/general.md", &project_folder_path)).expect("error creating general notes file"); + let mut attack_notes = fs::File::create(format!("{}/attacks.md", &project_folder_path)).expect("error creating attack notes file"); + let mut finding_notes = fs::File::create(format!("{}/findings.md", &project_folder_path)).expect("error creating findings notes file"); + let mut systeminfo = fs::File::create(format!("{}/systeminfo", &project_folder_path)).expect("error creating systeminfo note file"); + let mut netsta = fs::File::create(format!("{}/netstat", &project_folder_path)).expect("error creating netstat file"); + let mut creds_notes = fs::File::create(format!("{}/creds.md", &loot_folder)).expect("error creating creds note"); + let mut todo_notes = fs::File::create(format!("{}/todo.md", &project_folder_path)).expect("error creating todo notes"); + let mut cleanup_notes = fs::File::create(format!("{}/cleanup.md", &project_folder_path)).expect("error creating cleanup notes"); + // for tagging notes + let oyear = project_name.split("_").collect::>()[0]; + let year = format!("year-{}", oyear); + let project_type = "Internal"; + writeln!(&mut creds_notes, "#{} #{} #{} #l00t #creds", comapny_name, project_type, year).expect("error writing creds notes"); + writeln!(&mut cleanup_notes, "#{} #{} #{} #cleanup", comapny_name, project_type, year).expect("error writing to cleanup notes"); + writeln!(&mut general_notes, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing to general notes file"); + writeln!(&mut attack_notes, "#{} #{} #{} #attack", comapny_name, project_type, year).expect("error writing attack note tags"); + writeln!(&mut todo_notes, "#{} #{} #{} #todo", comapny_name, project_type, year).expect("error writing tag line on todo"); + writeln!(&mut finding_notes, "#{} #{} #{} #findings", comapny_name, project_type, year).expect("error writing tags line on findings"); + writeln!(&mut systeminfo, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tag line for system info"); + writeln!(&mut netsta, "#{} #{} #{} #general", comapny_name, project_type, year).expect("error writing tagline in the netstat file"); + writeln!(&mut creds_notes, "| System | username | password |").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"); + writeln!(&mut general_notes, "# Scope\n").expect("error writing to general notes file"); + writeln!(&mut general_notes, "| IP | environment | inscope? |").expect("error writing to general notes file"); + writeln!(&mut general_notes, "| -- | ----------- | -------- |").expect("error writing to general notes file"); + for address in &scope{ + if address.len() > 0{ + let address_vec: Vec<&str> = address.split(" ").collect(); + let address_line = format!("| {}|{}|{} |", address_vec[0], address_vec[1], address_vec[2]); + writeln!(&mut general_notes, "{}", address_line).expect("error writing to General Notes File"); + } + } + let netstat_path = format!("{}/netstat", &project_folder_path); + let systeminfo_path = format!("{}/systeminfo", &project_folder_path); + write!(&mut general_notes, " +On the call: + +Introductions + Let them know that their primary contact will be the PM and there should be + +Go over general attack strategy/procedure. + We will get a beacon payload by the time the test starts + The beacon payload should be executed on a domain joined windows system. + If the system is not domain joined/no domain - let Seth know as this modifies the standard beacon + Select a user based on a department/role that they would like tested (Marketing, Sales, HR, IT) + This can be a test system with a cloned user, but then we don't get keylogging or screen grabs + The beacon is created using Cobalt Strike and communicates over HTTPS + Since Cobalt Strike is very well signatured, remind them that they may need to add an exclusion in antivirus and/or web filter + We will look at local privilege escalation, conduct portscans, password sprays, targeted vulnerability scanning (NOT NESSUS), lateral movement opportunities, and escalating to DOMAIN ADMIN privilege. + Ask if they want a focus on any particular assets. for example, an old time logging system, or remote access system. + +Ask if they have any questions or concerns + +Do they have a specific contact + +Email any follow-up items from the call to the PM +").expect("error writing PPC text"); + write!(&mut attack_notes," +# current dat (ex: 7/5) +Got Persistence via (schtasks, bat schtasks, startup folder) +``` +``` + +whoami /all +``` +``` + + +ipconfig /all +``` +``` + + +netstat -ano +[[{}|netstat]] + + +net accounts +``` +``` + + +net accounts /domain +``` +``` + + +net localgroup administrators +``` +``` + +Net group \"domain admins\" /domain +``` +``` + + +net share +``` +``` + + +net use +``` +``` + + +systeminfo +[[{}|systeminfo]] + + +powerup.ps1/sharpup.exe notes. +``` +``` + + ", netstat_path, systeminfo_path).expect("error writing to attack notes for internal tests"); + write!(&mut finding_notes, " +# normal findings + +# data exfil +## [Sarting Username] + + ").expect("error writing to findings notes on internal"); + write!(&mut todo_notes, " +- [ ] local checks +- [ ] find shares +- [ ] snaffle +- [ ] bloodhound +- [ ] admin or RDP? +- [ ] certify +- [ ] password spray +").expect("error writing todo list"); +write!(&mut netsta," +``` + +```").expect("error writing code block to system info"); +write!(&mut systeminfo," +``` + +```").expect("error writing code block to system info"); +} + +fn main() { + // change this to you own pentest notes folder + let mut pentest_notes = String::new(); + // change this where you store your files for writing pentests + let mut project_files = String::new(); + let args: Vec = env::args().collect(); + let usage = " +Welcome!! + +This tool uses a config file at ~/.config/pyro_pentesting/tools/start_pentest.conf +If this file does not exist configuration creation function will run promping you for the paths needed for this program to run. + +./start_pentest /path/to/scope.txt/file company_name project_name + +Please make sure the type of pentest is included in the project name, such as internal, external, or webapp(to be implemented) + +example: +start_pentest ./scope.txt victim_company_incorporated 2022_external_pentest + "; + let mut config_file_path_buf = PathBuf::new(); + config_file_path_buf.push(home_dir().expect("error reading home dir in main()")); + config_file_path_buf.push(".config/pyro_pentest_tools/start_pentest.conf"); + println!("checking installation status"); + if Path::new(&config_file_path_buf).exists(){ + println!("reading existing configuration file"); + } + else{ + println!("no existing installation found"); + install(); + } + let config_string = fs::read_to_string(config_file_path_buf).expect("error reading "); + if config_string.contains("folder_path") && config_string.contains("notes_path"){ + let config_string_vec: Vec<&str> = config_string.split("\n").collect(); + for line in config_string_vec{ + if line.contains("folder"){ + let line_vec: Vec<&str> = line.split(":").collect(); + project_files = line_vec[1].to_owned(); + } + else if line.contains("notes"){ + let line_vec: Vec<&str> = line.split(":").collect(); + pentest_notes = line_vec[1].to_owned(); + } + } + } + if args.len() == 4{ + // the following two lines make the scope a vector + let scope_content = fs::read_to_string(&args[1]).expect("Error reading scope file"); + let scope: Vec<&str> = scope_content.split("\n").collect(); + let company_name = &args[2]; + let project_name = &args[3]; + 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, scope); + } + 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, scope); + } + 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."); + } + } + + else{ + print!("{}", usage); + } + +} \ No newline at end of file