Files
Linux-Server-Management-Too…/modules/security/malware-scanner.sh
T
cschantz ec1755b508 Improve ImunifyAV installation with better progress display
Changes:
- Show 'please wait' message for long installation
- Display installation progress from deployment script
- Clean up any existing deployment script first
- Show relevant output: Installing/Installed/Complete/Error
- Remove suppression of all output

This should make ImunifyAV installation more visible and debuggable.
2025-11-11 21:19:14 -05:00

1413 lines
44 KiB
Bash
Executable File

#!/bin/bash
################################################################################
# Malware Scanner
################################################################################
# Purpose: Comprehensive malware scanning with multiple engines
# Supports: ImunifyAV, ClamAV, Maldet (LMD)
# Scan scope: Single domain, user account, or entire server
################################################################################
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$SCRIPT_DIR/lib/common-functions.sh" 2>/dev/null || true
source "$SCRIPT_DIR/lib/system-detect.sh" 2>/dev/null || true
source "$SCRIPT_DIR/lib/user-manager.sh" 2>/dev/null || true
# Arrays for docroots and scanners
declare -a docroot_array
declare -a sanitized_docroot
declare -a remove_docroot
declare -a available_scanners
# Individual scanner detection functions
is_imunify_installed() {
command -v imunify-antivirus &>/dev/null || [ -f "/usr/bin/imunify-antivirus" ]
}
is_clamav_installed() {
command -v clamscan &>/dev/null || \
[ -f "/usr/local/cpanel/3rdparty/bin/clamscan" ] || \
rpm -qa | grep -q "cpanel-clamav"
}
is_maldet_installed() {
command -v maldet &>/dev/null || [ -f "/usr/local/sbin/maldet" ]
}
# Scanner detection
detect_scanners() {
available_scanners=()
if is_imunify_installed; then
available_scanners+=("imunify")
fi
if is_clamav_installed; then
available_scanners+=("clamav")
fi
if is_maldet_installed; then
available_scanners+=("maldet")
fi
if [ ${#available_scanners[@]} -eq 0 ]; then
echo -e "${RED}No malware scanners detected!${NC}"
echo ""
show_scanner_installation_guide
return 1
fi
return 0
}
# Show installation instructions for missing scanners
show_scanner_installation_guide() {
echo -e "${YELLOW}Available Malware Scanners:${NC}"
echo ""
# Check ImunifyAV
if ! is_imunify_installed; then
echo -e "${CYAN}ImunifyAV${NC} - FREE real-time malware scanner"
echo " Status: Not installed"
echo " Installation (cPanel):"
echo " yum install imunify-antivirus imunify-antivirus-cpanel"
echo " /opt/alt/python35/share/imunify360/scripts/av-userside-plugin.sh"
echo " Installation (script method):"
echo " wget https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh"
echo " bash imav-deploy.sh"
echo " Note: ImunifyAV is FREE. Imunify360 is the paid version."
echo " Docs: https://docs.imunify360.com/imunifyav/"
echo ""
else
echo -e "${GREEN}✓ ImunifyAV${NC} - Installed (FREE version)"
echo ""
fi
# Check ClamAV
if ! is_clamav_installed; then
echo -e "${CYAN}ClamAV${NC} - Open source antivirus engine"
echo " Status: Not installed"
echo " Installation (cPanel):"
echo " /scripts/update_local_rpm_versions --edit target_settings.clamav installed"
echo " /scripts/check_cpanel_rpms --fix --targets=clamav"
echo " Installation (manual):"
echo " yum install clamav clamav-update # RHEL/CentOS"
echo " apt-get install clamav clamav-daemon # Debian/Ubuntu"
echo " freshclam # Update virus definitions"
echo ""
else
echo -e "${GREEN}✓ ClamAV${NC} - Installed"
echo ""
fi
# Check Maldet
if ! is_maldet_installed; then
echo -e "${CYAN}Maldet (LMD)${NC} - Linux Malware Detect"
echo " Status: Not installed"
echo " Installation:"
echo " cd /tmp"
echo " wget http://www.rfxn.com/downloads/maldetect-current.tar.gz"
echo " tar -xzf maldetect-current.tar.gz"
echo " cd maldetect-*"
echo " ./install.sh"
echo " Docs: https://www.rfxn.com/projects/linux-malware-detect/"
echo ""
else
echo -e "${GREEN}✓ Maldet${NC} - Installed"
echo ""
fi
echo -e "${YELLOW}Recommendation:${NC} Install at least ClamAV (free) for basic scanning"
echo ""
}
# Install all scanners at once
install_all_scanners() {
echo ""
print_header "Install All Malware Scanners"
echo "This will install:"
echo " • ClamAV (free, open source)"
echo " • Maldet (free, Linux-specific)"
echo " • ImunifyAV (FREE version)"
echo ""
echo -e "${YELLOW}Note: ImunifyAV is FREE. Imunify360 is the paid version.${NC}"
echo ""
read -p "Proceed with installation? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Cancelled."
read -p "Press Enter to continue..."
return 0
fi
echo ""
echo "=========================================="
echo "Installing Scanners"
echo "=========================================="
echo ""
# Install ClamAV
if ! is_clamav_installed; then
echo -e "${CYAN}[1/3] Installing ClamAV...${NC}"
if [ -f "/usr/local/cpanel/cpanel" ]; then
# cPanel method - check if already installed but not configured
if rpm -qa | grep -q "cpanel-clamav"; then
echo -e "${GREEN}✓ ClamAV already installed (cPanel)${NC}"
else
/scripts/update_local_rpm_versions --edit target_settings.clamav installed 2>/dev/null
/scripts/check_cpanel_rpms --fix --targets=clamav 2>&1 | grep -E "Installing|Updating|up to date"
fi
elif command -v yum &>/dev/null; then
yum install -y clamav clamav-update 2>&1 | grep -E "Installing|Updating|already installed"
elif command -v apt-get &>/dev/null; then
apt-get update && apt-get install -y clamav clamav-daemon
fi
if is_clamav_installed; then
echo -e "${GREEN}✓ ClamAV installed${NC}"
# Find freshclam binary
local freshclam_bin=$(command -v freshclam || find /usr -name freshclam 2>/dev/null | head -1)
# Update virus signatures immediately
if [ -n "$freshclam_bin" ]; then
echo " → Updating virus signatures (this may take a moment)..."
$freshclam_bin 2>&1 | grep -E "updated|Downloaded|up-to-date" || $freshclam_bin &>/dev/null
echo -e " ${GREEN}${NC} Signatures updated"
fi
else
echo -e "${RED}✗ ClamAV installation failed${NC}"
fi
else
echo -e "${GREEN}✓ ClamAV already installed${NC}"
fi
echo ""
# Install Maldet
if ! is_maldet_installed; then
echo -e "${CYAN}[2/3] Installing Maldet...${NC}"
cd /tmp
wget -q http://www.rfxn.com/downloads/maldetect-current.tar.gz
if [ -f maldetect-current.tar.gz ]; then
tar -xzf maldetect-current.tar.gz
cd maldetect-* 2>/dev/null
./install.sh &>/dev/null
cd /tmp
rm -rf maldetect-*
fi
if is_maldet_installed; then
echo -e "${GREEN}✓ Maldet installed${NC}"
# Update malware signatures immediately
echo " → Updating malware signatures..."
maldet -u 2>&1 | grep -E "update completed|signatures" || maldet -u &>/dev/null
echo -e " ${GREEN}${NC} Signatures updated"
else
echo -e "${RED}✗ Maldet installation failed${NC}"
fi
else
echo -e "${GREEN}✓ Maldet already installed${NC}"
fi
echo ""
# Install ImunifyAV (FREE version)
if ! is_imunify_installed; then
echo -e "${CYAN}[3/3] Installing ImunifyAV (FREE)...${NC}"
echo " This may take several minutes - please wait..."
# Use deployment script method (most reliable)
cd /tmp
if [ -f "imav-deploy.sh" ]; then
rm -f imav-deploy.sh
fi
wget -q https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh
if [ -f imav-deploy.sh ]; then
# Run deployment script with progress indicators
bash imav-deploy.sh 2>&1 | grep -E "Installing|Installed|Complete|Error|Failed" || bash imav-deploy.sh
rm -f imav-deploy.sh
# Enable cPanel UI plugin if installed
if [ -f "/opt/alt/python35/share/imunify360/scripts/av-userside-plugin.sh" ]; then
echo " → Enabling cPanel UI plugin..."
/opt/alt/python35/share/imunify360/scripts/av-userside-plugin.sh &>/dev/null
fi
else
echo -e "${RED} Failed to download installation script${NC}"
fi
if is_imunify_installed; then
echo -e "${GREEN}✓ ImunifyAV (FREE) installed${NC}"
echo " No license key required - this is the FREE version"
# Find imunify-antivirus binary
local imunify_bin=$(command -v imunify-antivirus || find /usr -name imunify-antivirus 2>/dev/null | head -1)
# Update malware signatures immediately
if [ -n "$imunify_bin" ]; then
echo " → Updating malware signatures..."
$imunify_bin update 2>&1 | grep -E "updated|Success|completed" || $imunify_bin update &>/dev/null
echo -e " ${GREEN}${NC} Signatures updated"
fi
else
echo -e "${RED}✗ ImunifyAV installation failed${NC}"
fi
else
echo -e "${GREEN}✓ ImunifyAV already installed${NC}"
fi
echo ""
echo "=========================================="
echo "Installation Complete"
echo "=========================================="
echo ""
# Re-detect scanners
detect_scanners
echo ""
read -p "Press Enter to continue..."
}
# Detect control panel and gather docroots
detect_control_panel() {
docroot_array=()
# Detect cPanel
if [ -f "/etc/userdatadomains" ]; then
CONTROL_PANEL="cpanel"
export PATH=/usr/local/cpanel/3rdparty/bin/:$PATH
while IFS= read -r docroot; do
[ -n "$docroot" ] && docroot_array+=("$docroot")
done < <(cut -d= -f5 /etc/userdatadomains | sed 's/==/=/g' | sort -u)
# Detect Plesk
elif [ -f "/usr/local/psa/version" ]; then
CONTROL_PANEL="plesk"
while IFS= read -r domain; do
docroot=$(plesk bin site -i "$domain" 2>/dev/null | grep "WWW-Root" | awk '{print $2}')
[ -n "$docroot" ] && docroot_array+=("$docroot")
done < <(plesk bin site --list 2>/dev/null)
# Detect Interworx
elif [ -d "/usr/local/interworx/" ]; then
CONTROL_PANEL="interworx"
while IFS= read -r docroot; do
[ -n "$docroot" ] && docroot_array+=("$docroot")
done < <(grep -rh "DocumentRoot" /etc/httpd/conf* 2>/dev/null | grep -Ev '^\s*#|/var/www/html($|$)' | sed 's/DocumentRoot//g' | tr -d " " | sort -u)
else
CONTROL_PANEL="none"
echo -e "${YELLOW}No control panel detected${NC}"
echo "Manual path selection required"
return 1
fi
# Remove subdirectory docroots (avoid scanning same files twice)
sanitize_docroots
return 0
}
# Remove subdirectory docroots from array
sanitize_docroots() {
remove_docroot=()
for search_value in "${docroot_array[@]}"; do
# Count how many paths contain this value
count=$(printf '%s\n' "${docroot_array[@]}" | grep -c "$search_value" || true)
if [ "$count" -gt 1 ]; then
# Find subdirectories and mark for removal
while IFS= read -r subdir; do
if [ "$subdir" != "$search_value" ]; then
remove_docroot+=("$subdir")
fi
done < <(printf '%s\n' "${docroot_array[@]}" | grep "$search_value")
fi
done
# Build sanitized array
sanitized_docroot=()
for docroot in "${docroot_array[@]}"; do
# Check if this docroot is in remove list
skip=0
for remove in "${remove_docroot[@]}"; do
if [ "$docroot" = "$remove" ]; then
skip=1
break
fi
done
if [ $skip -eq 0 ]; then
sanitized_docroot+=("$docroot")
fi
done
}
# Get docroots for specific user
get_user_docroots() {
local username="$1"
local user_docroots=()
if [ "$CONTROL_PANEL" = "cpanel" ]; then
while IFS= read -r docroot; do
[ -n "$docroot" ] && user_docroots+=("$docroot")
done < <(grep "^${username}:" /etc/userdatadomains | cut -d= -f5 | sed 's/==/=/g' | sort -u)
else
echo -e "${RED}User-specific scanning only supported on cPanel${NC}"
return 1
fi
echo "${user_docroots[@]}"
}
# Get docroot for specific domain
get_domain_docroot() {
local domain="$1"
local domain_docroot=""
if [ "$CONTROL_PANEL" = "cpanel" ]; then
domain_docroot=$(grep "^${domain}:" /etc/userdatadomains | cut -d= -f5 | sed 's/==/=/g')
elif [ "$CONTROL_PANEL" = "plesk" ]; then
domain_docroot=$(plesk bin site -i "$domain" 2>/dev/null | grep "WWW-Root" | awk '{print $2}')
else
echo -e "${RED}Domain lookup only supported on cPanel/Plesk${NC}"
return 1
fi
echo "$domain_docroot"
}
# Memory check before scanning
check_memory() {
local total_mem=$(free -m | awk '/^Mem:/{print $2}')
local avail_mem=$(free -m | awk '/^Mem:/{print $7}')
local min_total=2048 # 2GB
local min_avail=512 # 512MB
if [ "$total_mem" -lt "$min_total" ] || [ "$avail_mem" -lt "$min_avail" ]; then
echo -e "${YELLOW}WARNING: Low memory detected${NC}"
echo "Total: ${total_mem}MB | Available: ${avail_mem}MB"
echo ""
echo "Running a full scan may cause high load or OOM conditions."
echo ""
read -p "Continue anyway? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Scan cancelled"
return 1
fi
fi
return 0
}
# ImunifyAV scanner
# Generate standalone malware scan script
generate_standalone_scanner() {
local scan_paths=("$@")
if [ ${#scan_paths[@]} -eq 0 ]; then
echo -e "${RED}No paths to scan${NC}"
return 1
fi
# Create session ID and directory
local session_id="malware-$(date +%Y%m%d-%H%M%S)"
local session_dir="/opt/${session_id}"
echo ""
print_header "Generating Standalone Scanner"
echo "Session ID: $session_id"
echo "Location: $session_dir"
echo ""
# Create directory structure
mkdir -p "$session_dir"/{logs,results}
# Create standalone scan script
cat > "$session_dir/scan.sh" << 'STANDALONE_EOF'
#!/bin/bash
################################################################################
# Standalone Malware Scanner
################################################################################
# Auto-generated by Server Management Toolkit
# This script is self-contained and can run independently
################################################################################
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
# Get script directory
SCAN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="$SCAN_DIR/logs"
RESULTS_DIR="$SCAN_DIR/results"
# Session info
SESSION_LOG="$LOG_DIR/session.log"
SUMMARY_FILE="$RESULTS_DIR/summary.txt"
INFECTED_LIST="$RESULTS_DIR/infected_files.txt"
# Logging function
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$SESSION_LOG"
}
# Banner
clear
echo "========================================"
echo "Standalone Malware Scanner"
echo "========================================"
echo "Session: $(basename $SCAN_DIR)"
echo "Started: $(date)"
echo "========================================"
echo ""
log_message "Scan session started"
# Detect available scanners
AVAILABLE_SCANNERS=()
if command -v imunify-antivirus &>/dev/null; then
AVAILABLE_SCANNERS+=("imunify")
log_message "Detected: ImunifyAV"
fi
if command -v clamscan &>/dev/null; then
AVAILABLE_SCANNERS+=("clamav")
log_message "Detected: ClamAV"
fi
if command -v maldet &>/dev/null; then
AVAILABLE_SCANNERS+=("maldet")
log_message "Detected: Maldet"
fi
if [ ${#AVAILABLE_SCANNERS[@]} -eq 0 ]; then
log_message "ERROR: No scanners found!"
echo -e "${RED}No malware scanners detected!${NC}"
exit 1
fi
log_message "Found ${#AVAILABLE_SCANNERS[@]} scanner(s): ${AVAILABLE_SCANNERS[*]}"
# Scan paths (will be replaced)
SCAN_PATHS=()
PLACEHOLDER_SCAN_PATHS
log_message "Scanning ${#SCAN_PATHS[@]} path(s)"
# Initialize summary
{
echo "=========================================="
echo "Malware Scan Summary Report"
echo "=========================================="
echo "Session: $(basename $SCAN_DIR)"
echo "Started: $(date)"
echo "Scanners: ${AVAILABLE_SCANNERS[*]}"
echo "Paths: ${#SCAN_PATHS[@]}"
echo ""
printf '%s\n' "${SCAN_PATHS[@]}"
echo ""
echo "=========================================="
echo ""
} > "$SUMMARY_FILE"
# Track completion
SCANNERS_COMPLETED=0
TOTAL_SCANNERS=${#AVAILABLE_SCANNERS[@]}
# Run each scanner
for scanner in "${AVAILABLE_SCANNERS[@]}"; do
SCANNER_NUM=$((SCANNERS_COMPLETED + 1))
echo ""
echo -e "${CYAN}[$SCANNER_NUM/$TOTAL_SCANNERS] Starting ${scanner^} scan...${NC}"
log_message "Starting ${scanner} scan"
{
echo "Scanner: ${scanner^}"
echo "Started: $(date)"
echo "---"
} >> "$SUMMARY_FILE"
case "$scanner" in
imunify)
log_message "ImunifyAV: Updating signatures"
imunify-antivirus update &>> "$LOG_DIR/imunify.log"
for path in "${SCAN_PATHS[@]}"; do
if [ -d "$path" ]; then
log_message "ImunifyAV: Queuing $path"
imunify-antivirus malware on-demand queue put "$path" &>> "$LOG_DIR/imunify.log"
fi
done
echo "✓ ImunifyAV scans queued" | tee -a "$SUMMARY_FILE"
log_message "ImunifyAV: Scans queued successfully"
;;
clamav)
if command -v freshclam &>/dev/null; then
log_message "ClamAV: Updating signatures"
freshclam &>> "$LOG_DIR/clamav.log"
fi
log_message "ClamAV: Starting scan"
clamscan --infected --recursive "${SCAN_PATHS[@]}" &>> "$LOG_DIR/clamav.log"
# Extract infected files
grep "FOUND" "$LOG_DIR/clamav.log" | cut -d: -f1 >> "$INFECTED_LIST" 2>/dev/null
CLAM_INFECTED=$(grep -c "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null || echo 0)
echo "✓ ClamAV scan complete - Found: $CLAM_INFECTED" | tee -a "$SUMMARY_FILE"
log_message "ClamAV: Scan complete - $CLAM_INFECTED infected files"
;;
maldet)
log_message "Maldet: Updating signatures"
maldet -u &>> "$LOG_DIR/maldet.log"
# Create temp path list
TEMP_PATHLIST="/tmp/maldet_paths_$$.txt"
printf '%s\n' "${SCAN_PATHS[@]}" > "$TEMP_PATHLIST"
log_message "Maldet: Starting scan"
maldet -b -f "$TEMP_PATHLIST" &>> "$LOG_DIR/maldet.log"
rm -f "$TEMP_PATHLIST"
echo "✓ Maldet scan complete" | tee -a "$SUMMARY_FILE"
log_message "Maldet: Scan complete"
;;
esac
echo "" | tee -a "$SUMMARY_FILE"
((SCANNERS_COMPLETED++))
# Wait between scanners
if [ $SCANNERS_COMPLETED -lt $TOTAL_SCANNERS ]; then
echo "Waiting 3 seconds before next scanner..."
sleep 3
fi
done
# Finalize report
{
echo "=========================================="
echo "Scan Session Complete"
echo "Completed: $(date)"
echo "=========================================="
echo ""
if [ -f "$INFECTED_LIST" ] && [ -s "$INFECTED_LIST" ]; then
echo "INFECTED FILES DETECTED:"
echo ""
sort -u "$INFECTED_LIST"
else
echo "No infected files detected by automated scan."
echo "Review individual scanner logs for details."
fi
} >> "$SUMMARY_FILE"
log_message "All scans completed successfully"
# Display completion
clear
echo "=========================================="
echo -e "${GREEN}Malware Scan Complete!${NC}"
echo "=========================================="
echo "Session: $(basename $SCAN_DIR)"
echo "Completed: $(date)"
echo ""
echo "Results saved to:"
echo " Summary: $SUMMARY_FILE"
echo " Logs: $LOG_DIR/"
echo ""
# Show summary
cat "$SUMMARY_FILE"
echo ""
echo "=========================================="
echo ""
# Prompt for cleanup
read -p "Delete scan directory and all results? (yes/no): " cleanup_choice
if [ "$cleanup_choice" = "yes" ]; then
log_message "User requested cleanup - deleting scan directory"
echo ""
echo "Removing scan directory..."
cd /
rm -rf "$SCAN_DIR"
echo -e "${GREEN}✓ Scan directory deleted${NC}"
echo ""
echo "This screen session will now close."
sleep 2
else
log_message "User chose to keep results"
echo ""
echo "Results preserved at: $SCAN_DIR"
echo ""
echo "You can:"
echo " • Review logs: ls $LOG_DIR"
echo " • View summary: cat $SUMMARY_FILE"
echo " • Delete manually: rm -rf $SCAN_DIR"
echo ""
echo "Press Ctrl+A then D to detach from this screen session"
echo ""
fi
log_message "Scan session ended"
STANDALONE_EOF
# Replace placeholder with actual paths
local paths_declaration="SCAN_PATHS=("
for path in "${scan_paths[@]}"; do
paths_declaration+="\"$path\" "
done
paths_declaration+=")"
sed -i "s|PLACEHOLDER_SCAN_PATHS|$paths_declaration|" "$session_dir/scan.sh"
# Make executable
chmod +x "$session_dir/scan.sh"
# Check if screen is installed
if ! command -v screen &>/dev/null; then
echo -e "${YELLOW}Warning: 'screen' not installed${NC}"
echo ""
echo "Screen allows you to detach from the scan session."
echo ""
echo "Options:"
echo " 1. Auto-install screen (recommended)"
echo " 2. Use nohup fallback (run in background without screen)"
echo " 3. Cancel"
echo ""
read -p "Select option: " screen_option
case "$screen_option" in
1)
echo ""
echo "Installing screen..."
if command -v yum &>/dev/null; then
yum install -y screen
elif command -v apt-get &>/dev/null; then
apt-get update && apt-get install -y screen
else
echo -e "${RED}Unable to auto-install. Install manually: yum install screen${NC}"
read -p "Press Enter to continue..."
return 1
fi
if ! command -v screen &>/dev/null; then
echo -e "${RED}Installation failed${NC}"
read -p "Press Enter to continue..."
return 1
fi
echo -e "${GREEN}✓ Screen installed successfully${NC}"
echo ""
;;
2)
# Use nohup fallback
echo ""
echo "Launching scan with nohup (background mode)..."
nohup bash "$session_dir/scan.sh" > "$session_dir/logs/nohup.out" 2>&1 &
local scan_pid=$!
sleep 1
if ps -p $scan_pid > /dev/null 2>&1; then
echo ""
echo -e "${GREEN}✓ Standalone scanner started successfully!${NC}"
echo ""
echo "Session ID: $session_id"
echo "Process ID: $scan_pid"
echo "Results directory: $session_dir/results/"
echo ""
echo -e "${CYAN}Monitor the scan:${NC}"
echo " tail -f $session_dir/logs/session.log"
echo ""
echo -e "${CYAN}Check if still running:${NC}"
echo " ps -p $scan_pid"
echo ""
echo -e "${GREEN}You can now safely delete the toolkit.${NC}"
echo -e "${GREEN}The scan will continue running independently.${NC}"
echo ""
# Store session info in reference database
store_reference "malware_standalone_latest" "$session_id"
store_reference "malware_standalone_${session_id}_dir" "$session_dir"
store_reference "malware_standalone_${session_id}_pid" "$scan_pid"
read -p "Press Enter to continue..."
return 0
else
echo -e "${RED}Failed to start scan${NC}"
echo "Run manually: bash $session_dir/scan.sh"
read -p "Press Enter to continue..."
return 1
fi
;;
3)
echo "Cancelled."
read -p "Press Enter to continue..."
return 0
;;
*)
echo -e "${RED}Invalid option${NC}"
read -p "Press Enter to continue..."
return 1
;;
esac
fi
# Launch in screen session
echo "Launching scan in screen session..."
screen -dmS "$session_id" bash "$session_dir/scan.sh"
sleep 1
# Verify screen started
if screen -list | grep -q "$session_id"; then
echo ""
echo -e "${GREEN}✓ Standalone scanner started successfully!${NC}"
echo ""
echo "Session ID: $session_id"
echo "Screen session: $session_id"
echo "Results directory: $session_dir/results/"
echo ""
echo -e "${CYAN}Monitor the scan:${NC}"
echo " screen -r $session_id"
echo ""
echo -e "${CYAN}Check progress:${NC}"
echo " tail -f $session_dir/logs/session.log"
echo ""
echo -e "${CYAN}Detach from screen:${NC}"
echo " Press: Ctrl+A then D"
echo ""
echo -e "${GREEN}You can now safely delete the toolkit.${NC}"
echo -e "${GREEN}The scan will continue running independently.${NC}"
echo ""
# Store session info in reference database
store_reference "malware_standalone_latest" "$session_id"
store_reference "malware_standalone_${session_id}_dir" "$session_dir"
else
echo -e "${RED}Failed to start screen session${NC}"
echo "Run manually: bash $session_dir/scan.sh"
fi
read -p "Press Enter to continue..."
}
# Compare results from multiple scanners
compare_scan_results() {
echo ""
print_header "Compare Scanner Results"
# Get latest multiscan session
local latest_session=$(get_reference "malware_multiscan_latest")
if [ -z "$latest_session" ]; then
echo "No multi-scanner sessions found."
echo ""
echo "Run a scan with 'All Available Scanners' option first."
read -p "Press Enter to continue..."
return
fi
local report_file=$(get_reference "malware_multiscan_${latest_session}")
if [ -f "$report_file" ]; then
echo "Latest multi-scanner session: $latest_session"
echo ""
less "$report_file"
else
echo "Report file not found: $report_file"
fi
echo ""
read -p "Press Enter to continue..."
}
# Launch standalone scanner menu
launch_standalone_scanner_menu() {
local preset_scope="$1" # Optional: server, user, domain, custom
echo ""
print_header "Launch Standalone Scanner"
echo "This will create a self-contained scanner in /opt/ that runs"
echo "independently. You can safely delete the toolkit after launching."
echo ""
if ! detect_control_panel; then
read -p "Press Enter to continue..."
return 1
fi
echo "Control Panel: ${CONTROL_PANEL^}"
echo "Available Scanners: ${available_scanners[*]}"
echo ""
local scope_choice
local scan_paths=()
local scan_description=""
# If preset scope provided, use it; otherwise show menu
if [ -n "$preset_scope" ]; then
case "$preset_scope" in
server) scope_choice=1 ;;
user) scope_choice=2 ;;
domain) scope_choice=3 ;;
custom) scope_choice=4 ;;
*) scope_choice=0 ;;
esac
else
echo "Select scan scope:"
echo " 1. Entire server (all docroots)"
echo " 2. Specific user account"
echo " 3. Specific domain"
echo " 4. Custom path"
echo " 0. Cancel"
echo ""
read -p "Select option: " scope_choice
fi
case $scope_choice in
1)
# Entire server
scan_paths=("${sanitized_docroot[@]}")
scan_description="full server scan"
if [ ${#scan_paths[@]} -eq 0 ]; then
echo -e "${RED}No docroots found!${NC}"
read -p "Press Enter to continue..."
return 1
fi
echo ""
echo "Scan paths: ${#scan_paths[@]} docroots"
;;
2)
# Specific user
echo ""
echo "Available users:"
select_user_interactive "Select user account to scan"
if [ -z "$SELECTED_USER" ]; then
echo "No user selected."
read -p "Press Enter to continue..."
return 1
fi
# Get user's docroots
for docroot in "${sanitized_docroot[@]}"; do
if [[ "$docroot" == *"/$SELECTED_USER/"* ]]; then
scan_paths+=("$docroot")
fi
done
if [ ${#scan_paths[@]} -eq 0 ]; then
echo -e "${RED}No docroots found for user: $SELECTED_USER${NC}"
read -p "Press Enter to continue..."
return 1
fi
scan_description="user $SELECTED_USER"
echo "Found ${#scan_paths[@]} docroots for $SELECTED_USER"
;;
3)
# Specific domain
echo ""
read -p "Enter domain name: " domain
if [ -z "$domain" ]; then
echo "No domain entered."
read -p "Press Enter to continue..."
return 1
fi
# Find docroot for domain
for docroot in "${sanitized_docroot[@]}"; do
if [[ "$docroot" == *"/$domain"* ]] || [[ "$docroot" == *"/$domain/"* ]]; then
scan_paths+=("$docroot")
fi
done
if [ ${#scan_paths[@]} -eq 0 ]; then
echo -e "${RED}No docroot found for domain: $domain${NC}"
read -p "Press Enter to continue..."
return 1
fi
scan_description="domain $domain"
echo "Found docroot: ${scan_paths[0]}"
;;
4)
# Custom path
echo ""
read -p "Enter path to scan: " custom_path
if [ -z "$custom_path" ]; then
echo "No path entered."
read -p "Press Enter to continue..."
return 1
fi
if [ ! -d "$custom_path" ]; then
echo -e "${RED}Path does not exist: $custom_path${NC}"
read -p "Press Enter to continue..."
return 1
fi
scan_paths=("$custom_path")
scan_description="custom path $custom_path"
;;
0)
return 0
;;
*)
echo -e "${RED}Invalid option${NC}"
sleep 1
return 1
;;
esac
# Confirm before generating
echo ""
echo -e "${YELLOW}Ready to generate standalone scanner${NC}"
echo "Scope: $scan_description"
echo "Paths: ${#scan_paths[@]}"
echo "Scanners: ${available_scanners[*]}"
echo ""
read -p "Generate and launch? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Cancelled."
read -p "Press Enter to continue..."
return 0
fi
# Generate and launch standalone scanner
generate_standalone_scanner "${scan_paths[@]}"
}
# Check status of all standalone scanners
check_standalone_status() {
echo ""
print_header "Standalone Scanner Status"
# Find all malware-* directories in /opt
local standalone_dirs=($(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r))
if [ ${#standalone_dirs[@]} -eq 0 ]; then
echo "No standalone scanner sessions found."
echo ""
read -p "Press Enter to continue..."
return 0
fi
echo "Active Sessions:"
echo ""
local running_count=0
local completed_count=0
local error_count=0
for dir in "${standalone_dirs[@]}"; do
local session_name=$(basename "$dir")
# Check if still running
if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
echo -e " ${GREEN}${NC} $session_name [RUNNING]"
((running_count++))
# Show progress if available
if [ -f "$dir/logs/session.log" ]; then
local last_log=$(tail -1 "$dir/logs/session.log" 2>/dev/null)
echo " Latest: $last_log"
fi
elif [ -f "$dir/results/summary.txt" ]; then
# Check if completed successfully
if grep -q "Multi-Scanner Session Complete\|Scan session ended" "$dir/results/summary.txt" 2>/dev/null; then
echo -e " ${CYAN}${NC} $session_name [COMPLETED]"
((completed_count++))
# Show infected count if available
if [ -f "$dir/results/infected_files.txt" ] && [ -s "$dir/results/infected_files.txt" ]; then
local infected_count=$(wc -l < "$dir/results/infected_files.txt")
echo -e " Found: ${RED}$infected_count infected files${NC}"
fi
else
echo -e " ${RED}${NC} $session_name [ERROR/INCOMPLETE]"
((error_count++))
fi
else
echo -e " ${YELLOW}?${NC} $session_name [UNKNOWN - no results yet]"
fi
echo ""
done
echo "Summary:"
echo " Running: $running_count"
echo " Completed: $completed_count"
echo " Errors: $error_count"
echo " Total: ${#standalone_dirs[@]}"
echo ""
read -p "Press Enter to continue..."
}
# Delete standalone scanner sessions
delete_standalone_sessions() {
echo ""
print_header "Delete Standalone Scanner Sessions"
# Find all malware-* directories in /opt
local standalone_dirs=($(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r))
if [ ${#standalone_dirs[@]} -eq 0 ]; then
echo "No standalone scanner sessions found."
echo ""
read -p "Press Enter to continue..."
return 0
fi
echo "Available sessions:"
echo ""
# List sessions with status
local i=1
for dir in "${standalone_dirs[@]}"; do
local session_name=$(basename "$dir")
local status="completed"
if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
status="${GREEN}running${NC}"
fi
echo -e " $i. $session_name [$status]"
((i++))
done
echo ""
echo " A. Delete all completed sessions"
echo " 0. Cancel"
echo ""
read -p "Select session to delete (or A for all completed): " delete_choice
case "$delete_choice" in
0)
return 0
;;
[Aa])
# Delete all completed sessions
echo ""
local deleted=0
for dir in "${standalone_dirs[@]}"; do
if ! pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
echo "Deleting: $(basename $dir)"
rm -rf "$dir"
((deleted++))
fi
done
echo ""
echo -e "${GREEN}✓ Deleted $deleted completed session(s)${NC}"
;;
*)
# Delete specific session
if [ "$delete_choice" -lt 1 ] || [ "$delete_choice" -gt ${#standalone_dirs[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
fi
local selected_dir="${standalone_dirs[$((delete_choice-1))]}"
local session_name=$(basename "$selected_dir")
# Check if running
if pgrep -f "$selected_dir/scan.sh" > /dev/null 2>&1; then
echo ""
echo -e "${YELLOW}Warning: This scan is currently running!${NC}"
read -p "Stop scan and delete? (yes/no): " confirm_running
if [ "$confirm_running" = "yes" ]; then
pkill -f "$selected_dir/scan.sh"
sleep 1
rm -rf "$selected_dir"
echo -e "${GREEN}✓ Stopped and deleted: $session_name${NC}"
else
echo "Cancelled."
fi
else
echo ""
read -p "Delete $session_name? (yes/no): " confirm_delete
if [ "$confirm_delete" = "yes" ]; then
rm -rf "$selected_dir"
echo -e "${GREEN}✓ Deleted: $session_name${NC}"
else
echo "Cancelled."
fi
fi
;;
esac
echo ""
read -p "Press Enter to continue..."
}
# Main scan menu
show_scan_menu() {
while true; do
print_banner "Malware Scanner"
echo "Available Scanners:"
for scanner in "${available_scanners[@]}"; do
echo "${scanner^}"
done
echo ""
echo -e "${CYAN}Create New Scan:${NC}"
echo " 1. Scan entire server"
echo " 2. Scan specific user"
echo " 3. Scan specific domain"
echo " 4. Scan custom path"
echo ""
echo -e "${CYAN}Monitor & Manage:${NC}"
echo " 5. Check scan status"
echo " 6. View scan results"
echo " 7. Delete scan sessions"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo " 8. Install all scanners"
echo " 9. Scanner settings"
echo ""
echo " 0. Back to main menu"
echo ""
read -p "Select option: " choice
case $choice in
1) launch_standalone_scanner_menu "server" ;;
2) launch_standalone_scanner_menu "user" ;;
3) launch_standalone_scanner_menu "domain" ;;
4) launch_standalone_scanner_menu "custom" ;;
5) check_standalone_status ;;
6) view_scan_results ;;
7) delete_standalone_sessions ;;
8) install_all_scanners ;;
9) scanner_settings ;;
0) return 0 ;;
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
esac
done
}
# View scan results
view_scan_results() {
echo ""
print_header "Scan Results"
echo "Select results to view:"
echo " 1. Toolkit scan results"
echo " 2. Standalone scanner results (/opt)"
echo " 0. Back"
echo ""
read -p "Option: " result_type
case "$result_type" in
1)
# Toolkit scan results
echo ""
echo "Select scanner to view results:"
local i=1
for scanner in "${available_scanners[@]}"; do
echo " $i. ${scanner^}"
((i++))
done
echo ""
read -p "Scanner: " scanner_choice
if [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
fi
local selected_scanner="${available_scanners[$((scanner_choice-1))]}"
echo ""
case "$selected_scanner" in
imunify)
echo "Recent ImunifyAV scans:"
imunify-antivirus malware on-demand list --since $(date --date="7 days ago" '+%s') 2>/dev/null || echo "No scans found"
;;
clamav)
echo "Recent ClamAV scans:"
find "$SCRIPT_DIR/logs/malware-scans" -name "clamav_*.log" -mtime -7 2>/dev/null | sort -r | head -5 || echo "No scans found"
;;
maldet)
echo "Recent Maldet scans:"
maldet -l 2>/dev/null || echo "No scans found"
;;
esac
;;
2)
# Standalone scanner results
echo ""
echo "Standalone scanner sessions:"
echo ""
# Find all malware-* directories in /opt
local standalone_dirs=($(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r))
if [ ${#standalone_dirs[@]} -eq 0 ]; then
echo "No standalone scanner sessions found in /opt"
echo ""
read -p "Press Enter to continue..."
return 0
fi
# List sessions
local i=1
for dir in "${standalone_dirs[@]}"; do
local session_name=$(basename "$dir")
local scan_date=$(echo "$session_name" | sed 's/malware-//')
# Check if still running
local status="completed"
if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
status="running"
fi
echo " $i. $session_name [$status]"
((i++))
done
echo ""
read -p "Select session (or 0 to cancel): " session_choice
if [ "$session_choice" = "0" ]; then
return 0
fi
if [ "$session_choice" -lt 1 ] || [ "$session_choice" -gt ${#standalone_dirs[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
fi
local selected_dir="${standalone_dirs[$((session_choice-1))]}"
echo ""
echo "Session: $(basename $selected_dir)"
echo "Location: $selected_dir"
echo ""
# Show results
if [ -f "$selected_dir/results/summary.txt" ]; then
echo "=== Summary ==="
cat "$selected_dir/results/summary.txt"
echo ""
else
echo "Summary not yet available (scan may still be running)"
echo ""
fi
# Show infected files if any
if [ -f "$selected_dir/results/infected_files.txt" ] && [ -s "$selected_dir/results/infected_files.txt" ]; then
echo "=== Infected Files ==="
cat "$selected_dir/results/infected_files.txt"
echo ""
fi
# Show recent log entries
if [ -f "$selected_dir/logs/session.log" ]; then
echo "=== Recent Log Entries ==="
tail -20 "$selected_dir/logs/session.log"
echo ""
fi
echo "View full logs:"
echo " tail -f $selected_dir/logs/session.log"
;;
0)
return 0
;;
*)
echo -e "${RED}Invalid option${NC}"
;;
esac
echo ""
read -p "Press Enter to continue..."
}
# Scanner settings
scanner_settings() {
echo ""
print_header "Scanner Settings"
echo "Settings (placeholder for future enhancements):"
echo " • Auto-quarantine infected files"
echo " • Email notifications"
echo " • Scheduled scans"
echo " • Custom exclusions"
echo ""
echo "Coming soon..."
read -p "Press Enter to continue..."
}
# Main execution
main() {
if ! detect_scanners; then
exit 1
fi
show_scan_menu
}
# Run if executed directly
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
main "$@"
fi