currently added some green for the initialization and red for errors, output color will be added soon!
437 lines
18 KiB
Rust
437 lines
18 KiB
Rust
use std::fs;
|
|
use std::fs::File;
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
use colored::Colorize;
|
|
|
|
use crate::Project;
|
|
use crate::project_controls;
|
|
use crate::get_user_input;
|
|
|
|
|
|
fn create_project_folder(path: &mut PathBuf, folder: &str){
|
|
path.push(folder);
|
|
let result = fs::create_dir_all(&path);
|
|
if result.is_err(){
|
|
println!("error creating {} directory!", folder);
|
|
}
|
|
else{
|
|
result.unwrap();
|
|
}
|
|
path.pop();
|
|
}
|
|
|
|
fn create_note_file(path: &PathBuf) -> Option<File>{
|
|
let result = fs::File::create(path);
|
|
if result.is_err(){
|
|
println!("error creating {} try manually!", path.display());
|
|
return None;
|
|
}
|
|
else{
|
|
let file = result.unwrap();
|
|
return Some(file);
|
|
}
|
|
}
|
|
|
|
fn external(passtemp: &PathBuf, project: &Project){
|
|
// using a pathbuf to create files.
|
|
let mut notes_path = project.notes_folder.clone();
|
|
let file_creation_res = fs::create_dir_all(¬es_path);
|
|
if file_creation_res.is_err(){
|
|
let error = file_creation_res.err().unwrap();
|
|
println!("{}","error creating notes folder!".red());
|
|
println!("{}", error.to_string().red())
|
|
}
|
|
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";
|
|
writeln!(&mut general_notes, "#{} #{} #general", project.customer, project_type).expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "# Scope").expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "\n| IP | Third Party | Approval |").expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "| -- | ----------- | -------- |").expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "# PPC").expect("failed to write general notes");
|
|
write!(&mut general_notes, "
|
|
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 -
|
|
|\n").expect("faile to write pentest notes");
|
|
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("attacks.md");
|
|
let attack_notes_result = create_note_file(¬es_path);
|
|
if attack_notes_result.is_some(){
|
|
let mut attack_notes = attack_notes_result.unwrap();
|
|
writeln!(&mut attack_notes, "#{} #{} #attack", project.customer, "external").expect("error writing tags on attack notes");
|
|
write!(&mut attack_notes,"
|
|
# Directory Bruteforcing
|
|
- [ ] example.com
|
|
|
|
----
|
|
|
|
# Login attacks
|
|
## examle.com/login
|
|
- [ ] stuffed
|
|
- [ ] sprayed
|
|
- [ ] bruteforced
|
|
- [ ] default
|
|
|
|
----
|
|
|
|
# MSOLspray.py
|
|
passwords tried:
|
|
* password\n
|
|
" ).expect("failed to write attack notes template");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("password_spray.md");
|
|
let pass_result = fs::copy(&passtemp, ¬es_path);
|
|
if pass_result.is_err(){
|
|
println!("error copying password spray file! try manually");
|
|
}
|
|
else{
|
|
pass_result.unwrap();
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("host_notes.md");
|
|
let host_notes_result = create_note_file(¬es_path);
|
|
if host_notes_result.is_some(){
|
|
let mut host_notes = host_notes_result.unwrap();
|
|
writeln!(&mut host_notes, "##{} #{} #host_notes", project.customer, "external").expect("error writing tag lin in host notes");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("findings.md");
|
|
let findings_notes_result = create_note_file(¬es_path);
|
|
if findings_notes_result.is_some(){
|
|
let mut finding_notes = findings_notes_result.unwrap();
|
|
writeln!(&mut finding_notes, "#{} #{} #findings", project.customer, "external").expect("error writing tag line on findings");
|
|
}
|
|
|
|
}
|
|
|
|
fn internal(passtemp: &PathBuf, project: &Project){
|
|
let mut notes_path = project.notes_folder.clone();
|
|
let file_creation_res = fs::create_dir_all(¬es_path);
|
|
if file_creation_res.is_err(){
|
|
let error = file_creation_res.err().unwrap();
|
|
println!("{}","error creating notes folder!".red());
|
|
println!("{}", error.to_string().red())
|
|
}
|
|
else{
|
|
file_creation_res.unwrap();
|
|
}
|
|
notes_path.push("password_spray.md");
|
|
println!("copying from {} to {}", passtemp.display(), ¬es_path.display());
|
|
let pass_result = fs::copy(&passtemp, ¬es_path);
|
|
if pass_result.is_err(){
|
|
let error = pass_result.err().unwrap();
|
|
println!("{}","error copying password spray file, try again manually!".red());
|
|
println!("{}", error.to_string().red())
|
|
}
|
|
else{
|
|
pass_result.unwrap();
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("l00t");
|
|
fs::create_dir_all(¬es_path).expect("error creating loot directory");
|
|
notes_path.push("creds.md");
|
|
let creds_notes_result = create_note_file(¬es_path);
|
|
if creds_notes_result.is_some(){
|
|
let mut creds_notes = creds_notes_result.unwrap();
|
|
writeln!(&mut creds_notes, "#{} #{} #l00t #creds", project.customer, "internal").expect("error writing creds notes");
|
|
writeln!(&mut creds_notes, "# CREDS").expect("error writing creds notes");
|
|
writeln!(&mut creds_notes, "\n| System | username | password |").expect("error writing creds notes");
|
|
writeln!(&mut creds_notes, "| ------ | -------- | -------- |").expect("error writing creds notes");
|
|
writeln!(&mut creds_notes, "\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, "| ---- | ---- | ---- |").expect("error writing creds notes");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.pop();
|
|
notes_path.push("general.md");
|
|
let general_result = create_note_file(¬es_path);
|
|
if general_result.is_some(){
|
|
let mut general_notes = general_result.unwrap();
|
|
writeln!(&mut general_notes, "#{} #{} #general", project.customer, "internal").expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "# Scope\n").expect("error writing to general notes file");
|
|
writeln!(&mut general_notes, "PASTE SCOPE FROM EXCELL HERE (THE EXCEL TO MARKDOWN TABLE PLUGIN WILL FORMAT FOR YOU").expect("shouldn't ever fail");
|
|
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.
|
|
|
|
Confirm On Prem AD vs NoAD or Azure AD
|
|
|
|
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");
|
|
}
|
|
notes_path.pop();
|
|
let enum_path = format!("{}/initial_enum.md", notes_path.display());
|
|
notes_path.push("attacks.md");
|
|
let attack_result = create_note_file(¬es_path);
|
|
if attack_result.is_some(){
|
|
let mut attack_notes = attack_result.unwrap();
|
|
writeln!(&mut attack_notes, "#{} #{} #attack", project.customer, "internal").expect("error writing attack note tags");
|
|
write!(&mut attack_notes,"
|
|
# current dat (ex: 7/5)
|
|
Got Persistence via (schtasks, bat schtasks, startup folder)
|
|
|
|
echo WHOAMI > initialenum.txt && echo ``` >> initialenum.txt && whoami /all >> initialenum.txt && echo ``` >> initialenum.txt && echo IPCONFIG >> initialenum.txt && echo ``` >> initialenum.txt && ipconfig /all >> initialenum.txt && echo ``` >> initialenum.txt && echo NETSTAT -ANO >> initialenum.txt && echo ``` >> initialenum.txt && netstat -ano >> initialenum.txt && echo ``` >> initialenum.txt && echo NET ACCOUNTS (LOCAL) >> initialenum.txt && echo ``` >> initialenum.txt && net accounts >> initialenum.txt && echo ``` >> initialenum.txt && echo NET ACCOUNTS (DOMAIN) >> initialenum.txt && echo ``` >> initialenum.txt && net accounts /domain >> initialenum.txt && echo ``` >> initialenum.txt && echo NET LOCALGROUP ADMINISTRATORS >> initialenum.txt && echo ``` >> initialenum.txt && net localgroup administrators >> initialenum.txt && echo ``` >> initialenum.txt && echo NET SHARE >> initialenum.txt && echo ``` >> initialenum.txt && net share >> initialenum.txt && echo ``` >> initialenum.txt && echo NET USE >> initialenum.txt && echo ``` >> initialenum.txt && net use >> initialenum.txt && echo ``` >> initialenum.txt && echo SYSTEMINFO >> initialenum.txt && echo ``` >> initialenum.txt && systeminfo >> initialenum.txt
|
|
|
|
|
|
whoami /all
|
|
![[{enum}#WHOAMI]]
|
|
|
|
|
|
ipconfig /all
|
|
![[{enum}#IPCONFIG]]
|
|
|
|
|
|
netstat -ano
|
|
[[{enum}#NETSTAT]]
|
|
|
|
|
|
net accounts
|
|
![[{enum}#NET ACCOUNTS]]
|
|
|
|
|
|
net accounts /domain
|
|
![[{enum}#NET ACCOUNTS DOMAIN]]
|
|
|
|
|
|
net localgroup administrators
|
|
![[{enum}#LOCAL ADMINS]]
|
|
|
|
Net group \"domain admins\" /domain
|
|
![[{enum}#DOMAIN ADMINS]]
|
|
|
|
|
|
net share
|
|
![[{enum}#NET SHARE]]
|
|
|
|
|
|
net use
|
|
![[{enum}#NET USE]]
|
|
|
|
|
|
systeminfo
|
|
[[{enum}#SYSTEMINFO]]
|
|
|
|
|
|
dsregcmd
|
|
[[{enum}#DSREGCMD]]
|
|
|
|
|
|
powerup.ps1/sharpup.exe notes.
|
|
|
|
|
|
|
|
|
|
", enum = enum_path).expect("error writing to attack notes for internal tests");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("findings.md");
|
|
let findings_result = create_note_file(¬es_path);
|
|
if findings_result.is_some(){
|
|
let mut finding_notes = findings_result.unwrap();
|
|
writeln!(&mut finding_notes, "#{} #{} #findings", project.customer, "internal").expect("error writing tags line on findings");
|
|
write!(&mut finding_notes, "
|
|
# normal findings
|
|
|
|
# data exfil
|
|
## [Sarting Username]
|
|
|
|
").expect("error writing to findings notes on internal");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("todo.md");
|
|
let todo_result = create_note_file(¬es_path);
|
|
if todo_result.is_some(){
|
|
let mut todo_notes = todo_result.unwrap();
|
|
writeln!(&mut todo_notes, "#{} #{} #todo", project.customer, "internal").expect("error writing tag line on todo");
|
|
write!(&mut todo_notes, "
|
|
|
|
- [ ] local checks
|
|
- [ ] find shares
|
|
- [ ] snaffle
|
|
- [ ] bloodhound
|
|
- [ ] admin or RDP?
|
|
- [ ] certify
|
|
- [ ] portscan
|
|
- [ ] sql stuff
|
|
- [ ] passwords in AD Descriptions?
|
|
- [ ] password spray
|
|
").expect("error writing todo list");
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("cleanup.md");
|
|
let cleanup_result = create_note_file(¬es_path);
|
|
if cleanup_result.is_some(){
|
|
let mut cleanup_notes = cleanup_result.unwrap();
|
|
writeln!(&mut cleanup_notes, "#{} #{} #cleanup", project.customer, "internal").expect("error writing to cleanup notes");
|
|
writeln!(&mut cleanup_notes, "- [ ] Breach machine C-temp-fr").expect("error writing to cleanup notes");
|
|
writeln!(&mut cleanup_notes, "- [ ] (continue to add as needed").expect("error writing ot cleanup notes");
|
|
}
|
|
}
|
|
|
|
|
|
fn vishing(project: &Project){
|
|
let mut notes_path = project.notes_folder.clone();
|
|
let mknote_folder_res = fs::create_dir_all(¬es_path);
|
|
if mknote_folder_res.is_err(){
|
|
let error = mknote_folder_res.err().unwrap();
|
|
println!("{}","Error creating notes folder!".red());
|
|
println!("{}", error.to_string().red());
|
|
return;
|
|
}
|
|
notes_path.push("general.md");
|
|
let general_notes_res = create_note_file(¬es_path);
|
|
if general_notes_res.is_some(){
|
|
let mut general_notes = general_notes_res.unwrap();
|
|
write!(general_notes, "# Scope\n\n").unwrap();
|
|
write!(general_notes, "
|
|
Introductions
|
|
|
|
have they been vished before?
|
|
if yes ask what the purpose of that vishing was, gain a foothold, or other?
|
|
|
|
ask the purpose of this test, just see if we can get creds or testing a vetting process, or any specific goals for the engagement.
|
|
|
|
four main aspects
|
|
1. verbal confirmation and verification of information
|
|
2. run commands on the system they're on
|
|
3. go to a specific website
|
|
4. join a screen sharing session with us
|
|
|
|
pretexts:
|
|
default is third party it.
|
|
they have 2 dudes for helpdesk so this may not be the best pretext. Try to impersonate a specific helpdesk user. impersonate William sounds like our plan.
|
|
|
|
Vector -
|
|
|
|
ask for any questions, comments, or concerns.
|
|
").unwrap();
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("findings.md");
|
|
let findings_res = create_note_file(¬es_path);
|
|
if findings_res.is_some(){
|
|
let mut findings_file = findings_res.unwrap();
|
|
write!(findings_file, "# Findings to write up\n\n\n# Delivery Notes\n").unwrap();
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("pretext.md");
|
|
let pretext_res = create_note_file(¬es_path);
|
|
if pretext_res.is_some(){
|
|
let mut pretext_file = pretext_res.unwrap();
|
|
write!(pretext_file, "\n\n\n#Script").unwrap();
|
|
write!(pretext_file, "
|
|
Hello I'm [name] from [Find Local IT Shop]. We were brought in to help your normal IT guys with some of the menial tasks so they can focus on more import improvement projects. As part of this we're making sure our inventory management system is checking in correctly and up to date, this should only take a minute or two. Is now bad time to talk?
|
|
|
|
Great I just need to confirm that my inventory report here is accurate.
|
|
|
|
Are you currently running Windows 11?
|
|
|
|
can you confirm your user name is [metadata username]?
|
|
|
|
Your primary browser is firfox?
|
|
|
|
Oh thats strange it seems our report is wrong then... I don't think our program on your computer is checking in correctly... uhhh I want to make sure you're getting all the windows updates we need to be compliant.
|
|
|
|
Hold the windows key on your keyboard and press the r button. in the box that opens up type cmd.exe and press enter.
|
|
|
|
This will open a scary black box, but don't worry I'll walk you through what we need here, it'll be pretty easy.
|
|
|
|
In that box type systemifo all one word and press enter.
|
|
|
|
Scroll up through that output and find the section that talks about hotfixes, how many are installed?
|
|
|
|
That doesn't seem like the right number to me, can you read me the last 3 that are listed there?
|
|
|
|
yeah you're definitely not getting all of the windows updates. This is going to take a bit of troubleshooting to figure out. Would you mind hopping in a Zoom call with me and sharing your screen so I can check a few things? This should only take a couple of minutes.
|
|
|
|
(open up the services manager and scroll through it, check some program files folders, and run a few commands in cmd to act like I'm troubleshooting.)
|
|
|
|
Hmmm everything looks ok on this end. I'm going to do some troubleshooting on the server side and see if we can get to the bottom of this. I don't think we'll need anything else from you to fix this, but if that changes I'll let you know. Thank you for your time.
|
|
").unwrap();
|
|
}
|
|
notes_path.pop();
|
|
notes_path.push("calls.md");
|
|
create_note_file(¬es_path);
|
|
}
|
|
|
|
pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, boxtemplate: &String, password_spray_file: &PathBuf) {
|
|
let mut project_files = upcoming_files.clone();
|
|
let mut project_notes = upcoming_notes.clone();
|
|
let customer_name = get_user_input("Customer name?");
|
|
let project_name = get_user_input("Project Name?");
|
|
project_files.push(&customer_name);
|
|
project_files.push(&project_name);
|
|
project_notes.push(&customer_name);
|
|
project_notes.push(&project_name);
|
|
println!("Files: {}\nNotes: {}\n\n", project_files.display(), project_notes.display());
|
|
let confirm_response = get_user_input("does this look ok?");
|
|
if confirm_response.to_lowercase().contains("n"){
|
|
println!("oof sorry");
|
|
return;
|
|
}
|
|
let mut working = project_files.clone();
|
|
create_project_folder(&mut working, "working");
|
|
create_project_folder(&mut working, "writing");
|
|
create_project_folder(&mut working, "delivery");
|
|
let project_boxname = format!("{}_{}", boxtemplate, customer_name);
|
|
let new_prject = Project{customer:customer_name.clone(), project_name:project_name.clone(), notes_folder:project_notes.clone(), files_folder:project_files.clone(),active:false, boxname:project_boxname.clone(),stage:"upcoming".to_owned(), id};
|
|
if project_name.to_lowercase().contains("external"){
|
|
external(password_spray_file, &new_prject);
|
|
}
|
|
else if project_name.to_lowercase().contains("internal"){
|
|
internal(password_spray_file, &new_prject);
|
|
}
|
|
else if project_name.to_lowercase().contains("vishing"){
|
|
vishing(&new_prject);
|
|
}
|
|
projects.push(new_prject);
|
|
project_controls::save_projects(projects, config_path);
|
|
println!("project created and saved to the projects config file!");
|
|
} |