Merge pull request #54 from chainreactors/dev

merge v1.0.1
This commit is contained in:
M09Ic 2024-08-06 16:53:00 +08:00 committed by GitHub
commit 8bf4b374ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 56 additions and 53 deletions

View File

@ -15,7 +15,7 @@ import (
"time" "time"
) )
var ver = "v1.0.0" var ver = "v1.0.1"
var DefaultConfig = "config.yaml" var DefaultConfig = "config.yaml"
func init() { func init() {
@ -44,13 +44,19 @@ func Spray() {
WIKI: https://chainreactors.github.io/wiki/spray WIKI: https://chainreactors.github.io/wiki/spray
QUICKSTART: QUICKSTART:
simple example: basic:
spray -u http://example.com
basic cidr and port:
spray -i example -p top2,top3
simple brute:
spray -u http://example.com -d wordlist1.txt -d wordlist2.txt spray -u http://example.com -d wordlist1.txt -d wordlist2.txt
mask-base wordlist: mask-base brute with wordlist:
spray -u http://example.com -w "/aaa/bbb{?l#4}/ccc" spray -u http://example.com -w "/aaa/bbb{?l#4}/ccc"
rule-base wordlist: rule-base brute with wordlist:
spray -u http://example.com -r rule.txt -d 1.txt spray -u http://example.com -r rule.txt -d 1.txt
list input spray: list input spray:
@ -127,13 +133,6 @@ func Spray() {
} }
ctx, canceler := context.WithTimeout(context.Background(), time.Duration(runner.Deadline)*time.Second) ctx, canceler := context.WithTimeout(context.Background(), time.Duration(runner.Deadline)*time.Second)
err = runner.Prepare(ctx)
if err != nil {
logs.Log.Errorf(err.Error())
return
}
go func() { go func() {
exitChan := make(chan os.Signal, 2) exitChan := make(chan os.Signal, 2)
signal.Notify(exitChan, os.Interrupt, syscall.SIGTERM) signal.Notify(exitChan, os.Interrupt, syscall.SIGTERM)
@ -154,10 +153,11 @@ func Spray() {
}() }()
}() }()
if runner.IsCheck { err = runner.Prepare(ctx)
runner.RunWithCheck(ctx) if err != nil {
} else { logs.Log.Errorf(err.Error())
runner.Run(ctx) return
} }
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }

2
go.mod
View File

@ -9,7 +9,7 @@ require (
github.com/chainreactors/fingers v0.0.0-20240716172449-2fc3147b9c2a github.com/chainreactors/fingers v0.0.0-20240716172449-2fc3147b9c2a
github.com/chainreactors/logs v0.0.0-20240207121836-c946f072f81f github.com/chainreactors/logs v0.0.0-20240207121836-c946f072f81f
github.com/chainreactors/parsers v0.0.0-20240708072709-07deeece7ce2 github.com/chainreactors/parsers v0.0.0-20240708072709-07deeece7ce2
github.com/chainreactors/utils v0.0.0-20240716182459-e85f2b01ee16 github.com/chainreactors/utils v0.0.0-20240805193040-ff3b97aa3c3f
github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508 github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508
github.com/expr-lang/expr v1.16.9 github.com/expr-lang/expr v1.16.9
github.com/gookit/config/v2 v2.2.5 github.com/gookit/config/v2 v2.2.5

2
go.sum
View File

@ -98,6 +98,8 @@ github.com/chainreactors/utils v0.0.0-20240704062557-662d623b74f4/go.mod h1:JA4e
github.com/chainreactors/utils v0.0.0-20240715080349-d2d0484c95ed/go.mod h1:LajXuvESQwP+qCMAvlcoSXppQCjuLlBrnQpu9XQ1HtU= github.com/chainreactors/utils v0.0.0-20240715080349-d2d0484c95ed/go.mod h1:LajXuvESQwP+qCMAvlcoSXppQCjuLlBrnQpu9XQ1HtU=
github.com/chainreactors/utils v0.0.0-20240716182459-e85f2b01ee16 h1:TCOshCp7PrWqhP/HSAM5kT3VxoOe7EoJbRseyoSX3RM= github.com/chainreactors/utils v0.0.0-20240716182459-e85f2b01ee16 h1:TCOshCp7PrWqhP/HSAM5kT3VxoOe7EoJbRseyoSX3RM=
github.com/chainreactors/utils v0.0.0-20240716182459-e85f2b01ee16/go.mod h1:LajXuvESQwP+qCMAvlcoSXppQCjuLlBrnQpu9XQ1HtU= github.com/chainreactors/utils v0.0.0-20240716182459-e85f2b01ee16/go.mod h1:LajXuvESQwP+qCMAvlcoSXppQCjuLlBrnQpu9XQ1HtU=
github.com/chainreactors/utils v0.0.0-20240805193040-ff3b97aa3c3f h1:2NKmadFYP9vCwC0YrazgttFACleOhxScTPzg0i76YAY=
github.com/chainreactors/utils v0.0.0-20240805193040-ff3b97aa3c3f/go.mod h1:LajXuvESQwP+qCMAvlcoSXppQCjuLlBrnQpu9XQ1HtU=
github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508 h1:iT4HWkoZzUAfQYcQMRH8XyrMau9tCVE0zSuFQnkhrqw= github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508 h1:iT4HWkoZzUAfQYcQMRH8XyrMau9tCVE0zSuFQnkhrqw=
github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508/go.mod h1:DUDx7PdsMEm5PvVhzkFyppzpiUhQb8dOJaWjVc1SMVk= github.com/chainreactors/words v0.4.1-0.20240510105042-5ba5c2edc508/go.mod h1:DUDx7PdsMEm5PvVhzkFyppzpiUhQb8dOJaWjVc1SMVk=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=

View File

@ -1,8 +1,8 @@
package ihttp package ihttp
import ( import (
"bytes"
"github.com/chainreactors/logs" "github.com/chainreactors/logs"
"github.com/chainreactors/utils/httputils"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
"io" "io"
"net/http" "net/http"
@ -93,15 +93,7 @@ func (r *Response) Header() []byte {
if r.FastResponse != nil { if r.FastResponse != nil {
return r.FastResponse.Header.Header() return r.FastResponse.Header.Header()
} else if r.StandardResponse != nil { } else if r.StandardResponse != nil {
var header bytes.Buffer return append(httputils.ReadRawHeader(r.StandardResponse), []byte("\r\n")...)
header.WriteString(r.StandardResponse.Proto + " " + r.StandardResponse.Status)
for k, v := range r.StandardResponse.Header {
for _, i := range v {
header.WriteString(k + ": " + i + "\r\n")
}
}
header.WriteString("\r\n")
return header.Bytes()
} else { } else {
return nil return nil
} }

View File

@ -111,6 +111,7 @@ type PluginOptions struct {
Advance bool `short:"a" long:"advance" description:"Bool, enable all plugin" config:"all" ` Advance bool `short:"a" long:"advance" description:"Bool, enable all plugin" config:"all" `
Extracts []string `long:"extract" description:"Strings, extract response, e.g.: --extract js --extract ip --extract version:(.*?)" config:"extract"` Extracts []string `long:"extract" description:"Strings, extract response, e.g.: --extract js --extract ip --extract version:(.*?)" config:"extract"`
ExtractConfig string `long:"extract-config" description:"String, extract config filename" config:"extract-config"` ExtractConfig string `long:"extract-config" description:"String, extract config filename" config:"extract-config"`
Active bool `long:"active" description:"Bool, enable active finger path"`
Recon bool `long:"recon" description:"Bool, enable recon" config:"recon"` Recon bool `long:"recon" description:"Bool, enable recon" config:"recon"`
Bak bool `long:"bak" description:"Bool, enable bak found" config:"bak"` Bak bool `long:"bak" description:"Bool, enable bak found" config:"bak"`
FileBak bool `long:"file-bak" description:"Bool, enable valid result bak found, equal --append-rule rule/filebak.txt" config:"file-bak"` FileBak bool `long:"file-bak" description:"Bool, enable valid result bak found, equal --append-rule rule/filebak.txt" config:"file-bak"`
@ -312,28 +313,45 @@ func (opt *Option) NewRunner() (*Runner, error) {
pkg.Extractors["recon"] = pkg.ExtractRegexps["pentest"] pkg.Extractors["recon"] = pkg.ExtractRegexps["pentest"]
} }
if opt.Finger {
pkg.EnableAllFingerEngine = true
}
// brute only
if opt.Advance { if opt.Advance {
r.Crawl = true r.Crawl = true
r.Finger = true r.Finger = true
r.Bak = true r.Bak = true
r.Common = true r.Common = true
r.Active = true
pkg.EnableAllFingerEngine = true pkg.EnableAllFingerEngine = true
pkg.Extractors["recon"] = pkg.ExtractRegexps["pentest"] pkg.Extractors["recon"] = pkg.ExtractRegexps["pentest"]
r.IsCheck = false
opt.AppendRule = append(opt.AppendRule, "filebak") opt.AppendRule = append(opt.AppendRule, "filebak")
} }
if opt.FileBak { if opt.FileBak {
r.IsCheck = false
opt.AppendRule = append(opt.AppendRule, "filebak") opt.AppendRule = append(opt.AppendRule, "filebak")
} }
if opt.Common { if opt.Common {
r.IsCheck = false
r.AppendWords = append(r.AppendWords, mask.SpecialWords["common_file"]...) r.AppendWords = append(r.AppendWords, mask.SpecialWords["common_file"]...)
} }
if opt.Finger {
if opt.Active {
r.IsCheck = false
r.AppendWords = append(r.AppendWords, pkg.ActivePath...) r.AppendWords = append(r.AppendWords, pkg.ActivePath...)
pkg.EnableAllFingerEngine = true }
if opt.Crawl {
r.IsCheck = false
} }
opt.PrintPlugin() opt.PrintPlugin()
if r.IsCheck == false {
logs.Log.Important("enabling brute mod, because of enabled brute plugin")
}
if opt.NoScope { if opt.NoScope {
r.Scope = []string{"*"} r.Scope = []string{"*"}
@ -497,6 +515,7 @@ func (opt *Option) PrintPlugin() {
if opt.RetryCount > 0 { if opt.RetryCount > 0 {
s.WriteString("Retry Count: " + strconv.Itoa(opt.RetryCount)) s.WriteString("Retry Count: " + strconv.Itoa(opt.RetryCount))
} }
if s.Len() > 0 { if s.Len() > 0 {
logs.Log.Important(s.String()) logs.Log.Important(s.String())
} }
@ -521,7 +540,8 @@ func (opt *Option) BuildWords(r *Runner) error {
logs.Log.Logf(pkg.LogVerbose, "Loaded %d word from %s", len(dicts[i]), f) logs.Log.Logf(pkg.LogVerbose, "Loaded %d word from %s", len(dicts[i]), f)
} }
if len(dicts) == 0 {
if len(dicts) == 0 && opt.Word == "" {
r.IsCheck = true r.IsCheck = true
} }

View File

@ -50,35 +50,21 @@ type CheckPool struct {
func (pool *CheckPool) Run(ctx context.Context, offset, limit int) { func (pool *CheckPool) Run(ctx context.Context, offset, limit int) {
pool.Worder.Run() pool.Worder.Run()
var done bool
// 挂起一个监控goroutine, 每100ms判断一次done, 如果已经done, 则关闭closeCh, 然后通过Loop中的select case closeCh去break, 实现退出
go func() {
for {
if done {
pool.wg.Wait()
close(pool.closeCh)
return
}
time.Sleep(100 * time.Millisecond)
}
}()
Loop: Loop:
for { for {
select { select {
case u, ok := <-pool.Worder.C: case u, ok := <-pool.Worder.C:
if !ok { if !ok {
done = true break Loop
continue
} }
if pool.reqCount < offset { if pool.reqCount < offset {
pool.reqCount++ pool.reqCount++
continue break Loop
} }
if pool.reqCount > limit { if pool.reqCount > limit {
continue break Loop
} }
pool.wg.Add(1) pool.wg.Add(1)
@ -96,7 +82,7 @@ Loop:
break Loop break Loop
} }
} }
pool.wg.Wait()
pool.Close() pool.Close()
} }

View File

@ -111,6 +111,7 @@ func (r *Runner) AppendFunction(fn func(string) []string) {
} }
func (r *Runner) Prepare(ctx context.Context) error { func (r *Runner) Prepare(ctx context.Context) error {
r.OutputHandler()
var err error var err error
if r.IsCheck { if r.IsCheck {
// 仅check, 类似httpx // 仅check, 类似httpx
@ -138,6 +139,7 @@ func (r *Runner) Prepare(ctx context.Context) error {
checkPool.Run(ctx, r.Offset, r.Count) checkPool.Run(ctx, r.Offset, r.Count)
r.poolwg.Done() r.poolwg.Done()
}) })
r.RunWithCheck(ctx)
} else { } else {
// 完整探测模式 // 完整探测模式
go func() { go func() {
@ -214,12 +216,12 @@ func (r *Runner) Prepare(ctx context.Context) error {
r.PrintStat(brutePool) r.PrintStat(brutePool)
r.Done() r.Done()
}) })
r.Run(ctx)
} }
if err != nil { if err != nil {
return err return err
} }
r.OutputHandler()
return nil return nil
} }

View File

@ -36,9 +36,10 @@ func NewBaseline(u, host string, resp *ihttp.Response) *Baseline {
bl.HeaderLength = len(bl.Header) bl.HeaderLength = len(bl.Header)
if i := resp.ContentLength(); ihttp.CheckBodySize(i) { if i := resp.ContentLength(); ihttp.CheckBodySize(i) {
body := resp.Body() if body := resp.Body(); body != nil {
bl.Body = make([]byte, len(body)) bl.Body = make([]byte, len(body))
copy(bl.Body, body) copy(bl.Body, body)
}
if i == -1 { if i == -1 {
bl.Chunked = true bl.Chunked = true

@ -1 +1 @@
Subproject commit 3e85234341b95f7e6e45b31468311f01093ac970 Subproject commit f2980b8d312c8088f3947d914499e96cfc40d975