#!/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 source "$SCRIPT_DIR/lib/reference-db.sh" 2>/dev/null || true source "$SCRIPT_DIR/lib/ip-reputation.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" ] } is_rkhunter_installed() { command -v rkhunter &>/dev/null || [ -f "/usr/bin/rkhunter" ] } # 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 is_rkhunter_installed; then available_scanners+=("rkhunter") 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 # Check Rootkit Hunter if ! is_rkhunter_installed; then echo -e "${CYAN}Rootkit Hunter${NC} - Rootkit/backdoor/exploit scanner" echo " Status: Not installed" echo " Installation:" echo " yum install epel-release -y # Enable EPEL repo" echo " yum install rkhunter -y" echo " rkhunter --update # Update definitions" echo " rkhunter --propupd # Initialize baseline" echo " Docs: https://rkhunter.sourceforge.net/" echo "" else echo -e "${GREEN}✓ Rootkit Hunter${NC} - Installed" echo "" fi echo -e "${YELLOW}Recommendation:${NC} Install at least ClamAV + RKHunter (both free) for comprehensive protection" 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 " • Rootkit Hunter (free, rootkit detection)" 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/4] 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/4] 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/4] 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 "" # Install Rootkit Hunter if ! is_rkhunter_installed; then echo -e "${CYAN}[4/4] Installing Rootkit Hunter...${NC}" # Ensure EPEL repo is enabled if command -v yum &>/dev/null; then if ! rpm -qa | grep -q epel-release; then echo " → Installing EPEL repository..." yum install -y epel-release 2>&1 | grep -E "Installing|Installed|already installed" fi # Install rkhunter yum install -y rkhunter 2>&1 | grep -E "Installing|Installed|already installed" elif command -v apt-get &>/dev/null; then apt-get update && apt-get install -y rkhunter fi if is_rkhunter_installed; then echo -e "${GREEN}✓ Rootkit Hunter installed${NC}" # Update definitions echo " → Updating rootkit definitions..." rkhunter --update 2>&1 | grep -E "updated|downloaded" || rkhunter --update &>/dev/null echo -e " ${GREEN}✓${NC} Definitions updated" # Initialize baseline (propupd creates file property database) echo " → Initializing baseline database..." rkhunter --propupd &>/dev/null echo -e " ${GREEN}✓${NC} Baseline initialized" else echo -e "${RED}✗ Rootkit Hunter installation failed${NC}" fi else echo -e "${GREEN}✓ Rootkit Hunter 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=() # Use system-detect.sh if available, otherwise detect if [ -n "$SYS_CONTROL_PANEL" ]; then CONTROL_PANEL="$SYS_CONTROL_PANEL" elif [ -f "/etc/userdatadomains" ]; then CONTROL_PANEL="cpanel" elif [ -f "/usr/local/psa/version" ]; then CONTROL_PANEL="plesk" elif [ -d "/usr/local/interworx/" ]; then CONTROL_PANEL="interworx" else CONTROL_PANEL="none" fi # cPanel-specific setup if [ "$CONTROL_PANEL" = "cpanel" ]; then # Add cPanel 3rdparty bin to PATH only for cPanel export PATH=/usr/local/cpanel/3rdparty/bin/:$PATH while IFS= read -r line; do # Format: domain: user==owner==main==domain==docroot==... # Extract docroot (field 5, 0-indexed field 4) docroot=$(echo "$line" | awk -F'==' '{print $5}') [ -n "$docroot" ] && [ -d "$docroot" ] && docroot_array+=("$docroot") done < <(cut -d: -f2- /etc/userdatadomains | sort -u) # Plesk-specific elif [ "$CONTROL_PANEL" = "plesk" ]; then 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) # InterWorx-specific (improved with proper path structure) elif [ "$CONTROL_PANEL" = "interworx" ]; then # InterWorx structure: /home/username/domain.com/html # Find all html directories in the InterWorx structure while IFS= read -r docroot; do [ -n "$docroot" ] && [ -d "$docroot" ] && docroot_array+=("$docroot") done < <(find /home/*/*/html -maxdepth 0 -type d 2>/dev/null | 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:-0}" -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 line; do docroot=$(echo "$line" | awk -F'==' '{print $5}') [ -n "$docroot" ] && [ -d "$docroot" ] && user_docroots+=("$docroot") done < <(grep ":.*${username}==" /etc/userdatadomains | cut -d: -f2- | sort -u) elif [ "$CONTROL_PANEL" = "interworx" ]; then # Use user-manager.sh to get all domains for this user local domains=$(get_user_domains "$username") if [ -n "$domains" ]; then while IFS= read -r domain; do # InterWorx: /home/username/domain.com/html local docroot="/home/${username}/${domain}/html" [ -d "$docroot" ] && user_docroots+=("$docroot") done <<< "$domains" fi else echo -e "${RED}User-specific scanning only supported on cPanel/InterWorx${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}') elif [ "$CONTROL_PANEL" = "interworx" ]; then # Find which user owns this domain using vhost configs local username=$(grep -l "ServerName ${domain}" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | head -1 | \ xargs grep "SuexecUserGroup" 2>/dev/null | awk '{print $2}') if [ -n "$username" ]; then # InterWorx: /home/username/domain.com/html domain_docroot="/home/${username}/${domain}/html" fi else echo -e "${RED}Domain lookup only supported on cPanel/Plesk/InterWorx${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 # Track if rkhunter was auto-installed (for cleanup) RKHUNTER_TEMP_INSTALLED=false if command -v rkhunter &>/dev/null; then AVAILABLE_SCANNERS+=("rkhunter") log_message "Detected: Rootkit Hunter" else # Auto-install rkhunter temporarily for this scan log_message "RKHunter not found - installing temporarily..." echo "→ Installing Rootkit Hunter (temporary, will be removed after scan)..." if command -v yum &>/dev/null; then # Ensure EPEL is available if ! rpm -qa | grep -q epel-release; then yum install -y epel-release &>/dev/null fi # Install rkhunter yum install -y rkhunter &>/dev/null if command -v rkhunter &>/dev/null; then # Update definitions and initialize baseline rkhunter --update &>/dev/null rkhunter --propupd &>/dev/null AVAILABLE_SCANNERS+=("rkhunter") RKHUNTER_TEMP_INSTALLED=true log_message "RKHunter installed temporarily" echo " ✓ RKHunter installed (will be removed after scan)" fi fi 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) SCAN_START=$(date +%s) log_message "ImunifyAV: Updating signatures" imunify-antivirus update &>> "$LOG_DIR/imunify.log" log_message "ImunifyAV: Starting on-demand scan (synchronous)" # Use on-demand start (synchronous) instead of queue (asynchronous) for path in "${SCAN_PATHS[@]}"; do if [ -d "$path" ]; then log_message "ImunifyAV: Scanning $path" echo "" echo " 📁 Scanning path: $path" echo " ⏳ Scanner: ImunifyAV (this may take several minutes...)" imunify-antivirus malware on-demand start --path="$path" &>> "$LOG_DIR/imunify.log" # Get scan results from most recent scan (newest scans are at top) # Skip header line (tail -n +2), then get first data line (head -1) # Field 11 is TOTAL (files scanned) LAST_SCAN=$(imunify-antivirus malware on-demand list 2>/dev/null | tail -n +2 | head -1) FILES_SCANNED=$(echo "$LAST_SCAN" | awk '{print $11}') # Verify we got a valid number, otherwise show 0 if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then FILES_SCANNED=0 fi echo " ✓ Scanned $FILES_SCANNED files" fi done # Extract malicious file count # Skip header line and count data rows, or use TOTAL_MALICIOUS from most recent scan IMUNIFY_INFECTED=$(echo "$LAST_SCAN" | awk '{print $12}') # Verify we got a valid number, otherwise try malicious list if ! [[ "$IMUNIFY_INFECTED" =~ ^[0-9]+$ ]]; then IMUNIFY_INFECTED=$(imunify-antivirus malware malicious list 2>/dev/null | tail -n +2 | wc -l || echo 0) fi SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ ImunifyAV scan complete - Found: $IMUNIFY_INFECTED | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE" log_message "ImunifyAV: Scan complete - $IMUNIFY_INFECTED malicious files in ${DURATION}s" ;; clamav) SCAN_START=$(date +%s) if command -v freshclam &>/dev/null; then log_message "ClamAV: Updating signatures" freshclam &>> "$LOG_DIR/clamav.log" fi log_message "ClamAV: Starting scan" echo "" echo " 📁 Scanning path(s): ${SCAN_PATHS[*]}" echo " ⏳ Scanner: ClamAV (comprehensive virus 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 # Get scan stats from log FILES_SCANNED=$(grep "Scanned files:" "$LOG_DIR/clamav.log" | tail -1 | awk '{print $3}') CLAM_INFECTED=$(grep -c "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null || echo 0) # Validate numbers if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then FILES_SCANNED=0 fi SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) echo " ✓ Scanned $FILES_SCANNED files" echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ ClamAV scan complete - Found: $CLAM_INFECTED | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE" log_message "ClamAV: Scan complete - $CLAM_INFECTED infected files in ${DURATION}s" ;; maldet) SCAN_START=$(date +%s) 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" echo "" echo " 📁 Scanning path(s): ${SCAN_PATHS[*]}" echo " ⏳ Scanner: Maldet/LMD (Linux-specific malware detection...)" maldet -b -f "$TEMP_PATHLIST" &>> "$LOG_DIR/maldet.log" # Extract scan results FILES_SCANNED=$(grep "files scanned" "$LOG_DIR/maldet.log" | tail -1 | awk '{print $1}') MALDET_HITS=$(grep "malware hits" "$LOG_DIR/maldet.log" | tail -1 | awk '{print $1}') # Validate numbers if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then FILES_SCANNED=0 fi if ! [[ "$MALDET_HITS" =~ ^[0-9]+$ ]]; then MALDET_HITS=0 fi rm -f "$TEMP_PATHLIST" SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) echo " ✓ Scanned $FILES_SCANNED files" echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ Maldet scan complete - Found: ${MALDET_HITS:-0} | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE" log_message "Maldet: Scan complete - ${MALDET_HITS:-0} hits in ${DURATION}s" ;; rkhunter) SCAN_START=$(date +%s) log_message "RKHunter: Updating definitions" rkhunter --update &>> "$LOG_DIR/rkhunter.log" log_message "RKHunter: Starting scan" echo "" echo " 🔍 System scan: Checking for rootkits, backdoors, exploits" echo " ⏳ Scanner: Rootkit Hunter (system-wide integrity check...)" # --check: Run all checks # --skip-keypress: Don't wait for user input # --report-warnings-only: Only show warnings/issues rkhunter --check --skip-keypress --report-warnings-only &>> "$LOG_DIR/rkhunter.log" # Extract warnings RKH_WARNINGS=$(grep -c "Warning:" "$LOG_DIR/rkhunter.log" 2>/dev/null || echo 0) # Extract any rootkits found grep "Rootkit" "$LOG_DIR/rkhunter.log" | grep -i "found" >> "$INFECTED_LIST" 2>/dev/null SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) echo " ✓ System integrity check complete" echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ RKHunter scan complete - Warnings: $RKH_WARNINGS | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE" log_message "RKHunter: Scan complete - $RKH_WARNINGS warnings in ${DURATION}s" ;; 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 with consolidated summary { echo "==========================================" echo "Scan Session Complete" echo "Completed: $(date)" echo "==========================================" echo "" # Consolidated Scanner Results Table echo "SCANNER RESULTS SUMMARY:" echo "----------------------------------------" # ImunifyAV results if echo "${AVAILABLE_SCANNERS[*]}" | grep -q "imunify"; then IMUNIFY_COUNT=$(grep -o "ImunifyAV scan complete - Found: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A") printf "%-20s %s\n" "ImunifyAV:" "$IMUNIFY_COUNT threats detected" fi # ClamAV results if echo "${AVAILABLE_SCANNERS[*]}" | grep -q "clamav"; then CLAM_COUNT=$(grep -o "ClamAV scan complete - Found: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A") printf "%-20s %s\n" "ClamAV:" "$CLAM_COUNT infected files" fi # Maldet results if echo "${AVAILABLE_SCANNERS[*]}" | grep -q "maldet"; then printf "%-20s %s\n" "Maldet:" "Scan complete (check logs)" fi # RKHunter results if echo "${AVAILABLE_SCANNERS[*]}" | grep -q "rkhunter"; then RKH_COUNT=$(grep -o "RKHunter scan complete - Warnings: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A") printf "%-20s %s\n" "Rootkit Hunter:" "$RKH_COUNT warnings" fi echo "----------------------------------------" echo "" if [ -f "$INFECTED_LIST" ] && [ -s "$INFECTED_LIST" ]; then echo "⚠️ INFECTED FILES DETECTED:" echo "" sort -u "$INFECTED_LIST" echo "" echo "ACTION REQUIRED: Review and quarantine/remove infected files" echo "" # IP Reputation Integration: Flag IPs that uploaded malware echo "----------------------------------------" echo "Analyzing upload sources..." echo "----------------------------------------" # Correlate infected files with Apache logs to find uploading IPs local flagged_ips=0 while read -r infected_file; do # Extract file path components local filename=$(basename "$infected_file") local filepath=$(dirname "$infected_file") # Try to find corresponding Apache access logs # Look for POST requests to the directory containing the infected file # Use system-detected log directory with control panel-specific search local log_search_cmd if [ "$CONTROL_PANEL" = "interworx" ]; then # InterWorx: Search /home/*/var/*/logs/transfer.log (VERIFIED: uses 'transfer.log') log_search_cmd="find /home/*/var/*/logs -type f -name 'transfer.log' 2>/dev/null" elif [ -n "$SYS_LOG_DIR" ] && [ -d "$SYS_LOG_DIR" ]; then # cPanel/Plesk: Use detected log directory log_search_cmd="find $SYS_LOG_DIR -type f -name '*.com' -o -name '*.net' -o -name '*.org' 2>/dev/null" fi if [ -n "$log_search_cmd" ]; then # Search last 7 days of logs for POST requests to this path eval "$log_search_cmd" | while read -r logfile; do # Check if this log corresponds to the domain/user grep -h "POST.*${filepath}" "$logfile" 2>/dev/null | tail -20 | while read -r logline; do # Extract IP from Apache log line local ip=$(echo "$logline" | awk '{print $1}') if [ -n "$ip" ] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then # Flag this IP in reputation database if type flag_ip_attack &>/dev/null; then flag_ip_attack "$ip" "RCE" 25 "Malware scanner: Uploaded $filename" >/dev/null 2>&1 echo " → Flagged IP: $ip (uploaded to $filepath)" >> "$LOG_DIR/flagged_ips.log" ((flagged_ips++)) fi fi done done fi done < <(sort -u "$INFECTED_LIST" | head -20) # Limit to first 20 files to avoid long processing if [ "${flagged_ips:-0}" -gt 0 ]; then echo "✓ Flagged $flagged_ips IPs in reputation database" echo " (See $LOG_DIR/flagged_ips.log for details)" else echo " No upload IPs identified (files may be older than log retention)" fi echo "" else echo "✓ No infected files detected by automated scan." echo "" echo "Review individual scanner logs for detailed information:" echo " • ImunifyAV: $LOG_DIR/imunify.log" echo " • ClamAV: $LOG_DIR/clamav.log" echo " • Maldet: $LOG_DIR/maldet.log" echo " • RKHunter: $LOG_DIR/rkhunter.log" 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 "" # Cleanup: Remove rkhunter if it was temporarily installed if [ "$RKHUNTER_TEMP_INSTALLED" = "true" ]; then log_message "Removing temporarily installed RKHunter..." echo "→ Cleaning up: Removing Rootkit Hunter..." if command -v yum &>/dev/null; then yum remove -y rkhunter &>/dev/null echo " ✓ RKHunter removed" log_message "RKHunter successfully removed" fi echo "" fi # Prompt for cleanup read -p "Delete scan script? (Logs and results will be preserved) (yes/no): " cleanup_choice if [ "$cleanup_choice" = "yes" ]; then log_message "User requested cleanup - deleting scan script" echo "" echo "Removing scan script..." rm -f "$SCAN_DIR/scan.sh" echo -e "${GREEN}✓ Scan script deleted${NC}" echo "" echo "Results preserved at: $SCAN_DIR" echo "" else log_message "User chose to keep scan script" echo "" echo "Scan script and results preserved at: $SCAN_DIR" echo "" fi echo "You can:" echo " • Review logs: ls $LOG_DIR" echo " • View summary: cat $SUMMARY_FILE" echo " • Delete scan directory manually: rm -rf $SCAN_DIR" echo "" echo "Press Ctrl+A then D to detach from this screen session," echo "or press Enter to open an interactive shell in this session..." echo "" read -t 30 -p "" # Keep screen session alive with an interactive shell echo "" echo "Opening interactive shell. Type 'exit' to close this screen session." echo "" log_message "Scan session ended - opening interactive shell" exec bash 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 (scan from / - WARNING: may take several hours)" 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=("/") scan_description="full server scan" echo "" echo -e "${YELLOW}WARNING: Full server scan from /${NC}" echo "This will scan the ENTIRE filesystem including:" echo " • All user directories" echo " • System files" echo " • Application files" echo "" echo "This scan may take several hours and use significant resources." echo "" read -p "Are you sure you want to proceed? (yes/no): " confirm_full_scan if [ "$confirm_full_scan" != "yes" ]; then echo "Cancelled." read -p "Press Enter to continue..." return 0 fi echo "" echo "Scan scope: Entire server from /" ;; 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() { # Build reference database once for the entire menu session if command -v build_reference_database &>/dev/null; then echo "Building system reference database..." build_reference_database 2>/dev/null || true clear fi 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