实现--bak, 自动生成字典爆破备份文件

This commit is contained in:
M09Ic 2023-01-06 00:48:13 +08:00
parent 26cc384de0
commit bb92c994cd
11 changed files with 118 additions and 36 deletions

View File

@ -55,10 +55,6 @@ func Spray() {
if err != nil {
utils.Fatal(err.Error())
}
err = pkg.LoadRules()
if err != nil {
utils.Fatal(err.Error())
}
var runner *internal.Runner
if option.ResumeFrom != "" {

2
go.mod
View File

@ -9,7 +9,7 @@ require (
github.com/chainreactors/ipcs v0.0.13
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.20230105095023-67f7d4e9186a
github.com/chainreactors/words v0.3.2-0.20230105161651-7c1fc4c9605a
)
require (

6
go.sum
View File

@ -39,6 +39,12 @@ github.com/chainreactors/words v0.3.2-0.20221214154622-381fc37abdf9 h1:IUNopSuor
github.com/chainreactors/words v0.3.2-0.20221214154622-381fc37abdf9/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
github.com/chainreactors/words v0.3.2-0.20230105095023-67f7d4e9186a h1:NoFfxJfPXiS2fzdmRIzWj4K+V7BRC2BAXlxQfckTeN0=
github.com/chainreactors/words v0.3.2-0.20230105095023-67f7d4e9186a/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
github.com/chainreactors/words v0.3.2-0.20230105160347-858217c41ce5 h1:uTiOYpgf4jz+/uwp+kAliLrOkVXjsC51pNmd4xH0uB4=
github.com/chainreactors/words v0.3.2-0.20230105160347-858217c41ce5/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
github.com/chainreactors/words v0.3.2-0.20230105161438-ec98bdc6906d h1:vWZwr3IaoEGEGE/IB0Im4gDqrOHpGK3szKOFDG4GFrc=
github.com/chainreactors/words v0.3.2-0.20230105161438-ec98bdc6906d/go.mod h1:QIWX1vMT5j/Mp9zx3/wgZh3FqskhjCbo/3Ffy/Hxj9w=
github.com/chainreactors/words v0.3.2-0.20230105161651-7c1fc4c9605a h1:vRAMDJ6UQV73uyiRBQnuE/+S7Q7JTpfubSpyRlooZ2U=
github.com/chainreactors/words v0.3.2-0.20230105161651-7c1fc4c9605a/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=

View File

@ -83,6 +83,7 @@ type ModeOptions struct {
Depth int `long:"depth" default:"0" description:"Int, recursive depth"`
Active bool `long:"active" description:"Bool, enable active finger detect"`
Crawl bool `long:"crawl" description:"Bool, enable crawl"`
Bak bool `long:"bak" description:"Bool, enable bak found"`
FileBak bool `long:"file-bak" description:"Bool, enable valid result bak found, equal --append-rule rule/filebak.txt"`
CrawlDepth int `long:"crawl-depth" default:"3" description:"Int, crawl depth"`
CheckPeriod int `long:"check-period" default:"200" description:"Int, check period when request"`
@ -134,6 +135,7 @@ func (opt *Option) PrepareRunner() (*Runner, error) {
BreakThreshold: opt.BreakThreshold,
Crawl: opt.Crawl,
Active: opt.Active,
Bak: opt.Bak,
}
if opt.Extracts != nil {
@ -254,7 +256,7 @@ func (opt *Option) PrepareRunner() (*Runner, error) {
opt.Word += "{@ext}"
}
r.Wordlist, err = mask.Run(opt.Word, dicts)
r.Wordlist, err = mask.Run(opt.Word, dicts, nil)
if err != nil {
return nil, err
}

View File

@ -144,7 +144,7 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
case RedirectSource:
bl.FrontURL = unit.frontUrl
pool.tempCh <- bl
case CrawlSource, ActiveSource, RuleSource:
case CrawlSource, ActiveSource, RuleSource, BakSource:
pool.tempCh <- bl
}
@ -312,6 +312,11 @@ func (pool *Pool) Run(ctx context.Context, offset, limit int) {
go pool.doActive()
}
if pool.Bak {
pool.wg.Add(1)
go pool.doBak()
}
Loop:
for {
select {
@ -504,6 +509,25 @@ func (pool *Pool) doCrawl(bl *pkg.Baseline) {
}
}
func (pool *Pool) doRule(bl *pkg.Baseline) {
defer pool.wg.Done()
if pool.AppendRule == nil {
return
}
if bl.Source == int(RuleSource) || bl.Dir {
return
}
for u := range rule.RunAsStream(pool.AppendRule.Expressions, path.Base(bl.Path)) {
pool.wg.Add(1)
pool.additionCh <- &Unit{
path: path.Join(path.Dir(bl.Path), u),
source: RuleSource,
depth: 1,
}
}
}
func (pool *Pool) doActive() {
defer pool.wg.Done()
for _, u := range pkg.ActivePath {
@ -515,6 +539,26 @@ func (pool *Pool) doActive() {
}
}
func (pool *Pool) doBak() {
defer pool.wg.Done()
u, err := url.Parse(pool.BaseURL)
if err != nil {
return
}
worder, err := words.NewWorderWithDsl("{?0}.{@bak_ext}", [][]string{pkg.BakGenerator(u.Host)}, nil)
if err != nil {
return
}
worder.Run()
for w := range worder.C {
pool.wg.Add(1)
pool.additionCh <- &Unit{
path: w,
source: BakSource,
}
}
}
func (pool *Pool) doCheck() {
if pool.failedCount > pool.BreakThreshold {
// 当报错次数超过上限是, 结束任务
@ -531,25 +575,6 @@ func (pool *Pool) doCheck() {
}
}
func (pool *Pool) doRule(bl *pkg.Baseline) {
defer pool.wg.Done()
if pool.AppendRule == nil {
return
}
if bl.Source == int(RuleSource) || bl.Dir {
return
}
for u := range rule.RunAsStream(pool.AppendRule.Expressions, path.Base(bl.Path)) {
pool.wg.Add(1)
pool.additionCh <- &Unit{
path: path.Join(path.Dir(bl.Path), u),
source: RuleSource,
depth: 1,
}
}
}
func (pool *Pool) addFuzzyBaseline(bl *pkg.Baseline) {
if _, ok := pool.baselines[bl.Status]; !ok && IntsContains(FuzzyStatus, bl.Status) {
bl.Collect()

View File

@ -74,6 +74,7 @@ type Runner struct {
IgnoreWaf bool
Crawl bool
Active bool
Bak bool
}
func (r *Runner) PrepareConfig() *pkg.Config {
@ -95,6 +96,7 @@ func (r *Runner) PrepareConfig() *pkg.Config {
IgnoreWaf: r.IgnoreWaf,
Crawl: r.Crawl,
Active: r.Active,
Bak: r.Bak,
}
if config.Mod == pkg.PathSpray {
config.ClientType = ihttp.FAST
@ -118,7 +120,8 @@ func (r *Runner) Prepare(ctx context.Context) error {
r.poolwg.Done()
return
}
pool.worder = words.NewWorderWithFns(r.URLList, r.Fns)
pool.worder = words.NewWorder(r.URLList)
pool.worder.Fns = r.Fns
pool.bar = pkg.NewBar("check", r.Total-r.Offset, r.Progress)
pool.Run(ctx, r.Offset, r.Total)
r.poolwg.Done()
@ -166,7 +169,8 @@ func (r *Runner) Prepare(ctx context.Context) error {
r.Done()
return
}
pool.worder = words.NewWorderWithFns(wl, r.Fns)
pool.worder = words.NewWorder(wl)
pool.worder.Fns = r.Fns
rules, err := loadRuleWithFiles(t.origin.RuleFiles, t.origin.RuleFilter)
if err != nil {
logs.Log.Error(err.Error())
@ -181,7 +185,8 @@ func (r *Runner) Prepare(ctx context.Context) error {
}
} else {
pool.Statistor = pkg.NewStatistor(t.baseUrl)
pool.worder = words.NewWorderWithFns(r.Wordlist, r.Fns)
pool.worder = words.NewWorder(r.Wordlist)
pool.worder.Fns = r.Fns
pool.worder.Rules = r.Rules.Expressions
}

View File

@ -54,6 +54,7 @@ const (
WordSource
WafSource
RuleSource
BakSource
)
func newUnit(path string, source int) *Unit {

View File

@ -101,7 +101,7 @@ func loadWordlist(word string, dictNames []string) ([]string, error) {
if err != nil {
return nil, err
}
wl, err := mask.Run(word, dicts)
wl, err := mask.Run(word, dicts, nil)
if err != nil {
return nil, err
}

View File

@ -41,4 +41,5 @@ type Config struct {
IgnoreWaf bool
Crawl bool
Active bool
Bak bool
}

View File

@ -3,7 +3,9 @@ package pkg
import (
"encoding/json"
"github.com/chainreactors/gogo/v2/pkg/fingers"
"github.com/chainreactors/gogo/v2/pkg/utils"
"github.com/chainreactors/ipcs"
"github.com/chainreactors/words/mask"
"math/rand"
"net/url"
"os"
@ -33,6 +35,24 @@ var (
}
)
func StringsContains(s []string, e string) bool {
for _, v := range s {
if v == e {
return true
}
}
return false
}
func IntsContains(s []int, e int) bool {
for _, v := range s {
if v == e {
return true
}
}
return false
}
func HasStdin() bool {
stat, err := os.Stdin.Stat()
if err != nil {
@ -98,6 +118,7 @@ func RandHost() string {
func LoadTemplates() error {
var err error
// load fingers
Fingers, err = fingers.LoadFingers(LoadConfig("http"))
if err != nil {
return err
@ -126,18 +147,30 @@ func LoadTemplates() error {
}
}
return nil
}
func LoadRules() error {
// load rule
var data map[string]interface{}
err := json.Unmarshal(LoadConfig("rule"), &data)
err = json.Unmarshal(LoadConfig("rule"), &data)
if err != nil {
return err
}
for k, v := range data {
Rules[k] = v.(string)
}
// load mask
var keywords map[string]interface{}
err = json.Unmarshal(LoadConfig("mask"), &keywords)
if err != nil {
return err
}
for k, v := range keywords {
t := make([]string, len(v.([]interface{})))
for i, vv := range v.([]interface{}) {
t[i] = utils.ToString(vv)
}
mask.SpecialWords[k] = t
}
return nil
}
@ -199,3 +232,16 @@ func URLJoin(base, uri string) string {
return base + "/" + uri
}
}
func BakGenerator(domain string) []string {
var possibilities []string
for first, _ := range domain {
for last, _ := range domain[first:] {
p := domain[first : first+last+1]
if !StringsContains(possibilities, p) {
possibilities = append(possibilities, p)
}
}
}
return possibilities
}

View File

@ -1,4 +1,4 @@
//go:generate go run templates/templates_gen.go -t templates -o pkg/templates.go -need http,rule
//go:generate go run templates/templates_gen.go -t templates -o pkg/templates.go -need http,rule,mask
package main
import "github.com/chainreactors/spray/cmd"