Skip to content

Commit

Permalink
Update flags order and set new flags to banner
Browse files Browse the repository at this point in the history
  • Loading branch information
devploit committed Jul 27, 2024
1 parent 034d0a0 commit 3b6b495
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 123 deletions.
245 changes: 126 additions & 119 deletions cmd/requester.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
package cmd

import (
"bufio"
"fmt"
"log"
"math/rand"
"net/url"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"time"
"unicode"

"github.com/fatih/color"
"github.com/zenthangplus/goccm"
"bufio"
"fmt"
"log"
"math/rand"
"net/url"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"time"
"unicode"

"github.com/fatih/color"
"github.com/zenthangplus/goccm"
)

type Result struct {
line string
statusCode int
contentLength int
defaultReq bool
line string
statusCode int
contentLength int
defaultReq bool
}


type RequestOptions struct {
uri string
headers []header
Expand All @@ -49,61 +48,67 @@ var defaultCl int
var printMutex = &sync.Mutex{}
var uniqueResults = make(map[string]bool)

// printResponse prints the results of HTTP requests in a tabular format with colored output based on the status codes.
// printResponse prints the results of HTTP requests in a tabular format with colored output based on the status codes.
func printResponse(result Result) {
printMutex.Lock()
defer printMutex.Unlock()

// Check if status code filtering is enabled
if len(statusCodes) > 0 {
statusMatch := false
for _, code := range statusCodes {
if strconv.Itoa(result.statusCode) == code {
statusMatch = true
break
}
}
if !statusMatch {
return
}
}

// Check for unique output if enabled
if uniqueOutput {
key := fmt.Sprintf("%d-%d", result.statusCode, result.contentLength)
if uniqueResults[key] {
return
}
uniqueResults[key] = true
}

resultContentLength := strconv.Itoa(result.contentLength) + " bytes"

var code string
switch result.statusCode {
case 200, 201, 202, 203, 204, 205, 206:
code = color.GreenString(strconv.Itoa(result.statusCode))
case 300, 301, 302, 303, 304, 307, 308:
code = color.YellowString(strconv.Itoa(result.statusCode))
case 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 429:
code = color.RedString(strconv.Itoa(result.statusCode))
case 500, 501, 502, 503, 504, 505, 511:
code = color.MagentaString(strconv.Itoa(result.statusCode))
}

if !_verbose {
if ((defaultSc == result.statusCode) && (defaultCl == result.contentLength) || result.contentLength == 0 || result.statusCode == 404 || result.statusCode == 400) && !result.defaultReq {
return
} else {
fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line)
}
} else {
fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line)
}
printMutex.Lock()
defer printMutex.Unlock()

// Check if status code filtering is enabled
if len(statusCodes) > 0 {
statusMatch := false
for _, code := range statusCodes {
if strconv.Itoa(result.statusCode) == code {
statusMatch = true
break
}
}
if !statusMatch {
return
}
}

// Check for unique output if enabled
if uniqueOutput {
key := fmt.Sprintf("%d-%d", result.statusCode, result.contentLength)
if uniqueResults[key] {
return
}
uniqueResults[key] = true
}

resultContentLength := strconv.Itoa(result.contentLength) + " bytes"

var code string
switch result.statusCode {
case 200, 201, 202, 203, 204, 205, 206:
code = color.GreenString(strconv.Itoa(result.statusCode))
case 300, 301, 302, 303, 304, 307, 308:
code = color.YellowString(strconv.Itoa(result.statusCode))
case 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 429:
code = color.RedString(strconv.Itoa(result.statusCode))
case 500, 501, 502, 503, 504, 505, 511:
code = color.MagentaString(strconv.Itoa(result.statusCode))
}

if !_verbose {
if ((defaultSc == result.statusCode) && (defaultCl == result.contentLength) || result.contentLength == 0 || result.statusCode == 404 || result.statusCode == 400) && !result.defaultReq {
return
} else {
fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line)
}
} else {
fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line)
}
}

func showInfo(options RequestOptions) {
var statusCodeStrings []string

for _, code := range statusCodes {
statusCodeStrings = append(statusCodeStrings, code)
}
statusCodesString := strings.Join(statusCodeStrings, ", ")

if !nobanner {
fmt.Println(`
________ ________ ________ ________ ________ ________ ________ ________ ________
Expand All @@ -112,34 +117,36 @@ func showInfo(options RequestOptions) {
╱ ╱ ╱ ╱ ╱ _╱ __/____ ╱ ╱ ╱
╲__╱_____╱╲________╱╲__╱__╱__╱╲________╱╲____╱___╱╲________╱ ╱____╱╲________╱╲________╱
`)
}
fmt.Printf("%s \t\t%s\n", "Target:", options.uri)
if len(options.reqHeaders[0]) != 0 {
for _, header := range options.headers {
fmt.Printf("%s \t\t%s\n", "Headers:", header)
fmt.Printf("%s \t\t%s\n", "Target:", options.uri)
if len(options.reqHeaders[0]) != 0 {
for _, header := range options.headers {
fmt.Printf("%s \t\t%s\n", "Headers:", header)
}
} else {
fmt.Printf("%s \t\t%s\n", "Headers:", "false")
}
} else {
fmt.Printf("%s \t\t%s\n", "Headers:", "false")
}
if len(options.proxy.Host) != 0 {
fmt.Printf("%s \t\t\t%s\n", "Proxy:", options.proxy.Host)
} else {
fmt.Printf("%s \t\t\t%s\n", "Proxy:", "false")
if len(options.proxy.Host) != 0 {
fmt.Printf("%s \t\t\t%s\n", "Proxy:", options.proxy.Host)
} else {
fmt.Printf("%s \t\t\t%s\n", "Proxy:", "false")
}
fmt.Printf("%s \t\t%s\n", "User Agent:", options.userAgent)
fmt.Printf("%s \t\t%s\n", "Method:", options.method)
fmt.Printf("%s \t%s\n", "Payloads folder:", options.folder)
if len(bypassIP) != 0 {
fmt.Printf("%s \t%s\n", "Custom bypass IP:", options.bypassIP)
} else {
fmt.Printf("%s \t%s\n", "Custom bypass IP:", "false")
}
fmt.Printf("%s \t%s\n", "Follow Redirects:", strconv.FormatBool(options.redirect))
fmt.Printf("%s \t%s\n", "Rate Limit detection:", strconv.FormatBool(options.rateLimit))
fmt.Printf("%s \t\t%s\n", "Status:", statusCodesString)
fmt.Printf("%s \t\t%d\n", "Timeout (ms):", options.timeout)
fmt.Printf("%s \t\t%d\n", "Delay (ms):", delay)
fmt.Printf("%s \t\t%s\n", "Techniques:", strings.Join(options.techniques, ", "))
fmt.Printf("%s \t\t%t\n", "Unique:", uniqueOutput)
fmt.Printf("%s \t\t%t\n", "Verbose:", options.verbose)
}
fmt.Printf("%s \t\t%s\n", "User Agent:", options.userAgent)
fmt.Printf("%s \t\t%s\n", "Method:", options.method)
fmt.Printf("%s \t%s\n", "Payloads folder:", options.folder)
if len(bypassIP) != 0 {
fmt.Printf("%s \t%s\n", "Custom bypass IP:", options.bypassIP)
} else {
fmt.Printf("%s \t%s\n", "Custom bypass IP:", "false")
}
fmt.Printf("%s \t%s\n", "Follow Redirects:", strconv.FormatBool(options.redirect))
fmt.Printf("%s \t%s\n", "Rate Limit detection:", strconv.FormatBool(options.rateLimit))
fmt.Printf("%s \t\t%d\n", "Timeout (ms):", options.timeout)
fmt.Printf("%s \t\t%d\n", "Delay (ms):", delay)
fmt.Printf("%s \t\t%s\n", "Techniques:", strings.Join(options.techniques, ", "))
fmt.Printf("%s \t\t%t\n", "Verbose:", options.verbose)
}

// generateCaseCombinations generates all combinations of uppercase and lowercase letters for a given string.
Expand Down Expand Up @@ -592,7 +599,7 @@ func requester(uri string, proxy string, userAgent string, reqHeaders []string,
} else {
line, err := randomLine(folder + "/useragents")
if err != nil {
fmt.Println("Error al leer el archivo:", err)
fmt.Println("Error reading the file:", err)
return
}
userAgent = line
Expand All @@ -617,28 +624,28 @@ func requester(uri string, proxy string, userAgent string, reqHeaders []string,

_verbose = verbose

options := RequestOptions{
uri: uri,
headers: headers,
method: method,
proxy: userProxy,
userAgent: userAgent,
redirect: redirect,
folder: folder,
bypassIP: bypassIP,
timeout: timeout,
rateLimit: rateLimit,
verbose: verbose,
techniques: techniques,
reqHeaders: reqHeaders,
banner: banner,
}

// Reset uniqueResults map before starting new requests
uniqueResults = make(map[string]bool)

// Call each function that will send HTTP requests with different variations of headers and URLs.
showInfo(options)
options := RequestOptions{
uri: uri,
headers: headers,
method: method,
proxy: userProxy,
userAgent: userAgent,
redirect: redirect,
folder: folder,
bypassIP: bypassIP,
timeout: timeout,
rateLimit: rateLimit,
verbose: verbose,
techniques: techniques,
reqHeaders: reqHeaders,
banner: banner,
}

// Reset uniqueResults map before starting new requests
uniqueResults = make(map[string]bool)

// Call each function that will send HTTP requests with different variations of headers and URLs.
showInfo(options)

for _, tech := range techniques {
switch tech {
Expand Down
6 changes: 2 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,13 @@ func init() {
rootCmd.PersistentFlags().BoolVarP(&rateLimit, "rate-limit", "l", false, "Halt requests upon encountering a 429 (rate limit) HTTP status code.")
rootCmd.PersistentFlags().BoolVarP(&redirect, "redirect", "r", false, "Automatically follow redirects in responses.")
rootCmd.PersistentFlags().StringVarP(&requestFile, "request-file", "", "", "Load request configuration and flags from a specified file.")
rootCmd.PersistentFlags().StringSliceVarP(&statusCodes, "status", "", []string{}, "Filter output by comma-separated status codes (e.g., 200,301,403)")
rootCmd.PersistentFlags().StringSliceVarP(&technique, "technique", "k", []string{"verbs", "verbs-case", "headers", "endpaths", "midpaths", "http-versions", "path-case"}, "Specify one or more attack techniques to use (e.g., headers,path-case).")
rootCmd.PersistentFlags().IntVarP(&timeout, "timeout", "", 6000, "Specify a max timeout time in ms.")
rootCmd.PersistentFlags().BoolVarP(&uniqueOutput, "unique", "", false, "Show unique output based on status code and response length")
rootCmd.PersistentFlags().StringVarP(&uri, "uri", "u", "", "Specify the target URL for the request.")
rootCmd.PersistentFlags().StringVarP(&userAgent, "user-agent", "a", "", "Specify a custom User-Agent string for requests (default: 'nomore403').")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose output for detailed request/response logging.")

// New flags
rootCmd.PersistentFlags().StringSliceVarP(&statusCodes, "status", "", []string{}, "Filter output by comma-separated status codes (e.g., 200,301,403)")
rootCmd.PersistentFlags().BoolVarP(&uniqueOutput, "unique", "", false, "Show unique output based on status code and response length")
}

// initConfig reads in config file and ENV variables if set.
Expand Down

0 comments on commit 3b6b495

Please sign in to comment.