diff --git a/go.mod b/go.mod index 99f4efcfb..b6c68d24e 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/projectdiscovery/nuclei go 1.14 require ( + github.com/projectdiscovery/gologger v1.0.0 github.com/stretchr/testify v1.5.1 github.com/valyala/fasttemplate v1.1.0 gopkg.in/yaml.v2 v2.2.2 diff --git a/go.sum b/go.sum index 3285573c4..326d2a19d 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/projectdiscovery/gologger v1.0.0 h1:XAQ8kHeVKXMjY4rLGh7eT5+oHU077BNEvs7X6n+vu1s= +github.com/projectdiscovery/gologger v1.0.0/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= diff --git a/internal/runner/banner.go b/internal/runner/banner.go new file mode 100644 index 000000000..f246d2601 --- /dev/null +++ b/internal/runner/banner.go @@ -0,0 +1,23 @@ +package runner + +import "github.com/projectdiscovery/gologger" + +const banner = ` + __ _ + ____ __ _______/ /__ (_) + / __ \/ / / / ___/ / _ \/ / + / / / / /_/ / /__/ / __/ / + /_/ /_/\__,_/\___/_/\___/_/ v1 +` + +// Version is the current version of nuclei +const Version = `1.0.0` + +// showBanner is used to show the banner to the user +func showBanner() { + gologger.Printf("%s\n", banner) + gologger.Printf("\t\tprojectdiscovery.io\n\n") + + gologger.Labelf("Use with caution. You are responsible for your actions\n") + gologger.Labelf("Developers assume no liability and are not responsible for any misuse or damage.\n") +} diff --git a/internal/runner/doc.go b/internal/runner/doc.go new file mode 100644 index 000000000..6f0967cb4 --- /dev/null +++ b/internal/runner/doc.go @@ -0,0 +1,2 @@ +// Package runner executes the enumeration process. +package runner diff --git a/internal/runner/options.go b/internal/runner/options.go new file mode 100644 index 000000000..33bd2f5ab --- /dev/null +++ b/internal/runner/options.go @@ -0,0 +1,74 @@ +package runner + +import ( + "flag" + "os" + + "github.com/projectdiscovery/gologger" +) + +// Options contains the configuration options for tuning +// the template requesting process. +type Options struct { + Templates string // Signature specifies the template/templates to use + Targets string // Targets specifies the targets to scan using templates. + Threads int // Thread controls the number of concurrent requests to make. + Timeout int // Timeout is the seconds to wait for a response from the server. + Output string // Output is the file to write found subdomains to. + Silent bool // Silent suppresses any extra text and only writes found URLs on screen. + Version bool // Version specifies if we should just show version and exit + Verbose bool // Verbose flag indicates whether to show verbose output or not + NoColor bool // No-Color disables the colored output. + + Stdin bool // Stdin specifies whether stdin input was given to the process +} + +// ParseOptions parses the command line flags provided by a user +func ParseOptions() *Options { + options := &Options{} + + flag.StringVar(&options.Templates, "f", "", "Template(s) to use during enumeration") + flag.StringVar(&options.Targets, "l", "", "Targets to scan using templates during enumeration") + flag.StringVar(&options.Output, "o", "", "File to write output to (optional)") + flag.BoolVar(&options.Silent, "silent", false, "Show only subdomains in output") + flag.BoolVar(&options.Version, "version", false, "Show version of shuffledns") + flag.BoolVar(&options.Verbose, "v", false, "Show Verbose output") + flag.BoolVar(&options.NoColor, "nC", false, "Don't Use colors in output") + flag.IntVar(&options.Threads, "t", 100, "Number of concurrent requests to make") + flag.IntVar(&options.Timeout, "timeout", 30, "Time to wait in seconds before timeout") + + flag.Parse() + + // Check if stdin pipe was given + options.Stdin = hasStdin() + + // Read the inputs and configure the logging + options.configureOutput() + + // Show the user the banner + showBanner() + + if options.Version { + gologger.Infof("Current Version: %s\n", Version) + os.Exit(0) + } + // Validate the options passed by the user and if any + // invalid options have been used, exit. + err := options.validateOptions() + if err != nil { + gologger.Fatalf("Program exiting: %s\n", err) + } + + return options +} + +func hasStdin() bool { + fi, err := os.Stdin.Stat() + if err != nil { + return false + } + if fi.Mode()&os.ModeNamedPipe == 0 { + return false + } + return true +} diff --git a/internal/runner/validate.go b/internal/runner/validate.go new file mode 100644 index 000000000..c9a4cf408 --- /dev/null +++ b/internal/runner/validate.go @@ -0,0 +1,36 @@ +package runner + +import ( + "errors" + + "github.com/projectdiscovery/gologger" +) + +// validateOptions validates the configuration options passed +func (options *Options) validateOptions() error { + // Both verbose and silent flags were used + if options.Verbose && options.Silent { + return errors.New("both verbose and silent mode specified") + } + + // Check if a list of resolvers was provided and it exists + if options.Templates == "" { + return errors.New("no template/templates provided") + } + + return nil +} + +// configureOutput configures the output on the screen +func (options *Options) configureOutput() { + // If the user desires verbose output, show verbose output + if options.Verbose { + gologger.MaxLevel = gologger.Verbose + } + if options.NoColor { + gologger.UseColors = false + } + if options.Silent { + gologger.MaxLevel = gologger.Silent + } +}