diff --git a/core/PortScan.go b/core/PortScan.go index ab82904..930d2e5 100644 --- a/core/PortScan.go +++ b/core/PortScan.go @@ -84,57 +84,71 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64) []string { } defer conn.Close() - // 记录开放端口 + // 记录开放端口(先记录到内存,延迟输出直到服务识别完成) atomic.AddInt64(&count, 1) aliveMap.Store(addr, struct{}{}) - common.LogInfo("端口开放 " + addr) common.SaveResult(&output.ScanResult{ Time: time.Now(), Type: output.TypePort, Target: host, Status: "open", Details: map[string]interface{}{"port": port}, }) - // 服务识别 - if common.EnableFingerprint { - if info, err := NewPortInfoScanner(host, port, conn, to).Identify(); err == nil { - // 构建结果详情 - details := map[string]interface{}{"port": port, "service": info.Name} - if info.Version != "" { - details["version"] = info.Version - } + // 统一服务识别(默认启用,替代原有的-fp选项逻辑) + serviceInfo, err := NewPortInfoScanner(host, port, conn, to).Identify() + if err == nil { + // 构建结果详情 + details := map[string]interface{}{"port": port, "service": serviceInfo.Name} + if serviceInfo.Version != "" { + details["version"] = serviceInfo.Version + } - // 处理额外信息 - for k, v := range info.Extras { - if v == "" { - continue - } - switch k { - case "vendor_product": - details["product"] = v - case "os", "info": - details[k] = v - } + // 处理额外信息 + for k, v := range serviceInfo.Extras { + if v == "" { + continue } - if len(info.Banner) > 0 { - details["banner"] = strings.TrimSpace(info.Banner) + switch k { + case "vendor_product": + details["product"] = v + case "os", "info": + details[k] = v } + } + if len(serviceInfo.Banner) > 0 { + details["banner"] = strings.TrimSpace(serviceInfo.Banner) + } - // 保存服务结果 - common.SaveResult(&output.ScanResult{ - Time: time.Now(), Type: output.TypeService, Target: host, - Status: "identified", Details: details, - }) + // 智能判断是否为Web服务 + isWeb := IsWebServiceByFingerprint(serviceInfo) + if isWeb { + details["is_web"] = true + // 标记该端口为Web服务,后续会自动启用WebTitle和WebPOC + MarkAsWebService(host, port, serviceInfo) + } - // 记录服务信息 - var sb strings.Builder - sb.WriteString("服务识别 " + addr + " => ") - if info.Name != "unknown" { - sb.WriteString("[" + info.Name + "]") - } - if info.Version != "" { - sb.WriteString(" 版本:" + info.Version) - } + // 保存服务结果 + common.SaveResult(&output.ScanResult{ + Time: time.Now(), Type: output.TypeService, Target: host, + Status: "identified", Details: details, + }) - for k, v := range info.Extras { + // 构建统一的服务信息日志 + var sb strings.Builder + sb.WriteString("端口开放 " + addr) + + if serviceInfo.Name != "unknown" { + sb.WriteString(" [" + serviceInfo.Name + "]") + if isWeb { + sb.WriteString("(Web服务)") + } + } + + if serviceInfo.Version != "" { + sb.WriteString(" 版本:" + serviceInfo.Version) + } + + // 添加详细信息(在-fp启用时) + if common.EnableFingerprint { + for k, v := range serviceInfo.Extras { if v == "" { continue } @@ -148,12 +162,17 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64) []string { } } - if len(info.Banner) > 0 && len(info.Banner) < 100 { - sb.WriteString(" Banner:[" + strings.TrimSpace(info.Banner) + "]") + if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 { + sb.WriteString(" Banner:[" + strings.TrimSpace(serviceInfo.Banner) + "]") } - - common.LogInfo(sb.String()) } + + // 统一输出端口和服务信息 + common.LogInfo(sb.String()) + } else { + // 服务识别失败时,只输出端口开放信息 + common.LogInfo("端口开放 " + addr) + common.LogDebug(fmt.Sprintf("服务识别失败 %s: %v,回退到Web检测", addr, err)) } return nil