Major refactor: Toolkit as monitor, standalone for all scans

Architecture Changes:
- ALL scans now use standalone scanner (/opt deployment)
- Toolkit serves as monitor/manager, not executor
- Removed direct scanning from toolkit entirely

New Features:
- Bulk scanner installation (install all 3 at once)
- Scan status checker with live progress
- Session manager (delete individual or all completed scans)
- Enhanced menu structure with clear separation

Menu Organization:
1. Create New Scan (server/user/domain/custom) → generates standalone
2. Monitor & Manage (status/results/delete)
3. Configuration (install all/settings)

Removed Functions:
- scan_entire_server() - now via standalone
- scan_user_account() - now via standalone
- scan_domain() - now via standalone
- scan_custom_path() - now via standalone
- run_all_scanners() - embedded in standalone
- scan_imunify/clamav/maldet() - embedded in standalone

Benefits:
- Cleaner separation of concerns
- Consistent scan execution (all via standalone)
- Better resource management
- Toolkit can be deleted during scan
- Centralized scan monitoring

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
cschantz
2025-11-11 19:16:16 -05:00
parent 6f7ef60b9f
commit b3b5505620
+323 -457
View File
@@ -102,6 +102,128 @@ show_scanner_installation_guide() {
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 (commercial, requires license)"
echo ""
echo -e "${YELLOW}Note: ImunifyAV requires a paid license to function.${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 ! command -v clamscan &>/dev/null; then
echo -e "${CYAN}[1/3] Installing ClamAV...${NC}"
if [ -f "/usr/local/cpanel/cpanel" ]; then
# cPanel method
/scripts/update_local_rpm_versions --edit target_settings.clamav installed
/scripts/check_cpanel_rpms --fix --targets=clamav
elif command -v yum &>/dev/null; then
yum install -y clamav clamav-update
elif command -v apt-get &>/dev/null; then
apt-get update && apt-get install -y clamav clamav-daemon
fi
if command -v clamscan &>/dev/null; then
echo -e "${GREEN}✓ ClamAV installed${NC}"
# Update signatures
if command -v freshclam &>/dev/null; then
echo " Updating virus signatures..."
freshclam &>/dev/null || true
fi
else
echo -e "${RED}✗ ClamAV installation failed${NC}"
fi
else
echo -e "${GREEN}✓ ClamAV already installed${NC}"
fi
echo ""
# Install Maldet
if ! command -v maldet &>/dev/null; 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 command -v maldet &>/dev/null; then
echo -e "${GREEN}✓ Maldet installed${NC}"
# Update signatures
echo " Updating signatures..."
maldet -u &>/dev/null || true
else
echo -e "${RED}✗ Maldet installation failed${NC}"
fi
else
echo -e "${GREEN}✓ Maldet already installed${NC}"
fi
echo ""
# Install ImunifyAV
if ! command -v imunify-antivirus &>/dev/null; then
echo -e "${CYAN}[3/3] Installing ImunifyAV...${NC}"
echo -e "${YELLOW}Note: Requires license key to activate${NC}"
cd /tmp
wget -q https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh
if [ -f imav-deploy.sh ]; then
bash imav-deploy.sh &>/dev/null
rm -f imav-deploy.sh
fi
if command -v imunify-antivirus &>/dev/null; then
echo -e "${GREEN}✓ ImunifyAV installed${NC}"
echo -e "${YELLOW} Register with: imunify-antivirus register <key>${NC}"
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=()
@@ -241,217 +363,6 @@ check_memory() {
}
# ImunifyAV scanner
scan_imunify() {
local scan_paths=("$@")
if ! command -v imunify-antivirus &>/dev/null; then
echo -e "${RED}ImunifyAV not installed${NC}"
return 1
fi
echo -e "${CYAN}Starting ImunifyAV scan...${NC}"
echo ""
# Update signatures
echo "→ Updating signatures..."
imunify-antivirus update 2>/dev/null
# Queue scan paths
for path in "${scan_paths[@]}"; do
if [ -d "$path" ]; then
echo "→ Queuing: $path"
imunify-antivirus malware on-demand queue put "$path" 2>/dev/null
fi
done
echo ""
echo -e "${GREEN}✓ Scan queued${NC}"
echo ""
echo "Monitor progress:"
echo " imunify-antivirus malware on-demand list"
}
# ClamAV scanner
scan_clamav() {
local scan_paths=("$@")
if ! command -v clamscan &>/dev/null; then
echo -e "${RED}ClamAV not installed${NC}"
return 1
fi
# Create log directory
local log_dir="$SCRIPT_DIR/logs/malware-scans"
mkdir -p "$log_dir"
local log_file="$log_dir/clamav_$(date +%Y%m%d_%H%M%S).log"
echo -e "${CYAN}Starting ClamAV scan...${NC}"
echo ""
# Update signatures
if command -v freshclam &>/dev/null; then
echo "→ Updating signatures..."
freshclam 2>/dev/null || true
fi
echo "→ Scanning paths..."
echo ""
# Log scan details
{
echo "ClamAV Malware Scan"
echo "Date: $(date)"
echo "Paths:"
printf '%s\n' "${scan_paths[@]}"
echo ""
echo "Results:"
echo "========================================"
} > "$log_file"
# Run scan
clamscan --infected --recursive "${scan_paths[@]}" >> "$log_file" 2>&1 &
local scan_pid=$!
echo "Scan running in background (PID: $scan_pid)"
echo "Log file: $log_file"
echo ""
echo "Monitor with: tail -f $log_file"
# Store scan info in reference DB
store_reference "malware_scan_clamav_latest" "$log_file"
}
# Maldet scanner
scan_maldet() {
local scan_paths=("$@")
if ! command -v maldet &>/dev/null; then
echo -e "${RED}Maldet not installed${NC}"
return 1
fi
# Create temp file with paths
local path_file="/tmp/maldet_paths_$$.txt"
printf '%s\n' "${scan_paths[@]}" > "$path_file"
echo -e "${CYAN}Starting Maldet scan...${NC}"
echo ""
# Update signatures
echo "→ Updating signatures..."
maldet -u 2>/dev/null || true
echo "→ Starting scan..."
maldet -b -f "$path_file"
rm -f "$path_file"
echo ""
echo "View results:"
echo " maldet -l"
}
# Run all available scanners sequentially
run_all_scanners() {
local scan_paths=("$@")
if [ ${#scan_paths[@]} -eq 0 ]; then
echo -e "${RED}No paths to scan${NC}"
return 1
fi
# Create session ID for this multi-scanner run
local session_id="multiscan_$(date +%Y%m%d_%H%M%S)"
local report_file="$SCRIPT_DIR/logs/malware-scans/${session_id}_summary.txt"
mkdir -p "$SCRIPT_DIR/logs/malware-scans"
echo ""
print_header "Multi-Scanner Session: $session_id"
echo "Running ${#available_scanners[@]} scanner(s) on ${#scan_paths[@]} path(s)"
echo "Session report: $report_file"
echo ""
# Initialize report
{
echo "=========================================="
echo "Multi-Scanner Malware Detection Report"
echo "=========================================="
echo "Session ID: $session_id"
echo "Date: $(date)"
echo "Scanners: ${available_scanners[*]}"
echo "Paths: ${#scan_paths[@]}"
echo ""
printf '%s\n' "${scan_paths[@]}"
echo ""
echo "=========================================="
echo ""
} > "$report_file"
local scanner_num=1
local total_scanners=${#available_scanners[@]}
# Run each scanner
for scanner in "${available_scanners[@]}"; do
echo -e "${CYAN}[$scanner_num/$total_scanners] Starting ${scanner^} scan...${NC}"
echo ""
{
echo "Scanner: ${scanner^}"
echo "Started: $(date)"
echo "---"
} >> "$report_file"
case "$scanner" in
imunify)
scan_imunify "${scan_paths[@]}" | tee -a "$report_file"
;;
clamav)
scan_clamav "${scan_paths[@]}" | tee -a "$report_file"
;;
maldet)
scan_maldet "${scan_paths[@]}" | tee -a "$report_file"
;;
esac
echo "" | tee -a "$report_file"
echo "---" >> "$report_file"
echo "" >> "$report_file"
((scanner_num++))
# Wait a moment between scanners
if [ $scanner_num -le $total_scanners ]; then
echo ""
echo "Waiting 3 seconds before next scanner..."
sleep 3
echo ""
fi
done
# Finalize report
{
echo "=========================================="
echo "Multi-Scanner Session Complete"
echo "Completed: $(date)"
echo "=========================================="
} >> "$report_file"
echo ""
echo -e "${GREEN}✓ All scanners completed${NC}"
echo ""
echo "Session report saved: $report_file"
echo ""
echo "View individual scanner results using option 5 from main menu"
# Store in reference database
store_reference "malware_multiscan_latest" "$session_id"
store_reference "malware_multiscan_${session_id}" "$report_file"
echo ""
read -p "Press Enter to continue..."
}
# Generate standalone malware scan script
generate_standalone_scanner() {
@@ -891,12 +802,13 @@ compare_scan_results() {
# 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 in a screen session. You can safely delete the"
echo "toolkit after launching - the scan will continue running."
echo "independently. You can safely delete the toolkit after launching."
echo ""
if ! detect_control_panel; then
@@ -908,6 +820,20 @@ launch_standalone_scanner_menu() {
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"
@@ -915,11 +841,8 @@ launch_standalone_scanner_menu() {
echo " 4. Custom path"
echo " 0. Cancel"
echo ""
read -p "Select option: " scope_choice
local scan_paths=()
local scan_description=""
fi
case $scope_choice in
1)
@@ -1045,6 +968,173 @@ launch_standalone_scanner_menu() {
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
@@ -1056,19 +1146,20 @@ show_scan_menu() {
done
echo ""
echo "Scan Scope:"
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 "${GREEN}Standalone Scanner:${NC}"
echo " 5. Launch standalone scanner (runs in background, toolkit-independent)"
echo ""
echo "Results & Management:"
echo -e "${CYAN}Monitor & Manage:${NC}"
echo " 5. Check scan status"
echo " 6. View scan results"
echo " 7. Compare scanner results"
echo " 8. Scanner settings"
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 ""
@@ -1076,246 +1167,21 @@ show_scan_menu() {
read -p "Select option: " choice
case $choice in
1) scan_entire_server ;;
2) scan_user_account ;;
3) scan_domain ;;
4) scan_custom_path ;;
5) launch_standalone_scanner_menu ;;
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) compare_scan_results ;;
8) scanner_settings ;;
7) delete_standalone_sessions ;;
8) install_all_scanners ;;
9) scanner_settings ;;
0) return 0 ;;
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
esac
done
}
# Scan entire server
scan_entire_server() {
echo ""
print_header "Full Server Scan"
if ! detect_control_panel; then
read -p "Press Enter to continue..."
return 1
fi
echo "Control Panel: ${CONTROL_PANEL^}"
echo "Docroots found: ${#sanitized_docroot[@]}"
echo ""
if ! check_memory; then
read -p "Press Enter to continue..."
return 1
fi
echo "Select scanner:"
local i=1
for scanner in "${available_scanners[@]}"; do
echo " $i. ${scanner^}"
((i++))
done
echo " $i. All Available Scanners (run sequentially)"
echo ""
read -p "Scanner: " scanner_choice
# Check for "All Scanners" option
if [ "$scanner_choice" -eq "$i" ]; then
run_all_scanners "${sanitized_docroot[@]}"
elif [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
else
local selected_scanner="${available_scanners[$((scanner_choice-1))]}"
case "$selected_scanner" in
imunify) scan_imunify "${sanitized_docroot[@]}" ;;
clamav) scan_clamav "${sanitized_docroot[@]}" ;;
maldet) scan_maldet "${sanitized_docroot[@]}" ;;
esac
fi
echo ""
read -p "Press Enter to continue..."
}
# Scan user account
scan_user_account() {
echo ""
print_header "Scan User Account"
if ! detect_control_panel; then
read -p "Press Enter to continue..."
return 1
fi
# Use user manager to select user
select_user_interactive "Select user to scan"
if [ -z "$SELECTED_USER" ]; then
echo "No user selected"
read -p "Press Enter to continue..."
return 1
fi
echo ""
echo "Getting docroots for: $SELECTED_USER"
local user_paths=($(get_user_docroots "$SELECTED_USER"))
if [ ${#user_paths[@]} -eq 0 ]; then
echo -e "${RED}No docroots found for user${NC}"
read -p "Press Enter to continue..."
return 1
fi
echo "Paths to scan: ${#user_paths[@]}"
printf ' %s\n' "${user_paths[@]}"
echo ""
echo "Select scanner:"
local i=1
for scanner in "${available_scanners[@]}"; do
echo " $i. ${scanner^}"
((i++))
done
echo " $i. All Available Scanners (run sequentially)"
echo ""
read -p "Scanner: " scanner_choice
# Check for "All Scanners" option
if [ "$scanner_choice" -eq "$i" ]; then
run_all_scanners "${user_paths[@]}"
elif [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
else
local selected_scanner="${available_scanners[$((scanner_choice-1))]}"
case "$selected_scanner" in
imunify) scan_imunify "${user_paths[@]}" ;;
clamav) scan_clamav "${user_paths[@]}" ;;
maldet) scan_maldet "${user_paths[@]}" ;;
esac
fi
echo ""
read -p "Press Enter to continue..."
}
# Scan domain
scan_domain() {
echo ""
print_header "Scan Domain"
if ! detect_control_panel; then
read -p "Press Enter to continue..."
return 1
fi
read -p "Enter domain name: " domain
if [ -z "$domain" ]; then
echo "No domain entered"
read -p "Press Enter to continue..."
return 1
fi
local domain_path=$(get_domain_docroot "$domain")
if [ -z "$domain_path" ] || [ ! -d "$domain_path" ]; then
echo -e "${RED}Domain not found or docroot doesn't exist${NC}"
read -p "Press Enter to continue..."
return 1
fi
echo "Docroot: $domain_path"
echo ""
echo "Select scanner:"
local i=1
for scanner in "${available_scanners[@]}"; do
echo " $i. ${scanner^}"
((i++))
done
echo " $i. All Available Scanners (run sequentially)"
echo ""
read -p "Scanner: " scanner_choice
# Check for "All Scanners" option
if [ "$scanner_choice" -eq "$i" ]; then
run_all_scanners "$domain_path"
elif [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
else
local selected_scanner="${available_scanners[$((scanner_choice-1))]}"
case "$selected_scanner" in
imunify) scan_imunify "$domain_path" ;;
clamav) scan_clamav "$domain_path" ;;
maldet) scan_maldet "$domain_path" ;;
esac
fi
echo ""
read -p "Press Enter to continue..."
}
# Scan custom path
scan_custom_path() {
echo ""
print_header "Scan Custom Path"
read -p "Enter path to scan: " custom_path
if [ -z "$custom_path" ] || [ ! -d "$custom_path" ]; then
echo -e "${RED}Path doesn't exist${NC}"
read -p "Press Enter to continue..."
return 1
fi
echo "Path: $custom_path"
echo ""
echo "Select scanner:"
local i=1
for scanner in "${available_scanners[@]}"; do
echo " $i. ${scanner^}"
((i++))
done
echo " $i. All Available Scanners (run sequentially)"
echo ""
read -p "Scanner: " scanner_choice
# Check for "All Scanners" option
if [ "$scanner_choice" -eq "$i" ]; then
run_all_scanners "$custom_path"
elif [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
echo -e "${RED}Invalid choice${NC}"
read -p "Press Enter to continue..."
return 1
else
local selected_scanner="${available_scanners[$((scanner_choice-1))]}"
case "$selected_scanner" in
imunify) scan_imunify "$custom_path" ;;
clamav) scan_clamav "$custom_path" ;;
maldet) scan_maldet "$custom_path" ;;
esac
fi
echo ""
read -p "Press Enter to continue..."
}
# View scan results
view_scan_results() {
echo ""