diff --git a/go.mod b/go.mod index 41bb4b8..638c2f5 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,10 @@ require ( github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/chainreactors/words v0.0.0-20240910083848-19a289e8984b // indirect + github.com/charmbracelet/lipgloss v0.13.0 // indirect + github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/facebookincubator/nvdtools v0.1.5 // indirect github.com/fatih/color v1.17.0 // indirect github.com/go-dedup/megophone v0.0.0-20170830025436-f01be21026f5 // indirect @@ -37,10 +40,12 @@ require ( github.com/gookit/goutil v0.6.15 // indirect github.com/klauspost/compress v1.17.8 // indirect github.com/kr/pretty v0.3.1 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/muesli/termenv v0.15.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect diff --git a/go.sum b/go.sum index 0abf8c8..0647b56 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -113,6 +115,10 @@ github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508 h1:iT4HWkoZz github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508/go.mod h1:DUDx7PdsMEm5PvVhzkFyppzpiUhQb8dOJaWjVc1SMVk= github.com/chainreactors/words v0.4.1-0.20240910075300-24fe4facd5a6 h1:QpUlRyzw5wn9avRbTHBKRhV06X79Yj/ghGKn2Gyb9v4= github.com/chainreactors/words v0.4.1-0.20240910075300-24fe4facd5a6/go.mod h1:zfz367PUmyaX6oAqV9SktVqyRXKlEh0sel9Wsq9dd2c= +github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= +github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= +github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= +github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -332,6 +338,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -369,6 +377,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw= github.com/panjf2000/ants/v2 v2.9.1/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= diff --git a/internal/option.go b/internal/option.go index 2660578..6c07ce8 100644 --- a/internal/option.go +++ b/internal/option.go @@ -14,6 +14,7 @@ import ( "github.com/chainreactors/utils/iutils" "github.com/chainreactors/words/mask" "github.com/chainreactors/words/rule" + "github.com/charmbracelet/lipgloss" "github.com/expr-lang/expr" "github.com/vbauerster/mpb/v8" "io/ioutil" @@ -304,10 +305,6 @@ func (opt *Option) NewRunner() (*Runner, error) { r.ClientType = ihttp.STANDARD } - if opt.Threads == DefaultThreads && len(opt.Dictionaries) == 0 { - r.Threads = 1000 - } - err = opt.BuildPlugin(r) if err != nil { return nil, err @@ -318,6 +315,10 @@ func (opt *Option) NewRunner() (*Runner, error) { return nil, err } + if opt.Threads == DefaultThreads && r.bruteMod { + r.Threads = 1000 + } + pkg.DefaultStatistor = pkg.Statistor{ Word: opt.Word, WordCount: len(r.Wordlist), @@ -392,6 +393,8 @@ func (opt *Option) NewRunner() (*Runner, error) { r.Probes = strings.Split(opt.OutputProbe, ",") } + fmt.Println(opt.PrintConfig(r)) + // init output file if opt.OutputFile != "" { r.OutputFile, err = files.NewFile(opt.OutputFile, false, false, true) @@ -435,30 +438,136 @@ func (opt *Option) NewRunner() (*Runner, error) { return r, nil } -func (opt *Option) PrintPlugin() { - var s strings.Builder - if opt.CrawlPlugin { - s.WriteString("crawl enable; ") - } - if opt.Finger { - s.WriteString("active fingerprint enable; ") - } - if opt.BakPlugin { - s.WriteString("bak file enable; ") - } - if opt.CommonPlugin { - s.WriteString("common file enable; ") - } - if opt.ReconPlugin { - s.WriteString("recon enable; ") - } - if opt.RetryCount > 0 { - s.WriteString("Retry Count: " + strconv.Itoa(opt.RetryCount)) +func (opt *Option) PrintConfig(r *Runner) string { + // 定义颜色样式 + keyStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#FFFFFF")).Width(20) // Key 加粗并设定宽度 + stringValueStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#FFA07A")) // 字符串样式 + arrayValueStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#98FB98")) // 数组样式 + numberValueStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#ADD8E6")) // 数字样式 + panelWidth := 60 // 调整 panelWidth 使内容稍微靠左 + padding := 2 // 减少 padding 以调整布局靠左 + + // 分割线样式和终端宽度计算 + divider := strings.Repeat("─", panelWidth) // 使用"─"符号生成更加连贯的分割线 + + // 处理不同类型的值 + formatValue := func(value interface{}) string { + switch v := value.(type) { + case string: + return stringValueStyle.Render(v) + case []string: + return arrayValueStyle.Render(fmt.Sprintf("%v", v)) + case int, int64, float64: + return numberValueStyle.Render(fmt.Sprintf("%v", v)) + default: + return stringValueStyle.Render(fmt.Sprintf("%v", v)) // 默认为字符串样式 + } } - if s.Len() > 0 { - logs.Log.Important(s.String()) + // 处理互斥参数,选择输出有值的那一个 + inputSource := "" + if opt.ResumeFrom != "" { + inputSource = lipgloss.JoinHorizontal(lipgloss.Left, "🌀 ", keyStyle.Render("ResumeFrom: "), formatValue(opt.ResumeFrom)) + } else if len(opt.URL) > 0 { + inputSource = lipgloss.JoinHorizontal(lipgloss.Left, "🌐 ", keyStyle.Render("URL: "), formatValue(opt.URL)) + } else if opt.URLFile != "" { + inputSource = lipgloss.JoinHorizontal(lipgloss.Left, "📂 ", keyStyle.Render("URLFile: "), formatValue(opt.URLFile)) + } else if len(opt.CIDRs) > 0 { + inputSource = lipgloss.JoinHorizontal(lipgloss.Left, "📡 ", keyStyle.Render("CIDRs: "), formatValue(opt.CIDRs)) + } else if opt.RawFile != "" { + inputSource = lipgloss.JoinHorizontal(lipgloss.Left, "📄 ", keyStyle.Render("RawFile: "), formatValue(opt.RawFile)) } + + // Input Options + inputOptions := lipgloss.JoinVertical(lipgloss.Left, + inputSource, // 互斥量处理 + + // PortRange 展示 + lipgloss.JoinHorizontal(lipgloss.Left, "🔢 ", keyStyle.Render("PortRange: "), formatValue(opt.PortRange)), + + // Dictionaries 展示 + lipgloss.JoinHorizontal(lipgloss.Left, "📚 ", keyStyle.Render("Dictionaries: "), formatValue(opt.Dictionaries)), + + // Word, Rules, FilterRule 展开为单独的行 + lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "💡 ", keyStyle.Render("Word: "), formatValue(r.Word)), + lipgloss.JoinHorizontal(lipgloss.Left, "📜 ", keyStyle.Render("Rules: "), formatValue(opt.Rules)), + lipgloss.JoinHorizontal(lipgloss.Left, "🔍 ", keyStyle.Render("FilterRule: "), formatValue(opt.FilterRule)), + ), + + // AppendRule 和 AppendWords 展开为单独的行 + lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "🔧 ", keyStyle.Render("AppendRule: "), formatValue(r.AppendRule)), + lipgloss.JoinHorizontal(lipgloss.Left, "🧩 ", keyStyle.Render("AppendWords: "), formatValue(len(r.AppendWords))), + ), + ) + + // Output Options + outputOptions := lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "📊 ", keyStyle.Render("Match: "), formatValue(opt.Match)), + lipgloss.JoinHorizontal(lipgloss.Left, "⚙️ ", keyStyle.Render("Filter: "), formatValue(opt.Filter)), + ) + + // Plugin Options + pluginValues := []string{} + if opt.ActivePlugin { + pluginValues = append(pluginValues, "active") + } + if opt.ReconPlugin { + pluginValues = append(pluginValues, "recon") + } + if opt.BakPlugin { + pluginValues = append(pluginValues, "bak") + } + if opt.CommonPlugin { + pluginValues = append(pluginValues, "common") + } + if opt.CrawlPlugin { + pluginValues = append(pluginValues, "crawl") + } + + pluginOptions := lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "🔎 ", keyStyle.Render("Extracts: "), formatValue(opt.Extracts)), + lipgloss.JoinHorizontal(lipgloss.Left, "🔌 ", keyStyle.Render("Plugins: "), formatValue(strings.Join(pluginValues, ", "))), + ) + + // Mode Options + modeOptions := lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "🛑 ", keyStyle.Render("BlackStatus: "), formatValue(pkg.BlackStatus)), + lipgloss.JoinHorizontal(lipgloss.Left, "✅ ", keyStyle.Render("WhiteStatus: "), formatValue(pkg.WhiteStatus)), + lipgloss.JoinHorizontal(lipgloss.Left, "🔄 ", keyStyle.Render("FuzzyStatus: "), formatValue(pkg.FuzzyStatus)), + lipgloss.JoinHorizontal(lipgloss.Left, "🔒 ", keyStyle.Render("UniqueStatus: "), formatValue(pkg.UniqueStatus)), + lipgloss.JoinHorizontal(lipgloss.Left, "🔑 ", keyStyle.Render("Unique: "), formatValue(opt.Unique)), + ) + + // Misc Options + miscOptions := lipgloss.JoinVertical(lipgloss.Left, + lipgloss.JoinHorizontal(lipgloss.Left, "⏱ ", keyStyle.Render("Timeout: "), formatValue(opt.Timeout)), + lipgloss.JoinHorizontal(lipgloss.Left, "📈 ", keyStyle.Render("PoolSize: "), formatValue(opt.PoolSize)), + lipgloss.JoinHorizontal(lipgloss.Left, "🧵 ", keyStyle.Render("Threads: "), formatValue(opt.Threads)), + lipgloss.JoinHorizontal(lipgloss.Left, "🌍 ", keyStyle.Render("Proxy: "), formatValue(opt.Proxy)), + ) + + // 将所有内容拼接在一起 + content := lipgloss.JoinVertical(lipgloss.Left, + inputOptions, + outputOptions, + pluginOptions, + modeOptions, + miscOptions, + ) + + // 使用正确的方式添加 padding,并居中显示内容 + contentWithPadding := lipgloss.NewStyle().PaddingLeft(padding).Render(content) + + // 使用 Place 方法来将整个内容居中显示 + return lipgloss.Place(panelWidth+padding*2, 0, lipgloss.Center, lipgloss.Center, + lipgloss.JoinVertical(lipgloss.Center, + divider, // 顶部分割线 + contentWithPadding, + divider, // 底部分割线 + ), + ) } func (opt *Option) BuildPlugin(r *Runner) error { @@ -501,7 +610,6 @@ func (opt *Option) BuildPlugin(r *Runner) error { r.bruteMod = true } - opt.PrintPlugin() if r.bruteMod { logs.Log.Important("enabling brute mod, because of enabled brute plugin") } @@ -670,7 +778,6 @@ func (opt *Option) BuildWords(r *Runner) error { }) } - logs.Log.Importantf("%s mod, Loaded %d dictionaries, %d rules and %d decorators", opt.Mod, len(opt.Dictionaries), len(opt.Rules), len(r.Fns)) return nil } diff --git a/internal/utils.go b/internal/utils.go index 8aea228..03ffaba 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -14,3 +14,9 @@ package internal // }) // } //} + +var ConfigTemplate = ` +----------------------------------------------------------- + +----------------------------------------------------------- +`