diff --git a/cmd/cmd.go b/cmd/cmd.go index 907b7b5..da62956 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -17,7 +17,7 @@ import ( "time" ) -var ver = "" +var ver = "v0.9.3" func Spray() { var option internal.Option @@ -79,13 +79,19 @@ func Spray() { } } } - // 一些全局变量初始化 + // logs + logs.AddLevel(internal.LogVerbose, "verbose", "[=] %s {{suffix}}") if option.Debug { logs.Log.SetLevel(logs.Debug) } - logs.DefaultColorMap[logs.Info] = logs.PurpleBold - logs.DefaultColorMap[logs.Important] = logs.GreenBold + logs.Log.SetColorMap(map[logs.Level]func(string) string{ + logs.Info: logs.PurpleBold, + logs.Important: logs.GreenBold, + internal.LogVerbose: logs.Green, + }) + + // 初始化全局变量 pkg.Distance = uint8(option.SimhashDistance) ihttp.DefaultMaxBodySize = option.MaxBodyLength * 1024 internal.MaxCrawl = option.CrawlDepth diff --git a/go.mod b/go.mod index 6385f03..a513ef9 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/antonmedv/expr v1.12.5 github.com/chainreactors/files v0.0.0-20231123083421-cea5b4ad18a8 github.com/chainreactors/gogo/v2 v2.11.12-0.20231228061950-116583962e30 - github.com/chainreactors/logs v0.0.0-20231220102821-19f082ce37c1 + github.com/chainreactors/logs v0.0.0-20240207121836-c946f072f81f github.com/chainreactors/parsers v0.0.0-20231227070753-8cda94b96b6c github.com/chainreactors/utils v0.0.0-20231031063336-9477f1b23886 github.com/chainreactors/words v0.4.1-0.20240206181137-09f7a0bc8f50 diff --git a/go.sum b/go.sum index e591334..7800a2d 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,12 @@ github.com/chainreactors/gogo/v2 v2.11.12-0.20231228061950-116583962e30/go.mod h github.com/chainreactors/logs v0.0.0-20231027080134-7a11bb413460/go.mod h1:VZFqkFDGmp7/JOMeraW+YI7kTGcgz9fgc/HArVFnrGQ= github.com/chainreactors/logs v0.0.0-20231220102821-19f082ce37c1 h1:y4xbdWsmBu1aAyYez1rBN5mgFdAtPViNrsObu1aWbuk= github.com/chainreactors/logs v0.0.0-20231220102821-19f082ce37c1/go.mod h1:6Mv6W70JrtL6VClulZhmMRZnoYpcTahcDTKLMNEjK0o= +github.com/chainreactors/logs v0.0.0-20240207114427-8450f3309979 h1:y3xOkts71C7nyzjE05lcOK7YlHuPdnZgES6by7+FeIg= +github.com/chainreactors/logs v0.0.0-20240207114427-8450f3309979/go.mod h1:6Mv6W70JrtL6VClulZhmMRZnoYpcTahcDTKLMNEjK0o= +github.com/chainreactors/logs v0.0.0-20240207115900-a28fc4021dad h1:43Xu1WaPWqeawpUSPlv7OYrEvOOEi0euQuOikgIvDRc= +github.com/chainreactors/logs v0.0.0-20240207115900-a28fc4021dad/go.mod h1:6Mv6W70JrtL6VClulZhmMRZnoYpcTahcDTKLMNEjK0o= +github.com/chainreactors/logs v0.0.0-20240207121836-c946f072f81f h1:tcfp+CEdgiMvjyUzWab5edJtxUwRMSMEIkLybupIx0k= +github.com/chainreactors/logs v0.0.0-20240207121836-c946f072f81f/go.mod h1:6Mv6W70JrtL6VClulZhmMRZnoYpcTahcDTKLMNEjK0o= github.com/chainreactors/neutron v0.0.0-20231221064706-fd6aaac9c50b/go.mod h1:Q6xCl+KaPtCDIziAHegFxdHOvg6DgpA6hcUWRnQKDPk= github.com/chainreactors/parsers v0.0.0-20231218072716-fb441aff745f/go.mod h1:ZHEkgxKf9DXoley2LUjdJkiSw08MC3vcJTxfqwYt2LU= github.com/chainreactors/parsers v0.0.0-20231220104848-3a0b5a5bd8dc/go.mod h1:V2w16sBSSiBlmsDR4A0Q9PIk9+TP/6coTXv6olvTI6M= diff --git a/internal/option.go b/internal/option.go index c5305fa..1d89344 100644 --- a/internal/option.go +++ b/internal/option.go @@ -22,9 +22,7 @@ import ( var ( DefaultThreads = 20 - //DefaultTimeout = 5 - //DefaultPoolSize = 5 - //DefaultRateLimit = 0 + LogVerbose = logs.Warn - 1 ) type Option struct { @@ -120,7 +118,7 @@ type ModeOptions struct { FuzzyStatus string `long:"fuzzy-status" default:"404,403,500,501,502,503" description:"Strings (comma split), custom fuzzy status"` UniqueStatus string `long:"unique-status" default:"403" description:"Strings (comma split), custom unique status"` Unique bool `long:"unique" description:"Bool, unique response"` - RetryCount int `long:"retry" default:"1" description:"Int, retry count"` + RetryCount int `long:"retry" default:"0" description:"Int, retry count"` SimhashDistance int `long:"distance" default:"5"` } @@ -132,7 +130,8 @@ type MiscOptions struct { PoolSize int `short:"P" long:"pool" default:"5" description:"Int, Pool size"` Threads int `short:"t" long:"thread" default:"20" description:"Int, number of threads per pool"` Debug bool `long:"debug" description:"Bool, output debug info"` - Version bool `short:"v" long:"version" description:"Bool, show version"` + Version bool `long:"version" description:"Bool, show version"` + Verbose []bool `short:"v" description:"Bool, log verbose level ,default 0, level1: -v level2 -vv "` Quiet bool `short:"q" long:"quiet" description:"Bool, Quiet"` NoColor bool `long:"no-color" description:"Bool, no color"` NoBar bool `long:"no-bar" description:"Bool, No progress bar"` @@ -189,6 +188,9 @@ func (opt *Option) PrepareRunner() (*Runner, error) { r.Progress.Start() logs.Log.SetOutput(r.Progress.Bypass()) } + if len(opt.Verbose) == 1 { + logs.Log.SetLevel(LogVerbose) + } // configuration if opt.Force { @@ -244,10 +246,13 @@ func (opt *Option) PrepareRunner() (*Runner, error) { if len(opt.AppendRule) > 0 { s.WriteString("file bak enable; ") } + if r.RetryCount > 0 { s.WriteString("Retry Count: " + strconv.Itoa(r.RetryCount)) } - logs.Log.Important(s.String()) + if s.Len() > 0 { + logs.Log.Important(s.String()) + } if opt.NoScope { r.Scope = []string{"*"} @@ -281,7 +286,8 @@ func (opt *Option) PrepareRunner() (*Runner, error) { if err != nil { return nil, err } - logs.Log.Importantf("Loaded %d word from %s", len(dicts[i]), f) + + logs.Log.Logf(LogVerbose, "Loaded %d word from %s", len(dicts[i]), f) } } @@ -318,7 +324,7 @@ func (opt *Option) PrepareRunner() (*Runner, error) { return nil, fmt.Errorf("%s %w", opt.Word, err) } if len(r.Wordlist) > 0 { - logs.Log.Importantf("Parsed %d words by %s", len(r.Wordlist), opt.Word) + logs.Log.Logf(LogVerbose, "Parsed %d words by %s", len(r.Wordlist), opt.Word) } if opt.Rules != nil { @@ -476,7 +482,7 @@ func (opt *Option) PrepareRunner() (*Runner, error) { } r.Tasks = tasks - logs.Log.Importantf("Loaded %d urls from %s", len(tasks), taskfrom) + logs.Log.Logf(LogVerbose, "Loaded %d urls from %s", len(tasks), taskfrom) // 类似dirsearch中的 if opt.Extensions != "" { @@ -553,7 +559,7 @@ func (opt *Option) PrepareRunner() (*Runner, error) { }) } - logs.Log.Importantf("Loaded %d dictionaries and %d decorators", len(opt.Dictionaries), len(r.Fns)) + logs.Log.Logf(LogVerbose, "Loaded %d dictionaries and %d decorators", len(opt.Dictionaries), len(r.Fns)) if opt.Match != "" { exp, err := expr.Compile(opt.Match, expr.Patch(&bytesPatcher{})) diff --git a/internal/pool.go b/internal/pool.go index 8b6897e..1b29593 100644 --- a/internal/pool.go +++ b/internal/pool.go @@ -148,14 +148,14 @@ func (pool *Pool) genReq(mod pkg.SprayMod, s string) (*ihttp.Request, error) { func (pool *Pool) Init() error { pool.initwg.Add(2) if pool.Index != "" { - logs.Log.Importantf("custom index url: %s", BaseURL(pool.url)+FormatURL(BaseURL(pool.url), pool.Index)) + logs.Log.Logf(LogVerbose, "custom index url: %s", BaseURL(pool.url)+FormatURL(BaseURL(pool.url), pool.Index)) pool.reqPool.Invoke(newUnit(pool.Index, InitIndexSource)) } else { pool.reqPool.Invoke(newUnit(pool.url.Path, InitIndexSource)) } if pool.Random != "" { - logs.Log.Importantf("custom random url: %s", BaseURL(pool.url)+FormatURL(BaseURL(pool.url), pool.Random)) + logs.Log.Logf(LogVerbose, "custom random url: %s", BaseURL(pool.url)+FormatURL(BaseURL(pool.url), pool.Random)) pool.reqPool.Invoke(newUnit(pool.Random, InitRandomSource)) } else { pool.reqPool.Invoke(newUnit(pool.safePath(pkg.RandPath()), InitRandomSource)) @@ -169,13 +169,13 @@ func (pool *Pool) Init() error { if pool.index.Chunked && pool.ClientType == ihttp.FAST { logs.Log.Warn("chunk encoding! buf current client FASTHTTP not support chunk decode") } - logs.Log.Info("[baseline.index] " + pool.index.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) + logs.Log.Logf(LogVerbose, "[baseline.index] "+pool.index.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) // 检测基本访问能力 if pool.random.ErrString != "" { logs.Log.Error(pool.index.String()) return fmt.Errorf(pool.index.ErrString) } - logs.Log.Info("[baseline.random] " + pool.random.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) + logs.Log.Logf(LogVerbose, "[baseline.random] "+pool.random.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) // 某些网站http会重定向到https, 如果发现随机目录出现这种情况, 则自定将baseurl升级为https if pool.url.Scheme == "http" { @@ -818,7 +818,7 @@ func (pool *Pool) addFuzzyBaseline(bl *pkg.Baseline) { pool.waiter.Add(1) pool.doCrawl(bl) // 非有效页面也可能存在一些特殊的url可以用来爬取 pool.baselines[bl.Status] = bl - logs.Log.Infof("[baseline.%dinit] %s", bl.Status, bl.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) + logs.Log.Logf(LogVerbose, "[baseline.%dinit] %s", bl.Status, bl.Format([]string{"status", "length", "spend", "title", "frame", "redirect"})) } } diff --git a/internal/runner.go b/internal/runner.go index d51ded0..ce60b56 100644 --- a/internal/runner.go +++ b/internal/runner.go @@ -219,6 +219,7 @@ func (r *Runner) Prepare(ctx context.Context) error { limit = pool.Statistor.Total } pool.bar = pkg.NewBar(config.BaseURL, limit-pool.Statistor.Offset, r.Progress) + logs.Log.Importantf("[pool] task: %s, total %d words, %d threads, proxy: %s", pool.BaseURL, limit-pool.Statistor.Offset, pool.Thread, pool.ProxyAddr) err = pool.Init() if err != nil { pool.Statistor.Error = err.Error() @@ -350,14 +351,14 @@ func (r *Runner) PrintStat(pool *Pool) { if r.Color { logs.Log.Important(pool.Statistor.ColorString()) if pool.Statistor.Error == "" { - logs.Log.Important(pool.Statistor.ColorCountString()) - logs.Log.Important(pool.Statistor.ColorSourceString()) + pool.Statistor.PrintColorCount() + pool.Statistor.PrintColorSource() } } else { logs.Log.Important(pool.Statistor.String()) if pool.Statistor.Error == "" { - logs.Log.Important(pool.Statistor.CountString()) - logs.Log.Important(pool.Statistor.SourceString()) + pool.Statistor.PrintCount() + pool.Statistor.PrintSource() } } diff --git a/pkg/statistor.go b/pkg/statistor.go index 7201e3c..47c16fe 100644 --- a/pkg/statistor.go +++ b/pkg/statistor.go @@ -92,7 +92,10 @@ func (stat *Statistor) String() string { return s.String() } -func (stat *Statistor) CountString() string { +func (stat *Statistor) PrintCount() { + if len(stat.Counts) == 0 { + return + } var s strings.Builder s.WriteString("[stat] ") s.WriteString(stat.BaseUrl) @@ -102,20 +105,26 @@ func (stat *Statistor) CountString() string { } s.WriteString(fmt.Sprintf(" %d: %d,", k, v)) } - return s.String() + logs.Log.Important(s.String()) } -func (stat *Statistor) SourceString() string { +func (stat *Statistor) PrintSource() { + if len(stat.Sources) == 0 { + return + } var s strings.Builder s.WriteString("[stat] ") s.WriteString(stat.BaseUrl) for k, v := range stat.Sources { s.WriteString(fmt.Sprintf(" %s: %d,", parsers.GetSpraySourceName(k), v)) } - return s.String() + logs.Log.Important(s.String()) } -func (stat *Statistor) ColorCountString() string { +func (stat *Statistor) PrintColorCount() { + if len(stat.Counts) == 0 { + return + } var s strings.Builder s.WriteString("[stat] ") s.WriteString(stat.BaseUrl) @@ -125,17 +134,20 @@ func (stat *Statistor) ColorCountString() string { } s.WriteString(fmt.Sprintf(" %s: %s,", logs.Cyan(strconv.Itoa(k)), logs.YellowBold(strconv.Itoa(v)))) } - return s.String() + logs.Log.Important(s.String()) } -func (stat *Statistor) ColorSourceString() string { +func (stat *Statistor) PrintColorSource() { + if len(stat.Sources) == 0 { + return + } var s strings.Builder s.WriteString("[stat] ") s.WriteString(stat.BaseUrl) for k, v := range stat.Sources { s.WriteString(fmt.Sprintf(" %s: %s,", logs.Cyan(parsers.GetSpraySourceName(k)), logs.YellowBold(strconv.Itoa(v)))) } - return s.String() + logs.Log.Important(s.String()) } func (stat *Statistor) Json() string {