mirror of
https://github.com/chainreactors/spray.git
synced 2025-05-06 18:51:22 +00:00
给全局的输出添加配色, 可以使用--no-color或-q关闭
This commit is contained in:
parent
34e544deaf
commit
073cf2a095
@ -284,7 +284,7 @@ spray支持断点续传, 可以通过`--resume-from`参数指定断点文件.
|
||||
断点续传支持比命令行更自由的字典配置. 每个任务都可以拥有独立的-w/-r/-d配置. 因此某些特殊情况下要进行批量操作, 可以通过脚本去构造对应的stat文件, 实现更加自由的任务配置.
|
||||
|
||||
### 递归
|
||||
spray并不鼓励使用递归, 因为spray的定位是批量从反代/cdn中发现隐形资产. 不管是因为批量, 还是因为反代/cdn, 99.9的情况都用不到递归.
|
||||
spray并不鼓励使用递归, 因为spray的定位是批量从反代/cdn中发现隐形资产. 不管是因为批量, 还是因为反代/cdn, 绝大多数的情况都用不到递归.
|
||||
|
||||
但为了兼容某些极为罕见的情况, spray依旧保留了递归的功能.
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -7,9 +7,9 @@ require (
|
||||
github.com/chainreactors/go-metrics v0.0.0-20220926021830-24787b7a10f8
|
||||
github.com/chainreactors/gogo/v2 v2.10.1
|
||||
github.com/chainreactors/ipcs v0.0.13
|
||||
github.com/chainreactors/logs v0.6.2
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214153111-85f123ff6580
|
||||
github.com/chainreactors/parsers v0.2.9-0.20221210155102-cc0814762410
|
||||
github.com/chainreactors/words v0.3.2-0.20221214062855-48dff09b01ad
|
||||
github.com/chainreactors/words v0.3.2-0.20221214154622-381fc37abdf9
|
||||
)
|
||||
|
||||
require (
|
||||
|
10
go.sum
10
go.sum
@ -19,6 +19,14 @@ github.com/chainreactors/ipcs v0.0.13/go.mod h1:E9M3Ohyq0TYQLlV4i2dbM9ThBZB1Nnd7
|
||||
github.com/chainreactors/logs v0.6.1/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/logs v0.6.2 h1:Yz5oayjwxO6KkjfjnmtT5WKbWjTaBdttFcneaFTpBe0=
|
||||
github.com/chainreactors/logs v0.6.2/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214130332-9bc5319887fe h1:FRMBKyuuh6EoHefqprP+pSblHrUxTaSp9GPJahYa+Fc=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214130332-9bc5319887fe/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214130646-2e08f98a1f71 h1:SpyPYjRihGyBiqoMUggXzCc4t9A0tmAvYdjghDG8s+M=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214130646-2e08f98a1f71/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214152543-60422cf64610 h1:ErODIlY9NmlrwEi6np3bm7HmuRZSaH3+ID2fJ2ViUpM=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214152543-60422cf64610/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214153111-85f123ff6580 h1:28gbL1t+Mm4AoP1MeKM9oeSHoPcUwIrzrLtmdusHMIo=
|
||||
github.com/chainreactors/logs v0.7.1-0.20221214153111-85f123ff6580/go.mod h1:Y0EtAnoF0kiASIJUnXN0pcOt420iRpHOAnOhEphzRHA=
|
||||
github.com/chainreactors/parsers v0.2.9-0.20221210155102-cc0814762410 h1:K7EV0wtUuN6Rvh/MgqaBXyElD3guPsgNR5kF8nrV7iw=
|
||||
github.com/chainreactors/parsers v0.2.9-0.20221210155102-cc0814762410/go.mod h1:Z9weht+lnFCk7UcwqFu6lXpS7u5vttiy0AJYOAyCCLA=
|
||||
github.com/chainreactors/words v0.3.2-0.20221212161820-bae5f18558db h1:Rv6mcLAKXRXoZuifCwGTlXnuDbDpbDKC0JsTI1op/OA=
|
||||
@ -27,6 +35,8 @@ github.com/chainreactors/words v0.3.2-0.20221214061028-a7cf9f9f8ddb h1:9AV8SH+Sv
|
||||
github.com/chainreactors/words v0.3.2-0.20221214061028-a7cf9f9f8ddb/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
|
||||
github.com/chainreactors/words v0.3.2-0.20221214062855-48dff09b01ad h1:uL3TIQgvFY7dLoX0tAzIIXilCPIcNeLz/124gs+SA/Q=
|
||||
github.com/chainreactors/words v0.3.2-0.20221214062855-48dff09b01ad/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
|
||||
github.com/chainreactors/words v0.3.2-0.20221214154622-381fc37abdf9 h1:IUNopSuorfINmn4pOuSwZtxJbg8zsRIZ67a33SiYoQ0=
|
||||
github.com/chainreactors/words v0.3.2-0.20221214154622-381fc37abdf9/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -92,6 +92,7 @@ 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 (seconds)"`
|
||||
Debug bool `long:"debug" description:"Bool, output debug info"`
|
||||
NoColor bool `long:"no-color" description:"Bool, no color"`
|
||||
Quiet bool `short:"q" long:"quiet" description:"Bool, Quiet"`
|
||||
NoBar bool `long:"no-bar" description:"Bool, No progress bar"`
|
||||
Mod string `short:"m" long:"mod" default:"path" choice:"path" choice:"host" description:"String, path/host spray"`
|
||||
@ -139,11 +140,19 @@ func (opt *Option) PrepareRunner() (*Runner, error) {
|
||||
}
|
||||
}
|
||||
// 一些全局变量初始化
|
||||
if !opt.NoColor {
|
||||
logs.Log.Color = true
|
||||
logs.DefaultColorMap[logs.Info] = logs.PurpleBold
|
||||
logs.DefaultColorMap[logs.Important] = logs.Green
|
||||
r.Color = true
|
||||
}
|
||||
if opt.Debug {
|
||||
logs.Log.Level = logs.Debug
|
||||
}
|
||||
if opt.Quiet {
|
||||
logs.Log.Quiet = true
|
||||
logs.Log.Color = false
|
||||
r.Color = false
|
||||
}
|
||||
if !(opt.Quiet || opt.NoBar) {
|
||||
r.Progress.Start()
|
||||
|
@ -230,7 +230,7 @@ func (pool *Pool) Init() error {
|
||||
return fmt.Errorf(pool.index.String())
|
||||
}
|
||||
pool.index.Collect()
|
||||
logs.Log.Important("[baseline.index] " + pool.index.String())
|
||||
logs.Log.Info("[baseline.index] " + pool.index.String())
|
||||
|
||||
pool.initwg.Add(1)
|
||||
pool.reqPool.Invoke(newUnit(pkg.RandPath(), InitRandomSource))
|
||||
@ -240,14 +240,14 @@ func (pool *Pool) Init() error {
|
||||
return fmt.Errorf(pool.random.String())
|
||||
}
|
||||
pool.random.Collect()
|
||||
logs.Log.Important("[baseline.random] " + pool.random.String())
|
||||
logs.Log.Info("[baseline.random] " + pool.random.String())
|
||||
|
||||
if pool.random.RedirectURL != "" {
|
||||
// 自定协议升级
|
||||
// 某些网站http会重定向到https, 如果发现随机目录出现这种情况, 则自定将baseurl升级为https
|
||||
rurl, err := url.Parse(pool.random.RedirectURL)
|
||||
if err == nil && rurl.Hostname() == pool.random.Url.Hostname() && pool.random.Url.Scheme == "http" && rurl.Scheme == "https" {
|
||||
logs.Log.Importantf("baseurl %s upgrade http to https", pool.BaseURL)
|
||||
logs.Log.Infof("baseurl %s upgrade http to https", pool.BaseURL)
|
||||
pool.BaseURL = strings.Replace(pool.BaseURL, "http", "https", 1)
|
||||
}
|
||||
}
|
||||
@ -435,7 +435,7 @@ func (pool *Pool) addFuzzyBaseline(bl *pkg.Baseline) {
|
||||
pool.locker.Lock()
|
||||
pool.baselines[bl.Status] = bl
|
||||
pool.locker.Unlock()
|
||||
logs.Log.Importantf("[baseline.%dinit] %s", bl.Status, bl.String())
|
||||
logs.Log.Infof("[baseline.%dinit] %s", bl.Status, bl.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,7 @@ type Runner struct {
|
||||
CheckPeriod int
|
||||
ErrPeriod int
|
||||
BreakThreshold int
|
||||
Color bool
|
||||
CheckOnly bool
|
||||
Force bool
|
||||
IgnoreWaf bool
|
||||
@ -198,8 +199,14 @@ func (r *Runner) Prepare(ctx context.Context) error {
|
||||
}
|
||||
|
||||
pool.Run(ctx, pool.Statistor.Offset, limit)
|
||||
logs.Log.Important(pool.Statistor.String())
|
||||
logs.Log.Important(pool.Statistor.Detail())
|
||||
if r.Color {
|
||||
logs.Log.Important(pool.Statistor.ColorString())
|
||||
logs.Log.Important(pool.Statistor.ColorDetail())
|
||||
} else {
|
||||
logs.Log.Important(pool.Statistor.String())
|
||||
logs.Log.Important(pool.Statistor.Detail())
|
||||
}
|
||||
|
||||
if r.StatFile != nil {
|
||||
r.StatFile.SafeWrite(pool.Statistor.Json())
|
||||
r.StatFile.SafeSync()
|
||||
@ -314,13 +321,26 @@ func (r *Runner) Outputting() {
|
||||
|
||||
} else {
|
||||
if len(r.Probes) > 0 {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console("[+] " + bl.Format(r.Probes) + "\n")
|
||||
if r.Color {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console(logs.GreenBold("[+] " + bl.Format(r.Probes) + "\n"))
|
||||
}
|
||||
} else {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console("[+] " + bl.Format(r.Probes) + "\n")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console("[+] " + bl.String() + "\n")
|
||||
if r.Color {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console(logs.GreenBold("[+] " + bl.ColorString() + "\n"))
|
||||
}
|
||||
} else {
|
||||
saveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console("[+] " + bl.String() + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,7 +360,12 @@ func (r *Runner) Outputting() {
|
||||
r.AddPool(&Task{baseUrl: bl.UrlString, depth: bl.RecuDepth + 1})
|
||||
}
|
||||
} else {
|
||||
logs.Log.Debug(bl.String())
|
||||
if r.Color {
|
||||
logs.Log.Debug(bl.ColorString())
|
||||
} else {
|
||||
logs.Log.Debug(bl.String())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,9 +378,13 @@ func (r *Runner) Outputting() {
|
||||
r.FuzzyFile.SafeWrite(bl.Jsonify() + "\n")
|
||||
}
|
||||
} else {
|
||||
fuzzySaveFunc = func(bl *pkg.Baseline) {
|
||||
if r.Fuzzy {
|
||||
logs.Log.Console("[baseline.fuzzy] " + bl.String() + "\n")
|
||||
if r.Color {
|
||||
fuzzySaveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console(logs.GreenBold("[fuzzy] " + bl.ColorString() + "\n"))
|
||||
}
|
||||
} else {
|
||||
fuzzySaveFunc = func(bl *pkg.Baseline) {
|
||||
logs.Log.Console("[fuzzy] " + bl.String() + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/chainreactors/gogo/v2/pkg/utils"
|
||||
"github.com/chainreactors/logs"
|
||||
"github.com/chainreactors/parsers"
|
||||
"github.com/chainreactors/spray/pkg/ihttp"
|
||||
"net/url"
|
||||
@ -227,6 +228,47 @@ func (bl *Baseline) Format(probes []string) string {
|
||||
return line.String()
|
||||
}
|
||||
|
||||
func (bl *Baseline) ColorString() string {
|
||||
var line strings.Builder
|
||||
if bl.FrontURL != "" {
|
||||
line.WriteString("\t")
|
||||
line.WriteString(logs.CyanLine(bl.FrontURL))
|
||||
line.WriteString(" --> ")
|
||||
}
|
||||
line.WriteString(logs.GreenLine(bl.UrlString))
|
||||
if bl.Host != "" {
|
||||
line.WriteString(" (" + bl.Host + ")")
|
||||
}
|
||||
|
||||
if bl.Reason != "" {
|
||||
line.WriteString(" [reason: ")
|
||||
line.WriteString(logs.YellowBold(bl.Reason))
|
||||
line.WriteString("]")
|
||||
}
|
||||
if bl.ErrString != "" {
|
||||
line.WriteString(" [err: ")
|
||||
line.WriteString(logs.RedBold(bl.ErrString))
|
||||
line.WriteString("]")
|
||||
return line.String()
|
||||
}
|
||||
|
||||
line.WriteString(" - ")
|
||||
line.WriteString(logs.GreenBold(strconv.Itoa(bl.Status)))
|
||||
line.WriteString(" - ")
|
||||
line.WriteString(logs.Blue(strconv.Itoa(bl.BodyLength)))
|
||||
line.WriteString(" - ")
|
||||
line.WriteString(logs.Blue(strconv.Itoa(int(bl.Spended)) + "ms"))
|
||||
line.WriteString(logs.GreenLine(bl.Additional("title")))
|
||||
line.WriteString(logs.Blue(bl.Frameworks.String()))
|
||||
line.WriteString(logs.Blue(bl.Extracteds.String()))
|
||||
if bl.RedirectURL != "" {
|
||||
line.WriteString(" --> ")
|
||||
line.WriteString(logs.CyanLine(bl.RedirectURL))
|
||||
line.WriteString(" ")
|
||||
}
|
||||
return line.String()
|
||||
}
|
||||
|
||||
func (bl *Baseline) String() string {
|
||||
var line strings.Builder
|
||||
if bl.FrontURL != "" {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/chainreactors/logs"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -56,6 +57,21 @@ type Statistor struct {
|
||||
RuleFilter string `json:"rule_filter"`
|
||||
}
|
||||
|
||||
func (stat *Statistor) ColorString() string {
|
||||
var s strings.Builder
|
||||
s.WriteString(fmt.Sprintf("[stat] %s took %d s, request total: %s, finish: %s/%s, found: %s, check: %s, failed: %s", logs.GreenLine(stat.BaseUrl), stat.EndTime-stat.StartTime, logs.YellowBold(strconv.Itoa(int(stat.ReqTotal))), logs.YellowBold(strconv.Itoa(stat.End)), logs.YellowBold(strconv.Itoa(stat.Total)), logs.YellowBold(strconv.Itoa(stat.FoundNumber)), logs.YellowBold(strconv.Itoa(stat.CheckNumber)), logs.YellowBold(strconv.Itoa(int(stat.FailedNumber)))))
|
||||
|
||||
if stat.FuzzyNumber != 0 {
|
||||
s.WriteString(", fuzzy: " + logs.Yellow(strconv.Itoa(stat.FuzzyNumber)))
|
||||
}
|
||||
if stat.FilteredNumber != 0 {
|
||||
s.WriteString(", filtered: " + logs.Yellow(strconv.Itoa(stat.FilteredNumber)))
|
||||
}
|
||||
if stat.WafedNumber != 0 {
|
||||
s.WriteString(", wafed: " + logs.Yellow(strconv.Itoa(stat.WafedNumber)))
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
func (stat *Statistor) String() string {
|
||||
var s strings.Builder
|
||||
s.WriteString(fmt.Sprintf("[stat] %s took %d s, request total: %d, finish: %d/%d, found: %d, check: %d, failed: %d", stat.BaseUrl, stat.EndTime-stat.StartTime, stat.ReqTotal, stat.End, stat.Total, stat.FoundNumber, stat.CheckNumber, stat.FailedNumber))
|
||||
@ -85,6 +101,19 @@ func (stat *Statistor) Detail() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func (stat *Statistor) ColorDetail() string {
|
||||
var s strings.Builder
|
||||
s.WriteString("[stat] ")
|
||||
s.WriteString(stat.BaseUrl)
|
||||
for k, v := range stat.Counts {
|
||||
if k == 0 {
|
||||
continue
|
||||
}
|
||||
s.WriteString(fmt.Sprintf(" %s: %s,", logs.YellowBold(strconv.Itoa(k)), logs.YellowBold(strconv.Itoa(v))))
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func (stat *Statistor) Json() string {
|
||||
content, err := json.Marshal(stat)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user