package core import ( "fmt" "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(), } } // LogPluginInfo 重写以提供基于端口的插件过滤 func (s *ServiceScanStrategy) LogPluginInfo() { // 需要从命令行参数获取端口信息来进行过滤 // 如果没有指定端口,使用默认端口进行过滤显示 if common.Ports == "" || common.Ports == "all" { // 默认端口扫描:显示所有插件 s.BaseScanStrategy.LogPluginInfo() } else { // 指定端口扫描:只显示匹配的插件 s.showPluginsForSpecifiedPorts() } } // showPluginsForSpecifiedPorts 显示指定端口的匹配插件 func (s *ServiceScanStrategy) showPluginsForSpecifiedPorts() { allPlugins, isCustomMode := s.GetPlugins() // 解析端口 ports := s.parsePortList(common.Ports) if len(ports) == 0 { s.BaseScanStrategy.LogPluginInfo() return } // 收集所有匹配的插件(去重) pluginSet := make(map[string]bool) for _, port := range ports { for _, pluginName := range allPlugins { if s.pluginExists(pluginName) { if s.IsPluginApplicableByName(pluginName, "127.0.0.1", port, isCustomMode) { pluginSet[pluginName] = true } } } } // 转换为列表 var applicablePlugins []string for pluginName := range pluginSet { applicablePlugins = append(applicablePlugins, pluginName) } // 输出结果 if len(applicablePlugins) > 0 { if isCustomMode { common.LogBase(fmt.Sprintf("服务插件: 自定义指定 (%s)", strings.Join(applicablePlugins, ", "))) } else { common.LogBase(fmt.Sprintf("服务插件: %s", strings.Join(applicablePlugins, ", "))) } } else { common.LogBase("服务插件: 无可用插件") } } // parsePortList 解析端口列表 func (s *ServiceScanStrategy) parsePortList(portStr string) []int { if portStr == "" || portStr == "all" { return []int{} } var ports []int parts := strings.Split(portStr, ",") for _, part := range parts { part = strings.TrimSpace(part) if port, err := strconv.Atoi(part); err == nil { ports = append(ports, port) } } return ports } // 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 } } } // 获取实际会被使用的插件列表(考虑所有发现端口的匹配) servicePluginSet := make(map[string]bool) // 提取所有目标端口用于插件适用性检查 var allPorts []int for port := range portSet { allPorts = append(allPorts, port) } for _, pluginName := range allPlugins { // 使用统一插件系统检查插件存在性 if s.pluginExists(pluginName) { // 检查插件是否适用于任意一个发现的端口 for _, port := range allPorts { if s.IsPluginApplicableByName(pluginName, "127.0.0.1", port, isCustomMode) { servicePluginSet[pluginName] = true break // 只要适用于一个端口就添加 } } } } // 转换为切片 var servicePlugins []string for pluginName := range servicePluginSet { servicePlugins = append(servicePlugins, pluginName) } // 输出插件信息 if len(servicePlugins) > 0 { common.LogBase(i18n.GetText("scan_service_plugins", strings.Join(servicePlugins, ", "))) } else { common.LogBase(i18n.GetText("scan_no_service_plugins")) } }