Skip to content

Commit

Permalink
Add initial coloring support in output results
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelbua committed Jul 28, 2020
1 parent 44e75d0 commit f8e52ce
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 9 deletions.
30 changes: 30 additions & 0 deletions v2/internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"context"
"errors"
"fmt"
"github.com/logrusorgru/aurora"
"io"
"io/ioutil"
"net/http/cookiejar"
"os"
"path/filepath"
"regexp"
"strings"
"sync"

Expand Down Expand Up @@ -42,6 +44,10 @@ type Runner struct {

// progress tracking
progress *progress.Progress

// output coloring
colorizer aurora.Aurora
decolorizer *regexp.Regexp
}

// New creates a new client for running enumeration process.
Expand All @@ -58,6 +64,18 @@ func New(options *Options) (*Runner, error) {
os.Exit(0)
}

// output coloring
useColor := !options.NoColor
runner.colorizer = aurora.NewAurora(useColor)
if useColor {
// compile a decolorization regex to cleanup file output messages
compiled, err := regexp.Compile("\\x1B\\[[0-9;]*[a-zA-Z]")
if err != nil {
return nil, err
}
runner.decolorizer = compiled
}

// If we have stdin, write it to a new file
if options.Stdin {
tempInput, err := ioutil.TempFile("", "stdin-input-*")
Expand Down Expand Up @@ -392,6 +410,9 @@ func (r *Runner) processTemplateWithList(p *progress.Progress, template *templat
DNSRequest: value,
Writer: writer,
JSON: r.options.JSON,
ColoredOutput: !r.options.NoColor,
Colorizer: r.colorizer,
Decolorizer: r.decolorizer,
})
case *requests.BulkHTTPRequest:
httpExecuter, err = executer.NewHTTPExecuter(&executer.HTTPOptions{
Expand All @@ -407,6 +428,9 @@ func (r *Runner) processTemplateWithList(p *progress.Progress, template *templat
JSON: r.options.JSON,
JSONRequests: r.options.JSONRequests,
CookieReuse: value.CookieReuse,
ColoredOutput: !r.options.NoColor,
Colorizer: r.colorizer,
Decolorizer: r.decolorizer,
})
}
if err != nil {
Expand Down Expand Up @@ -524,12 +548,18 @@ func (r *Runner) ProcessWorkflow(p *progress.Progress, workflow *workflows.Workf
ProxySocksURL: r.options.ProxySocksURL,
CustomHeaders: r.options.CustomHeaders,
CookieJar: jar,
ColoredOutput: !r.options.NoColor,
Colorizer: r.colorizer,
Decolorizer: r.decolorizer,
}
} else if len(t.RequestsDNS) > 0 {
template.DNSOptions = &executer.DNSOptions{
Debug: r.options.Debug,
Template: t,
Writer: writer,
ColoredOutput: !r.options.NoColor,
Colorizer: r.colorizer,
Decolorizer: r.decolorizer,
}
}
if template.DNSOptions != nil || template.HTTPOptions != nil {
Expand Down
13 changes: 13 additions & 0 deletions v2/pkg/executer/executer_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package executer
import (
"bufio"
"fmt"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v2/internal/progress"
"os"
"regexp"
"sync"

"github.com/pkg/errors"
Expand All @@ -26,6 +28,10 @@ type DNSExecuter struct {
dnsRequest *requests.DNSRequest
writer *bufio.Writer
outputMutex *sync.Mutex

coloredOutput bool
colorizer aurora.Aurora
decolorizer *regexp.Regexp
}

// DefaultResolvers contains the list of resolvers known to be trusted.
Expand All @@ -43,6 +49,10 @@ type DNSOptions struct {
Template *templates.Template
DNSRequest *requests.DNSRequest
Writer *bufio.Writer

ColoredOutput bool
Colorizer aurora.Aurora
Decolorizer *regexp.Regexp
}

// NewDNSExecuter creates a new DNS executer from a template
Expand All @@ -58,6 +68,9 @@ func NewDNSExecuter(options *DNSOptions) *DNSExecuter {
dnsRequest: options.DNSRequest,
writer: options.Writer,
outputMutex: &sync.Mutex{},
coloredOutput: options.ColoredOutput,
colorizer: options.Colorizer,
decolorizer: options.Decolorizer,
}
return executer
}
Expand Down
12 changes: 12 additions & 0 deletions v2/pkg/executer/executer_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"bufio"
"crypto/tls"
"fmt"
"github.com/logrusorgru/aurora"
"io"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/http/httputil"
"net/url"
"os"
"regexp"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -39,6 +41,10 @@ type HTTPExecuter struct {
outputMutex *sync.Mutex
customHeaders requests.CustomHeaders
CookieJar *cookiejar.Jar

coloredOutput bool
colorizer aurora.Aurora
decolorizer *regexp.Regexp
}

// HTTPOptions contains configuration options for the HTTP executer.
Expand All @@ -56,6 +62,9 @@ type HTTPOptions struct {
CustomHeaders requests.CustomHeaders
CookieReuse bool
CookieJar *cookiejar.Jar
ColoredOutput bool
Colorizer aurora.Aurora
Decolorizer *regexp.Regexp
}

// NewHTTPExecuter creates a new HTTP executer from a template
Expand Down Expand Up @@ -95,6 +104,9 @@ func NewHTTPExecuter(options *HTTPOptions) (*HTTPExecuter, error) {
writer: options.Writer,
customHeaders: options.CustomHeaders,
CookieJar: options.CookieJar,
coloredOutput: options.ColoredOutput,
colorizer: options.Colorizer,
decolorizer: options.Decolorizer,
}

return executer, nil
Expand Down
15 changes: 11 additions & 4 deletions v2/pkg/executer/output_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,25 @@ func (e *DNSExecuter) writeOutputDNS(domain string, matcher *matchers.Matcher, e
}

builder := &strings.Builder{}
colorizer := e.colorizer

builder.WriteRune('[')
builder.WriteString(e.template.ID)
builder.WriteString(colorizer.BrightGreen(e.template.ID).String())
if matcher != nil && len(matcher.Name) > 0 {
builder.WriteString(":")
builder.WriteString(matcher.Name)
builder.WriteString(colorizer.BrightGreen(matcher.Name).Bold().String())
}
builder.WriteString("] [dns] ")
builder.WriteString("] [")
builder.WriteString(colorizer.BrightBlue("dns").String())
builder.WriteString("] ")

builder.WriteString(domain)

// If any extractors, write the results
if len(extractorResults) > 0 {
builder.WriteString(" [")
for i, result := range extractorResults {
builder.WriteString(result)
builder.WriteString(colorizer.BrightCyan(result).String())
if i != len(extractorResults)-1 {
builder.WriteRune(',')
}
Expand All @@ -71,6 +75,9 @@ func (e *DNSExecuter) writeOutputDNS(domain string, matcher *matchers.Matcher, e

if e.writer != nil {
e.outputMutex.Lock()
if e.coloredOutput {
message = e.decolorizer.ReplaceAllString(message, "")
}
e.writer.WriteString(message)
e.outputMutex.Unlock()
}
Expand Down
16 changes: 11 additions & 5 deletions v2/pkg/executer/output_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,17 @@ func (e *HTTPExecuter) writeOutputHTTP(req *requests.HttpRequest, resp *http.Res
}

builder := &strings.Builder{}
colorizer := e.colorizer

builder.WriteRune('[')
builder.WriteString(e.template.ID)
builder.WriteString(colorizer.BrightGreen(e.template.ID).String())
if matcher != nil && len(matcher.Name) > 0 {
builder.WriteString(":")
builder.WriteString(matcher.Name)
builder.WriteString(colorizer.BrightGreen(matcher.Name).Bold().String())
}
builder.WriteString("] [http] ")
builder.WriteString("] [")
builder.WriteString(colorizer.BrightBlue("http").String())
builder.WriteString("] ")

// Escape the URL by replacing all % with %%
escapedURL := strings.Replace(URL, "%", "%%", -1)
Expand All @@ -79,7 +82,7 @@ func (e *HTTPExecuter) writeOutputHTTP(req *requests.HttpRequest, resp *http.Res
if len(extractorResults) > 0 {
builder.WriteString(" [")
for i, result := range extractorResults {
builder.WriteString(result)
builder.WriteString(colorizer.BrightCyan(result).String())
if i != len(extractorResults)-1 {
builder.WriteRune(',')
}
Expand All @@ -92,7 +95,7 @@ func (e *HTTPExecuter) writeOutputHTTP(req *requests.HttpRequest, resp *http.Res
builder.WriteString(" [")
var metas []string
for name, value := range req.Meta {
metas = append(metas, name+"="+value.(string))
metas = append(metas, colorizer.BrightYellow(name).Bold().String()+"="+ colorizer.BrightYellow(value.(string)).String() )
}
builder.WriteString(strings.Join(metas, ","))
builder.WriteString("]")
Expand All @@ -106,6 +109,9 @@ func (e *HTTPExecuter) writeOutputHTTP(req *requests.HttpRequest, resp *http.Res

if e.writer != nil {
e.outputMutex.Lock()
if e.coloredOutput {
message = e.decolorizer.ReplaceAllString(message, "")
}
e.writer.WriteString(message)
e.outputMutex.Unlock()
}
Expand Down

0 comments on commit f8e52ce

Please sign in to comment.