#!/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 # 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