package core import ( "github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common/i18n" "strconv" "strings" "sync" ) // ServiceScanStrategy 服务扫描策略 type ServiceScanStrategy struct { *BaseScanStrategy portDiscovery *PortDiscoveryService } // NewServiceScanStrategy 创建新的服务扫描策略 func NewServiceScanStrategy() *ServiceScanStrategy { return &ServiceScanStrategy{ BaseScanStrategy: NewBaseScanStrategy("服务扫描", FilterService), portDiscovery: NewPortDiscoveryService(), } } // Name 返回策略名称 func (s *ServiceScanStrategy) Name() string { return i18n.GetText("scan_strategy_service_name") } // Description 返回策略描述 func (s *ServiceScanStrategy) Description() string { return i18n.GetText("scan_strategy_service_desc") } // Execute 执行服务扫描策略 func (s *ServiceScanStrategy) Execute(info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { // 验证扫描目标 if info.Host == "" { common.LogError(i18n.GetText("parse_error_target_empty")) return } // 输出扫描开始信息 s.LogScanStart() // 验证插件配置 if err := s.ValidateConfiguration(); err != nil { common.LogError(err.Error()) return } common.LogBase(i18n.GetText("scan_host_start")) // 输出插件信息 s.LogPluginInfo() // 执行主机扫描流程 s.performHostScan(info, ch, wg) } // performHostScan 执行主机扫描的完整流程 func (s *ServiceScanStrategy) performHostScan(info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { // 使用端口发现服务发现目标 targetInfos, err := s.portDiscovery.DiscoverTargets(info.Host, info) if err != nil { common.LogError(err.Error()) return } // 执行漏洞扫描 if len(targetInfos) > 0 { common.LogBase(i18n.GetText("scan_vulnerability_start")) // 显示即将使用的漏洞扫描插件 s.LogVulnerabilityPluginInfo(targetInfos) ExecuteScanTasks(targetInfos, s, ch, wg) } } // PrepareTargets 准备目标信息 func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo) []common.HostInfo { // 使用端口发现服务发现目标 targetInfos, err := s.portDiscovery.DiscoverTargets(info.Host, info) if err != nil { common.LogError(err.Error()) return nil } return targetInfos } // LogVulnerabilityPluginInfo 输出漏洞扫描插件信息 func (s *ServiceScanStrategy) LogVulnerabilityPluginInfo(targets []common.HostInfo) { allPlugins, isCustomMode := s.GetPlugins() // 收集所有目标端口用于插件适用性检查 portSet := make(map[int]bool) for _, target := range targets { if target.Ports != "" { if port, err := strconv.Atoi(target.Ports); err == nil { portSet[port] = true } } } // 获取实际会被使用的插件列表(优化版本) var vulnerabilityPlugins []string for _, pluginName := range allPlugins { plugin, exists := common.PluginManager[pluginName] if !exists { continue } // 检查插件是否对任何目标端口适用 if s.isPluginApplicableToAnyPort(plugin, portSet, isCustomMode) { vulnerabilityPlugins = append(vulnerabilityPlugins, pluginName) } } // 输出插件信息 if len(vulnerabilityPlugins) > 0 { common.LogBase(i18n.GetText("scan_vulnerability_plugins", strings.Join(vulnerabilityPlugins, ", "))) } else { common.LogBase(i18n.GetText("scan_no_vulnerability_plugins")) } } // isPluginApplicableToAnyPort 检查插件是否对任何端口适用(性能优化) func (s *ServiceScanStrategy) isPluginApplicableToAnyPort(plugin common.ScanPlugin, portSet map[int]bool, isCustomMode bool) bool { // 自定义模式下运行所有明确指定的插件 if isCustomMode { return true } // 非自定义模式下,排除本地插件 if plugin.HasType(common.PluginTypeLocal) { return false } // 无端口限制的插件适用于所有端口 if len(plugin.Ports) == 0 { return true } // 有端口限制的插件:检查是否匹配任何目标端口 for port := range portSet { if plugin.HasPort(port) { return true } } return false }