mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 23:55:27 +00:00
Use global pipes for capturing, experimental unified rendering
This commit is contained in:
parent
29576f9ced
commit
63cfd354b9
@ -13,38 +13,36 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// global output refresh rate
|
||||||
RefreshHz = 4.
|
const RefreshHz = 8
|
||||||
RefreshMillis = int64((1. / RefreshHz) * 1000.)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Encapsulates progress tracking.
|
// Encapsulates progress tracking.
|
||||||
type IProgress interface {
|
type IProgress interface {
|
||||||
InitProgressbar(hostCount int64, templateCount int, requestCount int64)
|
InitProgressbar(hostCount int64, templateCount int, requestCount int64)
|
||||||
AddToTotal(delta int64)
|
AddToTotal(delta int64)
|
||||||
Update()
|
Update()
|
||||||
render()
|
|
||||||
Drop(count int64)
|
Drop(count int64)
|
||||||
Wait()
|
Wait()
|
||||||
StartStdCapture()
|
|
||||||
StopStdCapture()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Progress struct {
|
type Progress struct {
|
||||||
progress *mpb.Progress
|
progress *mpb.Progress
|
||||||
bar *mpb.Bar
|
bar *mpb.Bar
|
||||||
total int64
|
total int64
|
||||||
initialTotal int64
|
initialTotal int64
|
||||||
totalMutex *sync.Mutex
|
|
||||||
captureData *captureData
|
totalMutex *sync.Mutex
|
||||||
stdCaptureMutex *sync.Mutex
|
colorizer aurora.Aurora
|
||||||
stdout *strings.Builder
|
|
||||||
stderr *strings.Builder
|
// stdio capture and rendering
|
||||||
colorizer aurora.Aurora
|
renderChan chan time.Time
|
||||||
renderChan chan time.Time
|
captureData *captureData
|
||||||
renderMutex *sync.Mutex
|
stdCaptureMutex *sync.Mutex
|
||||||
renderTime time.Time
|
stdOut *strings.Builder
|
||||||
firstTimeOutput bool
|
stdErr *strings.Builder
|
||||||
|
stdStopRenderEvent chan bool
|
||||||
|
stdRenderEvent *time.Ticker
|
||||||
|
stdRenderWaitGroup *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and returns a new progress tracking object.
|
// Creates and returns a new progress tracking object.
|
||||||
@ -53,6 +51,8 @@ func NewProgress(noColor bool, active bool) IProgress {
|
|||||||
return &NoOpProgress{}
|
return &NoOpProgress{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshMillis := int64(1. / float64(RefreshHz) * 1000.)
|
||||||
|
|
||||||
renderChan := make(chan time.Time)
|
renderChan := make(chan time.Time)
|
||||||
p := &Progress{
|
p := &Progress{
|
||||||
progress: mpb.New(
|
progress: mpb.New(
|
||||||
@ -60,15 +60,17 @@ func NewProgress(noColor bool, active bool) IProgress {
|
|||||||
mpb.PopCompletedMode(),
|
mpb.PopCompletedMode(),
|
||||||
mpb.WithManualRefresh(renderChan),
|
mpb.WithManualRefresh(renderChan),
|
||||||
),
|
),
|
||||||
totalMutex: &sync.Mutex{},
|
totalMutex: &sync.Mutex{},
|
||||||
stdCaptureMutex: &sync.Mutex{},
|
colorizer: aurora.NewAurora(!noColor),
|
||||||
stdout: &strings.Builder{},
|
|
||||||
stderr: &strings.Builder{},
|
// stdio capture and rendering
|
||||||
colorizer: aurora.NewAurora(!noColor),
|
renderChan: renderChan,
|
||||||
renderChan: renderChan,
|
stdCaptureMutex: &sync.Mutex{},
|
||||||
renderMutex: &sync.Mutex{},
|
stdOut: &strings.Builder{},
|
||||||
renderTime: time.Now(),
|
stdErr: &strings.Builder{},
|
||||||
firstTimeOutput: true,
|
stdStopRenderEvent: make(chan bool),
|
||||||
|
stdRenderEvent: time.NewTicker(time.Millisecond * time.Duration(refreshMillis)),
|
||||||
|
stdRenderWaitGroup: &sync.WaitGroup{},
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
@ -90,6 +92,12 @@ func (p *Progress) InitProgressbar(hostCount int64, templateCount int, requestCo
|
|||||||
pluralize(hostCount, "host", "hosts"))
|
pluralize(hostCount, "host", "hosts"))
|
||||||
|
|
||||||
p.bar = p.setupProgressbar("["+barName+"]", requestCount, 0)
|
p.bar = p.setupProgressbar("["+barName+"]", requestCount, 0)
|
||||||
|
|
||||||
|
// creates r/w pipes and divert stdout+stderr writers to them and start capturing their output
|
||||||
|
p.captureData = startCapture(p.stdCaptureMutex, p.stdOut, p.stdErr)
|
||||||
|
|
||||||
|
// starts rendering the captured stdout+stderr data
|
||||||
|
p.renderStdData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update total progress request count
|
// Update total progress request count
|
||||||
@ -103,7 +111,6 @@ func (p *Progress) AddToTotal(delta int64) {
|
|||||||
// Update progress tracking information and increments the request counter by one unit.
|
// Update progress tracking information and increments the request counter by one unit.
|
||||||
func (p *Progress) Update() {
|
func (p *Progress) Update() {
|
||||||
p.bar.Increment()
|
p.bar.Increment()
|
||||||
p.render()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drops the specified number of requests from the progress bar total.
|
// Drops the specified number of requests from the progress bar total.
|
||||||
@ -111,7 +118,6 @@ func (p *Progress) Update() {
|
|||||||
func (p *Progress) Drop(count int64) {
|
func (p *Progress) Drop(count int64) {
|
||||||
// mimic dropping by incrementing the completed requests
|
// mimic dropping by incrementing the completed requests
|
||||||
p.bar.IncrInt64(count)
|
p.bar.IncrInt64(count)
|
||||||
p.render()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that a progress bar's total count is up-to-date if during an enumeration there were uncompleted requests and
|
// Ensures that a progress bar's total count is up-to-date if during an enumeration there were uncompleted requests and
|
||||||
@ -126,56 +132,60 @@ func (p *Progress) Wait() {
|
|||||||
p.totalMutex.Unlock()
|
p.totalMutex.Unlock()
|
||||||
p.progress.Wait()
|
p.progress.Wait()
|
||||||
|
|
||||||
|
// close the writers and wait for the EOF condition
|
||||||
|
stopCapture(p.captureData)
|
||||||
|
|
||||||
|
// stop the renderer and wait for it
|
||||||
|
p.stdStopRenderEvent <- true
|
||||||
|
p.stdRenderWaitGroup.Wait()
|
||||||
|
|
||||||
// drain any stdout/stderr data
|
// drain any stdout/stderr data
|
||||||
p.drainStringBuilderTo(p.stdout, os.Stdout)
|
p.drainStringBuilderTo(p.stdOut, os.Stdout)
|
||||||
p.drainStringBuilderTo(p.stderr, os.Stderr)
|
p.drainStringBuilderTo(p.stdErr, os.Stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts capturing stdout and stderr instead of producing visual output that may interfere with the progress bars.
|
func (p *Progress) renderStdData() {
|
||||||
func (p *Progress) StartStdCapture() {
|
// trigger a render event
|
||||||
p.stdCaptureMutex.Lock()
|
p.renderChan <- time.Now()
|
||||||
p.captureData = startStdCapture()
|
gologger.Infof("Waiting for your terminal to settle..")
|
||||||
}
|
time.Sleep(time.Millisecond * 250)
|
||||||
|
|
||||||
// Stops capturing stdout and stderr and store both output to be shown later.
|
count := 0
|
||||||
func (p *Progress) StopStdCapture() {
|
p.stdRenderWaitGroup.Add(1)
|
||||||
stopStdCapture(p.captureData)
|
go func(waitGroup *sync.WaitGroup) {
|
||||||
p.stdout.Write(p.captureData.DataStdOut.Bytes())
|
for {
|
||||||
p.stderr.Write(p.captureData.DataStdErr.Bytes())
|
select {
|
||||||
|
case <-p.stdStopRenderEvent:
|
||||||
|
waitGroup.Done()
|
||||||
|
return
|
||||||
|
case _ = <-p.stdRenderEvent.C:
|
||||||
|
p.stdCaptureMutex.Lock()
|
||||||
|
{
|
||||||
|
hasStdout := p.stdOut.Len() > 0
|
||||||
|
hasStderr := p.stdErr.Len() > 0
|
||||||
|
hasOutput := hasStdout || hasStderr
|
||||||
|
|
||||||
p.renderMutex.Lock()
|
if hasOutput {
|
||||||
{
|
count++
|
||||||
hasStdout := p.stdout.Len() > 0
|
stdout := p.captureData.backupStdout
|
||||||
hasStderr := p.stderr.Len() > 0
|
stderr := p.captureData.backupStderr
|
||||||
hasOutput := hasStdout || hasStderr
|
|
||||||
|
|
||||||
if hasOutput {
|
// go back one line and clean it all
|
||||||
if p.firstTimeOutput {
|
fmt.Fprint(stderr, "\u001b[1A\u001b[2K")
|
||||||
// trigger a render event
|
p.drainStringBuilderTo(p.stdOut, stdout)
|
||||||
p.renderChan <- time.Now()
|
p.drainStringBuilderTo(p.stdErr, stderr)
|
||||||
gologger.Infof("Waiting for your terminal to settle..")
|
|
||||||
// no way to sync to it? :(
|
|
||||||
time.Sleep(time.Millisecond * 250)
|
|
||||||
p.firstTimeOutput = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if can, now := p.canRender(); can {
|
// make space for the progressbar to render itself
|
||||||
// go back one line and clean it all
|
fmt.Fprintln(stderr, "")
|
||||||
fmt.Fprint(os.Stderr, "\u001b[1A\u001b[2K")
|
}
|
||||||
p.drainStringBuilderTo(p.stdout, os.Stdout)
|
|
||||||
p.drainStringBuilderTo(p.stderr, os.Stderr)
|
|
||||||
|
|
||||||
// make space for the progressbar to render itself
|
// always trigger a render event to try ensure it's visible even with fast output
|
||||||
fmt.Fprintln(os.Stderr, "")
|
p.renderChan <- time.Now()
|
||||||
|
}
|
||||||
// always trigger a render event to try ensure it's visible even with fast output
|
p.stdCaptureMutex.Unlock()
|
||||||
p.renderChan <- now
|
|
||||||
p.renderTime = now
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}(p.stdRenderWaitGroup)
|
||||||
p.renderMutex.Unlock()
|
|
||||||
p.stdCaptureMutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and returns a progress bar.
|
// Creates and returns a progress bar.
|
||||||
@ -203,23 +213,6 @@ func (p *Progress) setupProgressbar(name string, total int64, priority int) *mpb
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Progress) render() {
|
|
||||||
p.renderMutex.Lock()
|
|
||||||
if can, now := p.canRender(); can {
|
|
||||||
p.renderChan <- now
|
|
||||||
p.renderTime = now
|
|
||||||
}
|
|
||||||
p.renderMutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Progress) canRender() (bool, time.Time) {
|
|
||||||
now := time.Now()
|
|
||||||
if now.Sub(p.renderTime).Milliseconds() >= RefreshMillis {
|
|
||||||
return true, now
|
|
||||||
}
|
|
||||||
return false, now
|
|
||||||
}
|
|
||||||
|
|
||||||
func pluralize(count int64, singular, plural string) string {
|
func pluralize(count int64, singular, plural string) string {
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
return plural
|
return plural
|
||||||
|
|||||||
@ -5,8 +5,5 @@ type NoOpProgress struct{}
|
|||||||
func (p *NoOpProgress) InitProgressbar(hostCount int64, templateCount int, requestCount int64) {}
|
func (p *NoOpProgress) InitProgressbar(hostCount int64, templateCount int, requestCount int64) {}
|
||||||
func (p *NoOpProgress) AddToTotal(delta int64) {}
|
func (p *NoOpProgress) AddToTotal(delta int64) {}
|
||||||
func (p *NoOpProgress) Update() {}
|
func (p *NoOpProgress) Update() {}
|
||||||
func (p *NoOpProgress) render() {}
|
|
||||||
func (p *NoOpProgress) Drop(count int64) {}
|
func (p *NoOpProgress) Drop(count int64) {}
|
||||||
func (p *NoOpProgress) Wait() {}
|
func (p *NoOpProgress) Wait() {}
|
||||||
func (p *NoOpProgress) StartStdCapture() {}
|
|
||||||
func (p *NoOpProgress) StopStdCapture() {}
|
|
||||||
|
|||||||
@ -2,28 +2,25 @@ package progress
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Inspired by the https://github.com/PumpkinSeed/cage module
|
Inspired by the https://github.com/PumpkinSeed/cage module
|
||||||
*/
|
*/
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bufio"
|
||||||
|
"github.com/projectdiscovery/gologger"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type captureData struct {
|
type captureData struct {
|
||||||
backupStdout *os.File
|
backupStdout *os.File
|
||||||
writerStdout *os.File
|
writerStdout *os.File
|
||||||
backupStderr *os.File
|
backupStderr *os.File
|
||||||
writerStderr *os.File
|
writerStderr *os.File
|
||||||
|
waitFinishRead *sync.WaitGroup
|
||||||
DataStdOut *bytes.Buffer
|
|
||||||
DataStdErr *bytes.Buffer
|
|
||||||
|
|
||||||
outStdout chan []byte
|
|
||||||
outStderr chan []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startStdCapture() *captureData {
|
func startCapture(writeMutex *sync.Mutex, stdout *strings.Builder, stderr *strings.Builder) *captureData {
|
||||||
rStdout, wStdout, errStdout := os.Pipe()
|
rStdout, wStdout, errStdout := os.Pipe()
|
||||||
if errStdout != nil {
|
if errStdout != nil {
|
||||||
panic(errStdout)
|
panic(errStdout)
|
||||||
@ -41,54 +38,51 @@ func startStdCapture() *captureData {
|
|||||||
backupStderr: os.Stderr,
|
backupStderr: os.Stderr,
|
||||||
writerStderr: wStderr,
|
writerStderr: wStderr,
|
||||||
|
|
||||||
outStdout: make(chan []byte),
|
waitFinishRead: &sync.WaitGroup{},
|
||||||
outStderr: make(chan []byte),
|
|
||||||
|
|
||||||
DataStdOut: &bytes.Buffer{},
|
|
||||||
DataStdErr: &bytes.Buffer{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Stdout = c.writerStdout
|
os.Stdout = c.writerStdout
|
||||||
os.Stderr = c.writerStderr
|
os.Stderr = c.writerStderr
|
||||||
|
|
||||||
stdCopy := func(out chan<- []byte, reader *os.File) {
|
stdCopy := func(builder *strings.Builder, reader *os.File, waitGroup *sync.WaitGroup) {
|
||||||
var buffer bytes.Buffer
|
r := bufio.NewReader(reader)
|
||||||
_, _ = io.Copy(&buffer, reader)
|
buf := make([]byte, 0, 4*1024)
|
||||||
if buffer.Len() > 0 {
|
for {
|
||||||
out <- buffer.Bytes()
|
n, err := r.Read(buf[:cap(buf)])
|
||||||
|
buf = buf[:n]
|
||||||
|
if n == 0 {
|
||||||
|
if err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == io.EOF {
|
||||||
|
waitGroup.Done()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
waitGroup.Done()
|
||||||
|
gologger.Fatalf("stdcapture error: %s", err)
|
||||||
|
}
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
waitGroup.Done()
|
||||||
|
gologger.Fatalf("stdcapture error: %s", err)
|
||||||
|
}
|
||||||
|
writeMutex.Lock()
|
||||||
|
builder.Write(buf)
|
||||||
|
writeMutex.Unlock()
|
||||||
}
|
}
|
||||||
close(out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go stdCopy(c.outStdout, rStdout)
|
c.waitFinishRead.Add(2)
|
||||||
go stdCopy(c.outStderr, rStderr)
|
go stdCopy(stdout, rStdout, c.waitFinishRead)
|
||||||
|
go stdCopy(stderr, rStderr, c.waitFinishRead)
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopStdCapture(c *captureData) {
|
func stopCapture(c *captureData) {
|
||||||
_ = c.writerStdout.Close()
|
_ = c.writerStdout.Close()
|
||||||
_ = c.writerStderr.Close()
|
_ = c.writerStderr.Close()
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
c.waitFinishRead.Wait()
|
||||||
|
|
||||||
stdRead := func(in <-chan []byte, outData *bytes.Buffer) {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
for {
|
|
||||||
out, more := <-in
|
|
||||||
if more {
|
|
||||||
outData.Write(out)
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Add(2)
|
|
||||||
go stdRead(c.outStdout, c.DataStdOut)
|
|
||||||
go stdRead(c.outStderr, c.DataStdErr)
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
os.Stdout = c.backupStdout
|
os.Stdout = c.backupStdout
|
||||||
os.Stderr = c.backupStderr
|
os.Stderr = c.backupStderr
|
||||||
|
|||||||
@ -336,7 +336,7 @@ func (r *Runner) RunEnumeration() {
|
|||||||
gologger.Errorf("Could not find any valid input URLs.")
|
gologger.Errorf("Could not find any valid input URLs.")
|
||||||
} else if totalRequests > 0 || hasWorkflows {
|
} else if totalRequests > 0 || hasWorkflows {
|
||||||
|
|
||||||
// track global progress
|
// tracks global progress and captures stdout/stderr until p.Wait finishes
|
||||||
p.InitProgressbar(r.inputCount, templateCount, totalRequests)
|
p.InitProgressbar(r.inputCount, templateCount, totalRequests)
|
||||||
|
|
||||||
for _, match := range allTemplates {
|
for _, match := range allTemplates {
|
||||||
@ -384,9 +384,7 @@ func (r *Runner) processTemplateWithList(p progress.IProgress, template *templat
|
|||||||
if template.Info.Severity != "" {
|
if template.Info.Severity != "" {
|
||||||
message += " [" + template.Info.Severity + "]"
|
message += " [" + template.Info.Severity + "]"
|
||||||
}
|
}
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Infof("%s\n", message)
|
gologger.Infof("%s\n", message)
|
||||||
p.StopStdCapture()
|
|
||||||
|
|
||||||
var writer *bufio.Writer
|
var writer *bufio.Writer
|
||||||
if r.output != nil {
|
if r.output != nil {
|
||||||
@ -432,9 +430,7 @@ func (r *Runner) processTemplateWithList(p progress.IProgress, template *templat
|
|||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Drop(request.(*requests.BulkHTTPRequest).GetRequestCount())
|
p.Drop(request.(*requests.BulkHTTPRequest).GetRequestCount())
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not create http client: %s\n", err)
|
gologger.Warningf("Could not create http client: %s\n", err)
|
||||||
p.StopStdCapture()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,9 +458,7 @@ func (r *Runner) processTemplateWithList(p progress.IProgress, template *templat
|
|||||||
globalresult.Or(result.GotResults)
|
globalresult.Or(result.GotResults)
|
||||||
}
|
}
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not execute step: %s\n", result.Error)
|
gologger.Warningf("Could not execute step: %s\n", result.Error)
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
<-r.limiter
|
<-r.limiter
|
||||||
}(text)
|
}(text)
|
||||||
@ -489,9 +483,7 @@ func (r *Runner) ProcessWorkflowWithList(p progress.IProgress, workflow *workflo
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if err := r.ProcessWorkflow(p, workflow, text); err != nil {
|
if err := r.ProcessWorkflow(p, workflow, text); err != nil {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not run workflow for %s: %s\n", text, err)
|
gologger.Warningf("Could not run workflow for %s: %s\n", text, err)
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
<-r.limiter
|
<-r.limiter
|
||||||
}(text)
|
}(text)
|
||||||
@ -522,9 +514,7 @@ func (r *Runner) ProcessWorkflow(p progress.IProgress, workflow *workflows.Workf
|
|||||||
// Check if the template is an absolute path or relative path.
|
// Check if the template is an absolute path or relative path.
|
||||||
// If the path is absolute, use it. Otherwise,
|
// If the path is absolute, use it. Otherwise,
|
||||||
if r.isRelative(value) {
|
if r.isRelative(value) {
|
||||||
p.StartStdCapture()
|
|
||||||
newPath, err := r.resolvePath(value)
|
newPath, err := r.resolvePath(value)
|
||||||
p.StopStdCapture()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newPath, err = r.resolvePathWithBaseFolder(filepath.Dir(workflow.GetPath()), value)
|
newPath, err = r.resolvePathWithBaseFolder(filepath.Dir(workflow.GetPath()), value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -629,9 +619,7 @@ func (r *Runner) ProcessWorkflow(p progress.IProgress, workflow *workflows.Workf
|
|||||||
|
|
||||||
_, err := script.RunContext(context.Background())
|
_, err := script.RunContext(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Errorf("Could not execute workflow '%s': %s\n", workflow.ID, err)
|
gologger.Errorf("Could not execute workflow '%s': %s\n", workflow.ID, err)
|
||||||
p.StopStdCapture()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -94,10 +94,8 @@ func (e *DNSExecuter) ExecuteDNS(p progress.IProgress, URL string) (result Resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.debug {
|
if e.debug {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Infof("Dumped DNS request for %s (%s)\n\n", URL, e.template.ID)
|
gologger.Infof("Dumped DNS request for %s (%s)\n\n", URL, e.template.ID)
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", compiledRequest.String())
|
fmt.Fprintf(os.Stderr, "%s\n", compiledRequest.String())
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the request to the target servers
|
// Send the request to the target servers
|
||||||
@ -110,15 +108,11 @@ func (e *DNSExecuter) ExecuteDNS(p progress.IProgress, URL string) (result Resul
|
|||||||
|
|
||||||
p.Update()
|
p.Update()
|
||||||
|
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Verbosef("Sent DNS request to %s\n", "dns-request", URL)
|
gologger.Verbosef("Sent DNS request to %s\n", "dns-request", URL)
|
||||||
p.StopStdCapture()
|
|
||||||
|
|
||||||
if e.debug {
|
if e.debug {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Infof("Dumped DNS response for %s (%s)\n\n", URL, e.template.ID)
|
gologger.Infof("Dumped DNS response for %s (%s)\n\n", URL, e.template.ID)
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", resp.String())
|
fmt.Fprintf(os.Stderr, "%s\n", resp.String())
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matcherCondition := e.dnsRequest.GetMatchersCondition()
|
matcherCondition := e.dnsRequest.GetMatchersCondition()
|
||||||
@ -133,9 +127,7 @@ func (e *DNSExecuter) ExecuteDNS(p progress.IProgress, URL string) (result Resul
|
|||||||
// If the matcher has matched, and its an OR
|
// If the matcher has matched, and its an OR
|
||||||
// write the first output then move to next matcher.
|
// write the first output then move to next matcher.
|
||||||
if matcherCondition == matchers.ORCondition && len(e.dnsRequest.Extractors) == 0 {
|
if matcherCondition == matchers.ORCondition && len(e.dnsRequest.Extractors) == 0 {
|
||||||
p.StartStdCapture()
|
|
||||||
e.writeOutputDNS(domain, matcher, nil)
|
e.writeOutputDNS(domain, matcher, nil)
|
||||||
p.StopStdCapture()
|
|
||||||
result.GotResults = true
|
result.GotResults = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,9 +147,7 @@ func (e *DNSExecuter) ExecuteDNS(p progress.IProgress, URL string) (result Resul
|
|||||||
// Write a final string of output if matcher type is
|
// Write a final string of output if matcher type is
|
||||||
// AND or if we have extractors for the mechanism too.
|
// AND or if we have extractors for the mechanism too.
|
||||||
if len(e.dnsRequest.Extractors) > 0 || matcherCondition == matchers.ANDCondition {
|
if len(e.dnsRequest.Extractors) > 0 || matcherCondition == matchers.ANDCondition {
|
||||||
p.StartStdCapture()
|
|
||||||
e.writeOutputDNS(domain, nil, extractorResults)
|
e.writeOutputDNS(domain, nil, extractorResults)
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@ -146,9 +146,7 @@ func (e *HTTPExecuter) ExecuteHTTP(p progress.IProgress, URL string) (result Res
|
|||||||
remaining--
|
remaining--
|
||||||
}
|
}
|
||||||
|
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Verbosef("Sent HTTP request to %s\n", "http-request", URL)
|
gologger.Verbosef("Sent HTTP request to %s\n", "http-request", URL)
|
||||||
p.StopStdCapture()
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -162,10 +160,8 @@ func (e *HTTPExecuter) handleHTTP(p progress.IProgress, URL string, request *req
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not make http request")
|
return errors.Wrap(err, "could not make http request")
|
||||||
}
|
}
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Infof("Dumped HTTP request for %s (%s)\n\n", URL, e.template.ID)
|
gologger.Infof("Dumped HTTP request for %s (%s)\n\n", URL, e.template.ID)
|
||||||
fmt.Fprintf(os.Stderr, "%s", string(dumpedRequest))
|
fmt.Fprintf(os.Stderr, "%s", string(dumpedRequest))
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
resp, err := e.httpClient.Do(req)
|
resp, err := e.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -180,10 +176,8 @@ func (e *HTTPExecuter) handleHTTP(p progress.IProgress, URL string, request *req
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not dump http response")
|
return errors.Wrap(err, "could not dump http response")
|
||||||
}
|
}
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Infof("Dumped HTTP response for %s (%s)\n\n", URL, e.template.ID)
|
gologger.Infof("Dumped HTTP response for %s (%s)\n\n", URL, e.template.ID)
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", string(dumpedResponse))
|
fmt.Fprintf(os.Stderr, "%s\n", string(dumpedResponse))
|
||||||
p.StopStdCapture()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
@ -220,9 +214,7 @@ func (e *HTTPExecuter) handleHTTP(p progress.IProgress, URL string, request *req
|
|||||||
result.Matches[matcher.Name] = nil
|
result.Matches[matcher.Name] = nil
|
||||||
// probably redundant but ensures we snapshot current payload values when matchers are valid
|
// probably redundant but ensures we snapshot current payload values when matchers are valid
|
||||||
result.Meta = request.Meta
|
result.Meta = request.Meta
|
||||||
p.StartStdCapture()
|
|
||||||
e.writeOutputHTTP(request, resp, body, matcher, nil)
|
e.writeOutputHTTP(request, resp, body, matcher, nil)
|
||||||
p.StopStdCapture()
|
|
||||||
result.GotResults = true
|
result.GotResults = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,9 +241,7 @@ func (e *HTTPExecuter) handleHTTP(p progress.IProgress, URL string, request *req
|
|||||||
// Write a final string of output if matcher type is
|
// Write a final string of output if matcher type is
|
||||||
// AND or if we have extractors for the mechanism too.
|
// AND or if we have extractors for the mechanism too.
|
||||||
if len(outputExtractorResults) > 0 || matcherCondition == matchers.ANDCondition {
|
if len(outputExtractorResults) > 0 || matcherCondition == matchers.ANDCondition {
|
||||||
p.StartStdCapture()
|
|
||||||
e.writeOutputHTTP(request, resp, body, nil, outputExtractorResults)
|
e.writeOutputHTTP(request, resp, body, nil, outputExtractorResults)
|
||||||
p.StopStdCapture()
|
|
||||||
result.GotResults = true
|
result.GotResults = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -67,16 +67,12 @@ func (n *NucleiVar) Call(args ...tengo.Object) (ret tengo.Object, err error) {
|
|||||||
httpExecuter, err := executer.NewHTTPExecuter(template.HTTPOptions)
|
httpExecuter, err := executer.NewHTTPExecuter(template.HTTPOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Drop(request.GetRequestCount())
|
p.Drop(request.GetRequestCount())
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not compile request for template '%s': %s\n", template.HTTPOptions.Template.ID, err)
|
gologger.Warningf("Could not compile request for template '%s': %s\n", template.HTTPOptions.Template.ID, err)
|
||||||
p.StopStdCapture()
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
result := httpExecuter.ExecuteHTTP(p, n.URL)
|
result := httpExecuter.ExecuteHTTP(p, n.URL)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not send request for template '%s': %s\n", template.HTTPOptions.Template.ID, result.Error)
|
gologger.Warningf("Could not send request for template '%s': %s\n", template.HTTPOptions.Template.ID, result.Error)
|
||||||
p.StopStdCapture()
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +90,7 @@ func (n *NucleiVar) Call(args ...tengo.Object) (ret tengo.Object, err error) {
|
|||||||
dnsExecuter := executer.NewDNSExecuter(template.DNSOptions)
|
dnsExecuter := executer.NewDNSExecuter(template.DNSOptions)
|
||||||
result := dnsExecuter.ExecuteDNS(p, n.URL)
|
result := dnsExecuter.ExecuteDNS(p, n.URL)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
p.StartStdCapture()
|
|
||||||
gologger.Warningf("Could not compile request for template '%s': %s\n", template.HTTPOptions.Template.ID, result.Error)
|
gologger.Warningf("Could not compile request for template '%s': %s\n", template.HTTPOptions.Template.ID, result.Error)
|
||||||
p.StopStdCapture()
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user