Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cli arguments handling #7

Merged
merged 5 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

NAME = bruteforce

SRC = src/main.go

all: $(NAME)
Expand All @@ -15,4 +16,8 @@ fclean:

re: fclean all

.PHONY: all clean fclean re
install_program:
echo "source $(pwd)/autocompletion/bash/_bruteforce" >> ~/.bashrc
echo "source $(pwd)/autocompletion/zsh/_bruteforce" >> ~/.zshrc

.PHONY: all clean fclean re install_program
28 changes: 28 additions & 0 deletions autocompletion/bash/_bruteforce
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

_bruteforce_completion() {
local cur prev opts
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--threads -v --status-codes --header --body --wordlist"

if [[ ${COMP_CWORD} -eq 1 ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
elif [[ ${COMP_CWORD} -eq 2 ]]; then
case "${prev}" in
--threads)
COMPREPLY=( $(compgen -W "1 2 4 8 16 32" -- "${cur}") )
;;
--status-codes)
COMPREPLY=( $(compgen -W "200 401 403 404 429 500" -- "${cur}") )
;;
--header|--body|--wordlist)
COMPREPLY=()
;;
esac
else
COMPREPLY=( $(compgen -W "http:// https://" -- "${cur}") )
fi
}

complete -F _bruteforce_completion bruteforce
23 changes: 23 additions & 0 deletions autocompletion/zsh/_bruteforce
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#compdef bruteforce

_bruteforce() {
local -a args

args=(
'-v[verbose mode]'
'--threads=[number of threads]:number of threads:(1 2 4 8 16 32)'
'--status-codes=[Comma-separated list of status codes to match]:status codes:'
'--header=[Header to match]:header:'
'--body=[String to match in response body]:body:'
'--wordlist=[Wordlist to bruteforce URLs with]:wordlist:_files'
'*:url:_bruteforce_urls'
)

_arguments -s $args
}

_bruteforce_urls() {
_urls -p 'http://' 'https://'
}

compdef _bruteforce bruteforce
45 changes: 45 additions & 0 deletions src/cli/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cli

import (
"bruteforce/src/models"
"errors"
"flag"
"fmt"
"os"
)

func Parse_cli_args() (models.Forcing_params, error) {
var params models.Forcing_params

UrlError := errors.New("No url given")
ThreadsError := errors.New("Wrong number of threads given")

forkptr := flag.Bool("v", false, "Verbose program")
statusPtr := flag.String("status-codes", "200,401,403,404,429,500", "Comma-separated list of status codes to match")
headerPtr := flag.String("header", "", "Header to match")
bodyPtr := flag.String("body", "", "String to match in response body")
wordlistPtr := flag.String("wordlist", "", "Wordlist to bruteforce url with")
flag.IntVar(&params.Workers, "threads", 1, "Number of threads to be used")

flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: bruteforce [options] <url>\n")
fmt.Fprintf(os.Stderr, "Options:\n")
flag.PrintDefaults()
}

flag.Parse()

if params.Workers < 1 {
return params, ThreadsError
}
if len(flag.Args()) != 1 {
return params, UrlError
}
params.Url = flag.Args()[0]
params.BoolFlags.Verbose = *forkptr
params.Status = *statusPtr
params.Header = *headerPtr
params.Body = *bodyPtr
params.Wordlist = *wordlistPtr
return params, nil
}
31 changes: 8 additions & 23 deletions src/main.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
package main

import (
"bruteforce/src/cli"
"bruteforce/src/matching"
"bruteforce/src/query"
"flag"
"fmt"
)

func main() {
usagePtr := flag.Bool("help", false, "a bool")
statusPtr := flag.String("status-codes", "200,401,403,404,429,500", "Comma-separated list of status codes to match")
headerPtr := flag.String("header", "", "Header to match")
bodyPtr := flag.String("body", "", "String to match in response body")

flag.Parse()
if *usagePtr {
fmt.Println("Usage for matching options:\n\nuse flag -status-codes=\"<status-options>\"")
fmt.Println("\tstatus-options\t200,202,400,404 (Comma-separated list)")
fmt.Println("\t\t\tall")
fmt.Println("\t\t\t[By default: 200,401,403,404,429,500]")
fmt.Println("\nuse flag -header=\"<key:value>\"")
fmt.Println("use flag -body=\"<string-in-body>\"")
return
forcing_params, err := cli.Parse_cli_args()

if err != nil {
panic(err)
}
fmt.Println(forcing_params)

criteria := matcher.MatchParser(*statusPtr, *headerPtr, *bodyPtr)
fmt.Println(criteria)
criteria := matcher.MatchParser(&forcing_params)

data := query.ForceData{
Worker: 3,
WordList: "../wordList/rootList",
Url: "http://localhost:3333",
}
// matcher.MatchResponse can be called with criteria (above) in parameter
query.MainRequest(data, criteria) // maybe like this?
query.MainRequest(&forcing_params, criteria) // maybe like this?
}
9 changes: 5 additions & 4 deletions src/matching/matcher.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package matcher

import (
"bruteforce/src/models"
"io"
"log"
"net/http"
Expand Down Expand Up @@ -31,17 +32,17 @@ func MatchResponse(response *http.Response, criteria MatchCriteria) (bool, strin
return true, "matched successfully"
}

func MatchParser(statuses string, headers string, bodyContains string) MatchCriteria {
matchCodes, err := parseStatusCodes(statuses)
func MatchParser(params *models.Forcing_params) MatchCriteria {
matchCodes, err := parseStatusCodes(params.Status)
if err != nil {
log.Fatal("Error parsing status codes:", err)
}

matchHeaders := parseHeaders(headers)
matchHeaders := parseHeaders(params.Header)
criteria := MatchCriteria{
StatusCodes: matchCodes,
Headers: matchHeaders,
BodyContains: bodyContains,
BodyContains: params.Body,
}

return criteria
Expand Down
15 changes: 15 additions & 0 deletions src/models/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package models

type boolflags struct {
Verbose bool
}

type Forcing_params struct {
Workers int
Url string
Wordlist string
BoolFlags boolflags
Status string
Header string
Body string
}
18 changes: 7 additions & 11 deletions src/query/callWorker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,27 @@ package query

import (
"bruteforce/src/matching"
"bruteforce/src/models"
"bruteforce/src/utils"
"sync"
)

type ForceData struct {
Worker int
WordList string
Url string
}

func executeQueryFromFile(wg *sync.WaitGroup, data ForceData, currentPath chan string) {
func executeQueryFromFile(wg *sync.WaitGroup, params *models.Forcing_params, currentPath chan string) {
defer wg.Done()
for taskData := range currentPath {
QueryExecute(data, taskData, "POST")
QueryExecute(params, taskData, "POST")
}
}

func MainRequest(data ForceData, criteria matcher.MatchCriteria) {
func MainRequest(params *models.Forcing_params, criteria matcher.MatchCriteria) {
wg := &sync.WaitGroup{}
wg.Add(data.Worker)
channel := make(chan string)
wordArray := utils.GetFileContent(data.WordList)
wordArray := utils.GetFileContent(params.Wordlist)

for i := 0; i < data.Worker; i++ {
go executeQueryFromFile(wg, data, channel)
for i := 0; i < params.Workers; i++ {
go executeQueryFromFile(wg, params, channel)
}
for i := 0; i < len(wordArray); i++ {
channel <- wordArray[i]
Expand Down
5 changes: 3 additions & 2 deletions src/query/queryExecute.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package query

import (
"bruteforce/src/models"
"fmt"
"io"
"log"
"net/http"
)

func QueryExecute(data ForceData, path string, method string) {
func QueryExecute(params *models.Forcing_params, path string, method string) {
client := &http.Client{}
req, err := http.NewRequest(method, data.Url+path, nil)
req, err := http.NewRequest(method, params.Url+path, nil)
if err != nil {
log.Fatal(err)
}
Expand Down
Loading