refactor: 优化控制台输出格式

- 去掉时间戳,保留[*][+]前缀
- Web输出合并WebTitle和WebFinger为一行
- 有指纹显示绿色[+],无指纹显示白色[*]
- 格式: code:xxx len:xxx title:xxx server:xxx [指纹]
- 服务探测格式: [Product:xxx ||Version:xxx] Banner:(xxx)
- 字段对齐,输出更清爽
This commit is contained in:
ZacharyZcR
2026-01-20 12:05:01 +08:00
parent e86dd1a231
commit 4ef21f3841
3 changed files with 48 additions and 31 deletions
+2 -3
View File
@@ -114,10 +114,9 @@ func (l *Logger) log(level LogLevel, content string) {
return
}
// 格式化消息
timeStr := l.formatElapsedTime(time.Since(l.startTime))
// 格式化消息:保留前缀,去掉时间戳
prefix := l.getLevelPrefix(level)
logMsg := fmt.Sprintf("[%s] %s %s", timeStr, prefix, content)
logMsg := fmt.Sprintf("%s %s", prefix, content)
// 输出消息
l.outputMessage(level, logMsg)
+24 -10
View File
@@ -311,23 +311,37 @@ func isResourceExhaustedError(err error) bool {
}
// buildServiceLogMessage 构建服务识别的日志信息
// 格式: addr service banner (简洁单行,方便复制)
// 格式: addr service [Product:xxx ||Version:xxx] Banner:(xxx)
func buildServiceLogMessage(addr string, serviceInfo *ServiceInfo, isWeb bool) string {
var parts []string
parts = append(parts, addr)
var msg strings.Builder
msg.WriteString(fmt.Sprintf("%-21s", addr))
if serviceInfo.Name != "unknown" {
parts = append(parts, serviceInfo.Name)
msg.WriteString(fmt.Sprintf(" %-8s", serviceInfo.Name))
}
// Banner 优先,其次是版本信息
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
parts = append(parts, strings.TrimSpace(serviceInfo.Banner))
} else if serviceInfo.Version != "" {
parts = append(parts, serviceInfo.Version)
// 构建 [Product:xxx ||Version:xxx] 格式
var info []string
if product, ok := serviceInfo.Extras["product"]; ok && product != "" {
info = append(info, fmt.Sprintf("Product:%s", product))
}
if serviceInfo.Version != "" {
info = append(info, fmt.Sprintf("Version:%s", serviceInfo.Version))
}
if len(info) > 0 {
msg.WriteString(fmt.Sprintf(" [%s]", strings.Join(info, " ||")))
}
return strings.Join(parts, " ")
// Banner 信息
if len(serviceInfo.Banner) > 0 {
banner := strings.TrimSpace(serviceInfo.Banner)
if len(banner) > 80 {
banner = banner[:80] + "..."
}
msg.WriteString(fmt.Sprintf(" Banner:(%s)", banner))
}
return msg.String()
}
// scanSinglePort 扫描单个端口并进行服务识别(重构后的简洁版本)
+22 -18
View File
@@ -40,7 +40,7 @@ func NewWebTitlePlugin() *WebTitlePlugin {
// Scan 执行WebTitle扫描
func (p *WebTitlePlugin) Scan(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *WebScanResult {
title, status, server, fingerprints, url, err := p.getWebTitle(ctx, info, config)
title, status, length, server, fingerprints, url, err := p.getWebTitle(ctx, info, config)
if err != nil {
return &WebScanResult{
Success: false,
@@ -48,21 +48,24 @@ func (p *WebTitlePlugin) Scan(ctx context.Context, info *common.HostInfo, config
}
}
msg := fmt.Sprintf("WebTitle %s", url)
if title != "" {
msg += fmt.Sprintf(" [%s]", title)
}
if status != 0 {
msg += fmt.Sprintf(" %d", status)
// 构建输出:URL code:状态码 len:长度 title:标题 server:服务器 [指纹]
titleDisplay := title
if titleDisplay == "" {
titleDisplay = "None"
}
msg := fmt.Sprintf("%-30s code:%-3d len:%-5d title:%-20s", url, status, length, titleDisplay)
if server != "" {
msg += fmt.Sprintf(" %s", server)
msg += fmt.Sprintf(" server:%s", server)
}
// 基础信息用白色输出
common.LogInfo(msg)
// 指纹信息单独用绿色输出
if len(fingerprints) > 0 {
common.LogSuccess(fmt.Sprintf("WebFinger %s %v", url, fingerprints))
msg += fmt.Sprintf(" %v", fingerprints)
}
// 有指纹用绿色,无指纹用白色
if len(fingerprints) > 0 {
common.LogSuccess(msg)
} else {
common.LogInfo(msg)
}
return &WebScanResult{
@@ -75,7 +78,7 @@ func (p *WebTitlePlugin) Scan(ctx context.Context, info *common.HostInfo, config
}
}
func (p *WebTitlePlugin) getWebTitle(ctx context.Context, info *common.HostInfo, config *common.Config) (string, int, string, []string, string, error) {
func (p *WebTitlePlugin) getWebTitle(ctx context.Context, info *common.HostInfo, config *common.Config) (string, int, int, string, []string, string, error) {
// 智能协议检测
protocol := p.detectProtocol(info, config)
baseURL := fmt.Sprintf("%s://%s:%d", protocol, info.Host, info.Port)
@@ -90,7 +93,7 @@ func (p *WebTitlePlugin) getWebTitle(ctx context.Context, info *common.HostInfo,
req, err := http.NewRequestWithContext(ctx, "GET", baseURL, nil)
if err != nil {
return "", 0, "", nil, displayURL, err
return "", 0, 0, "", nil, displayURL, err
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
@@ -98,13 +101,14 @@ func (p *WebTitlePlugin) getWebTitle(ctx context.Context, info *common.HostInfo,
// 先使用不跟随重定向的Client获取原始响应
resp, err := lib.ClientNoRedirect.Do(req)
if err != nil {
return "", 0, "", nil, displayURL, err
return "", 0, 0, "", nil, displayURL, err
}
body, err := io.ReadAll(resp.Body)
_ = resp.Body.Close()
if len(body) <= 0 && err != nil {
return "", resp.StatusCode, resp.Header.Get("Server"), nil, displayURL, err
contentLen := len(body)
if contentLen <= 0 && err != nil {
return "", resp.StatusCode, 0, resp.Header.Get("Server"), nil, displayURL, err
}
// 收集用于指纹识别的响应数据
@@ -157,7 +161,7 @@ func (p *WebTitlePlugin) getWebTitle(ctx context.Context, info *common.HostInfo,
// 执行指纹识别(合并原始响应和跳转后响应的指纹)
fingerprints := p.identifyFingerprintsMulti(info, baseURL, checkDataList, config)
return title, statusCode, server, fingerprints, displayURL, nil
return title, statusCode, contentLen, server, fingerprints, displayURL, nil
}
// resolveRedirectURL 解析重定向URL,处理相对路径