Skip to content

Commit

Permalink
full display
Browse files Browse the repository at this point in the history
  • Loading branch information
ariary committed Sep 14, 2022
1 parent 96265e9 commit b8109c6
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 44 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Additionaly, it is possible to filter displayed results:
-emin, --stderr-min filter to only display if stderr characters number is lesser than n
-emax, --stderr-max filter to only display if stderr characters number is greater than n
-eeq, --stderr-equal filter to only display if stderr characters number is equal to n
-ew, --stderr-word filter to only display if stderr cointains specific word
```
**execution time filters:**
Expand Down Expand Up @@ -122,5 +123,6 @@ It is also possible to choose which result field is displayed in `cfuzz` output
-t, --time display execution time
-c, --code display exit code
-Hb, --no-banner do not display banner
-w, --only-word only display words
-r, --only-word only display words
-f, --full-output display full command execution output (can't be combined with others display mode)
```
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/ariary/cfuzz

go 1.17

require github.com/ariary/go-utils v1.0.16
41 changes: 30 additions & 11 deletions pkg/fuzz/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Config struct {
Multiple bool
StdinWordlist bool
DisplayModes []DisplayMode
FullDisplay bool
HideBanner bool
Hide bool
Filters []Filter
Expand All @@ -43,31 +44,30 @@ CONFIGURATION
-if, --stdin-fuzzing fuzz sdtin instead of command line
-m, --spider fuzz multiple keyword places. You must provide as many wordlists as keywords. Provide them in order you want them to be applied.
-sw, --stdin-wordlist provide wordlist in cfuzz stdin
-T, --threads number of concurrent threads (if no limit is set the execution of the command could be modified)
DISPLAY
-oc, --stdout display stdout number of characters
-ec, --stderr display stderr number of characters
-t, --time display execution time
-c, --code display exit code
-Hb, --no-banner do not display banner
-w, --only-word only display words
-r, --only-word only display words (from wordlist)
-f, --full-output display full command execution output (can't be combined with others display mode)
FILTER
-H, --hide only display results that don't pass the filters
STDOUT:
-omin, --stdout-min filter to only display if stdout characters number is lesser than n
-omax, --stdout-max filter to only display if stdout characters number is greater than n
-oeq, --stdout-equal filter to only display if stdout characters number is equal to n
-r, --stdout-word filter to only display if stdout cointains specific word
-ow, --stdout-word filter to only display if stdout cointains specific word
STDERR:
-emin, --stderr-min filter to only display if stderr characters number is lesser than n
-emax, --stderr-max filter to only display if stderr characters number is greater than n
-eeq, --stderr-equal filter to only display if stderr characters number is equal to n
-ew, --stderr-word filter to only display if stderr cointains specific word
TIME:
-tmin, --time-min filter to only display if exectuion time is shorter than n seconds
Expand Down Expand Up @@ -168,6 +168,9 @@ func NewConfig() Config {
flag.BoolVar(&codeDisplay, "c", false, "display command execution exit code.")
flag.BoolVar(&codeDisplay, "code", false, "display command execution exit code.")

flag.BoolVar(&config.FullDisplay, "f", false, "display full command execution output")
flag.BoolVar(&config.FullDisplay, "full-output", false, "display full command execution output")

// FILTERS
var success, failure bool
flag.BoolVar(&success, "success", false, "filter to display only command with exit code 0.")
Expand All @@ -190,7 +193,7 @@ func NewConfig() Config {

// parse display mode
if !noDisplay {
config.DisplayModes = parseDisplayMode(stdoutDisplay, stderrDisplay, timeDisplay, codeDisplay)
config.DisplayModes = parseDisplayMode(&config, stdoutDisplay, stderrDisplay, timeDisplay, codeDisplay)
}

return config
Expand Down Expand Up @@ -222,6 +225,10 @@ func (c *Config) CheckConfig() error {
} else if !c.Multiple && len(c.Wordlists) > 1 {
return errors.New("Several wordlists have been submitted. Please use -m flag to use more than one wordlist/keyword")
}

if c.FullDisplay && len(c.DisplayModes) > 0 {
return errors.New("-f/full-output can't be used with other display mode:" + c.DisplayModes[0].Name()) //only give the first one for example
}
// check field consistency
err := checkKeywordsPresence(c)

Expand Down Expand Up @@ -254,7 +261,7 @@ func checkKeywordsPresence(c *Config) error {
}

//parseDisplayMode: Return array of display mode interface chosen with flags. If none, default is stdout characters display mode
func parseDisplayMode(stdout bool, stderr bool, time bool, code bool) (modes []DisplayMode) {
func parseDisplayMode(c *Config, stdout bool, stderr bool, time bool, code bool) (modes []DisplayMode) {
if stdout {
modes = append(modes, StdoutDisplay{})
}
Expand All @@ -268,11 +275,14 @@ func parseDisplayMode(stdout bool, stderr bool, time bool, code bool) (modes []D
modes = append(modes, CodeDisplay{})
}

//default, if none
if len(modes) == 0 {
stdoutDisplay := StdoutDisplay{}
modes = []DisplayMode{stdoutDisplay}
//default, if none && not full display
if !c.FullDisplay {
if len(modes) == 0 {
stdoutDisplay := StdoutDisplay{}
modes = []DisplayMode{stdoutDisplay}
}
}

return modes
}

Expand Down Expand Up @@ -367,6 +377,15 @@ func parseFilters(config *Config) {
})
}

ewordS := []string{"ew", "stderr-word"}
for i := 0; i < len(ewordS); i++ {
flag.Func(ewordS[i], "filter to display only results cointaing specific in stderr", func(word string) error {
filter := StderrWordFilter{TargetWord: word}
config.Filters = append(config.Filters, filter)
return nil
})
}

// time filters
tmaxS := []string{"tmax", "time-max"}
for i := 0; i < len(tmaxS); i++ {
Expand Down
30 changes: 28 additions & 2 deletions pkg/fuzz/filter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package fuzz

import "strings"
import (
"strings"
)

// Filter: interface used to determine which results will be displayed
type Filter interface {
Expand All @@ -10,6 +12,8 @@ type Filter interface {
Name() string
}

// STDOUT FILTERS

// StdoutMaxFilter: Filter that accept only result with less characters than a specific number
type StdoutMaxFilter struct {
Max int
Expand Down Expand Up @@ -38,7 +42,7 @@ func (filter StdoutMinFilter) IsOk(result ExecResult) bool {
return len(result.Stdout) >= filter.Min
}

//StdoutEqFilter: filter struct that accept only result with exact amoun of characters
//StdoutEqFilter: filter struct that accept only result with exact amount of characters
type StdoutEqFilter struct {
Eq int
}
Expand Down Expand Up @@ -68,6 +72,8 @@ func (filter StdoutWordFilter) IsOk(result ExecResult) bool {
return strings.Contains(result.Stdout, filter.TargetWord)
}

// STDERR FILTERS

//StderrMaxFilter: Filter that accept only result with less characters than a specific number
type StderrMaxFilter struct {
Max int
Expand Down Expand Up @@ -108,6 +114,24 @@ func (filter StderrEqFilter) IsOk(result ExecResult) bool {
return len(result.Stderr) == filter.Eq
}

//StderrWordFilter: filter struct that accept only result containing specific word for stderr
type StderrWordFilter struct {
TargetWord string
}

//Name: return StdoutWordFilter name
func (filter StderrWordFilter) Name() string {
return "stderr word containing"
}

//IsOK: return true a specific word is found in result stdout. Note that this is equivalent to grep:
//the word could be surrounded by non-space characters
func (filter StderrWordFilter) IsOk(result ExecResult) bool {
return strings.Contains(result.Stderr, filter.TargetWord)
}

// TIME FILTERS

type TimeMaxFilter struct {
Max int
}
Expand Down Expand Up @@ -144,6 +168,8 @@ func (filter TimeEqFilter) IsOk(result ExecResult) bool {
return int(result.Time.Seconds()) == filter.Eq
}

// CODE FILTERS

// CodeSuccessFilter: filter wether result regarding the exit code
type CodeSuccessFilter struct {
Zero bool
Expand Down
39 changes: 16 additions & 23 deletions pkg/fuzz/fuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,29 +193,22 @@ func Exec(cfg Config, wg *sync.WaitGroup, substitutesStr []string) {

// PrintExec: Print execution result according to configuration and filter
func PrintExec(cfg Config, result ExecResult) {
// filter
// if cfg.Hide { //hide field that pass filter and show others
// for i := 0; i < len(cfg.Filters); i++ {
// if cfg.Filters[i].IsOk(result) {
// return //don't display it
// }
// }
// } else {
// for i := 0; i < len(cfg.Filters); i++ {
// if !cfg.Filters[i].IsOk(result) {
// return //don't display it
// }
// }
// }
for i := 0; i < len(cfg.Filters); i++ {
if cfg.Filters[i].IsOk(result) == cfg.Hide {
return //don't display it
if cfg.FullDisplay {
PrintFullExecOutput(cfg, result)
return
} else {

for i := 0; i < len(cfg.Filters); i++ {
if cfg.Filters[i].IsOk(result) == cfg.Hide {
return //don't display it
}
}
// display

var fields []string
for i := 0; i < len(cfg.DisplayModes); i++ {
fields = append(fields, cfg.DisplayModes[i].DisplayString(result))
}
PrintLine(cfg, result.Substitute, fields...)
}
// display
var fields []string
for i := 0; i < len(cfg.DisplayModes); i++ {
fields = append(fields, cfg.DisplayModes[i].DisplayString(result))
}
PrintLine(cfg, result.Substitute, fields...)
}
34 changes: 27 additions & 7 deletions pkg/fuzz/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ import (
"fmt"
"strings"
"text/tabwriter"

"github.com/ariary/go-utils/pkg/color"
)

// Banner: Print the banner as it is trendy for this kind of tool. thanks to: https://patorjk.com/software/taag
func Banner() {
banner := `
var nameDraw = color.Teal(`
_/_/
_/_/_/ _/ _/ _/ _/_/_/_/ _/_/_/_/
_/ _/_/_/_/ _/ _/ _/ _/
_/ _/ _/ _/ _/ _/
_/_/_/ _/ _/_/_/ _/_/_/_/ _/_/_/_/
By @ariary (https://github.com/ariary)
`
`)
var author = color.Yellow("By @ariary (" + color.Underlined("https://github.com/ariary") + ")")

// Banner: Print the banner as it is trendy for this kind of tool. thanks to: https://patorjk.com/software/taag
func Banner() {
banner := nameDraw + author
fmt.Println(banner)
fmt.Println()
}
Expand Down Expand Up @@ -54,14 +57,14 @@ func PrintConfig(cfg Config) {
PrintLine(cfg, "filters:", allFilters)
}
if cfg.Hide {
fmt.Println("Only displays filter that do not pass the filter")
fmt.Println("Only displays words that do not pass the filter")
}
fmt.Println()
fmt.Println(line)
fmt.Println()
}

// Nice printing of a line containing 2 or more elements
//PrintLine: Nice printing of a line containing 2 or more elements
func PrintLine(cfg Config, value string, element ...string) {
// string builder and tabwriter
var strBuilder strings.Builder
Expand All @@ -79,3 +82,20 @@ func PrintLine(cfg Config, value string, element ...string) {
cfg.ResultLogger.Println(strBuilder.String())

}

//PrintFullExecOutput Nice printing of command execution
func PrintFullExecOutput(cfg Config, result ExecResult) {
//TODO
cfg.ResultLogger.Println()
cfg.ResultLogger.Println(color.Bold(color.Cyan(result.Substitute)))
if result.Stdout != "" {
cfg.ResultLogger.Println(color.GreenForeground("STDOUT:"))
cfg.ResultLogger.Println(result.Stdout)
}
if result.Stderr != "" {
cfg.ResultLogger.Println(color.RedForeground("STDERR:"))
cfg.ResultLogger.Println(result.Stderr)
}

cfg.ResultLogger.Println()
}

0 comments on commit b8109c6

Please sign in to comment.