941d624f7a
CRITICAL FIXES (7 → 0):
- Fixed 6 dangerous rm -rf commands with unvalidated variables
- lib/common-functions.sh:176 - Added validation before rm
- tools/erase-toolkit-traces.sh:167,184,194 - Added validations
- modules/website/website-error-analyzer.sh:131 - Fixed trap
- modules/website/500-error-tracker.sh:56 - Fixed trap
- Fixed eval command injection risk in malware-scanner.sh
- Replaced eval with direct find command execution
- Properly escaped parentheses for complex find patterns
HIGH FIXES (10 → 0):
- Fixed 70+ integer comparison issues across 10 files
- Used ${var:-0} syntax to prevent "integer expression expected" errors
- Applied to: lib/ip-reputation.sh, lib/user-manager.sh, launcher.sh,
modules/security/bot-analyzer.sh, modules/security/live-attack-monitor.sh,
modules/security/malware-scanner.sh, modules/security/optimize-ct-limit.sh,
modules/performance/hardware-health-check.sh,
modules/performance/mysql-query-analyzer.sh,
modules/website/500-error-tracker.sh
- Added parameter validation to 10 functions in lib/mysql-analyzer.sh:
- map_database_to_user_domain(), get_database_owner(), get_database_domain()
- identify_plugin_from_table(), get_table_size(), get_database_tables()
- analyze_table_structure(), extract_database_from_query()
- capture_live_queries() (already had validation via file existence check)
- parse_slow_query_log() (already had validation via file existence check)
PROGRESS: 106 issues → 100 issues (-6 issues fixed)
- CRITICAL: 7 → 0 (100% fixed)
- HIGH: 10 → 0 (100% fixed)
- MEDIUM: 63 (unchanged)
- LOW: 26 (unchanged)
1784 lines
60 KiB
Bash
Executable File
1784 lines
60 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
|
|
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:-0} -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
|
|
if [ "$CONTROL_PANEL" = "interworx" ]; then
|
|
# InterWorx: Search /home/*/var/*/logs/transfer.log (VERIFIED: uses 'transfer.log')
|
|
# Search last 7 days of logs for POST requests to this path
|
|
find /home/*/var/*/logs -type f -name 'transfer.log' 2>/dev/null | 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
|
|
elif [ -n "$SYS_LOG_DIR" ] && [ -d "$SYS_LOG_DIR" ]; then
|
|
# cPanel/Plesk: Use detected log directory
|
|
# Search last 7 days of logs for POST requests to this path
|
|
find "$SYS_LOG_DIR" -type f \( -name '*.com' -o -name '*.net' -o -name '*.org' \) 2>/dev/null | 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
|