mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-24 20:21:52 +08:00
refactor: 优化控制台输出格式
- 去掉时间戳,保留[*][+]前缀 - Web输出合并WebTitle和WebFinger为一行 - 有指纹显示绿色[+],无指纹显示白色[*] - 格式: code:xxx len:xxx title:xxx server:xxx [指纹] - 服务探测格式: [Product:xxx ||Version:xxx] Banner:(xxx) - 字段对齐,输出更清爽
This commit is contained in:
@@ -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
@@ -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
@@ -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,处理相对路径
|
||||
|
||||
Reference in New Issue
Block a user