Skip to content

Commit

Permalink
Merge pull request #72 from x90skysn3k/v2.1.6
Browse files Browse the repository at this point in the history
V2.1.6
  • Loading branch information
x90skysn3k authored Feb 25, 2024
2 parents 09e5aab + 8fb9482 commit 74131f1
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 59 deletions.
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
target-branch: "dev"
schedule:
interval: "weekly"

- package-ecosystem: "github-actions"
directory: "/"
target-branch: "dev"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"

42 changes: 42 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Build Docker Images

on:
push:
branches:
- main
workflow_dispatch:
schedule:
- cron: "0 0 * * *"

jobs:
Dockerhub:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: checkout sources
uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v4
with:
push: true
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/386,linux/ppc64le
tags: |
ghcr.io/x90skysn3k/brutespray:latest
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# BruteSpray

![Version](https://img.shields.io/badge/Version-2.1.5-red)[![goreleaser](https://github.com/x90skysn3k/brutespray/actions/workflows/release.yml/badge.svg)](https://github.com/x90skysn3k/brutespray/actions/workflows/release.yml)[![Go Report Card](https://goreportcard.com/badge/github.com/x90skysn3k/brutespray)](https://goreportcard.com/report/github.com/x90skysn3k/brutespray)

![Version](https://img.shields.io/badge/Version-2.1.6-red)[![goreleaser](https://github.com/x90skysn3k/brutespray/actions/workflows/release.yml/badge.svg)](https://github.com/x90skysn3k/brutespray/actions/workflows/release.yml)[![Go Report Card](https://goreportcard.com/badge/github.com/x90skysn3k/brutespray)](https://goreportcard.com/report/github.com/x90skysn3k/brutespray)

Created by: Shane Young/@t1d3nio && Jacob Robles/@shellfail

Expand Down Expand Up @@ -36,7 +35,6 @@ Command: ```brutespray -f nmap.xml -u userlist -p passlist```

Command: ```brutespray -H ssh://127.0.0.1:22 -u userlist -p passlist```


## Examples

<img src="brutespray.gif" width="512">
Expand Down
10 changes: 7 additions & 3 deletions brute/run.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package brute

import (
"math"
"time"

"github.com/x90skysn3k/brutespray/modules"
Expand Down Expand Up @@ -29,11 +30,12 @@ func MapService(service string) string {
return service
}

func RunBrute(h modules.Host, u string, p string, progressCh chan<- int, timeout time.Duration, retry int) bool {
func RunBrute(h modules.Host, u string, p string, progressCh chan<- int, timeout time.Duration, retry int, output string) bool {
service := MapService(h.Service)
var result bool
var con_result bool
var retrying bool = false
var delayTime time.Duration = 1 * time.Second

for i := 0; i < retry; i++ {
switch service {
Expand Down Expand Up @@ -74,10 +76,12 @@ func RunBrute(h modules.Host, u string, p string, progressCh chan<- int, timeout
if con_result {
break
} else {
delayTime = time.Duration(int64(time.Second) * int64(math.Min(10, float64(i+2))))
retrying := true
modules.PrintResult(service, h.Host, h.Port, u, p, result, con_result, progressCh, retrying)
modules.PrintResult(service, h.Host, h.Port, u, p, result, con_result, progressCh, retrying, output, delayTime)
time.Sleep(delayTime)
}
}
modules.PrintResult(service, h.Host, h.Port, u, p, result, con_result, progressCh, retrying)
modules.PrintResult(service, h.Host, h.Port, u, p, result, con_result, progressCh, retrying, output, delayTime)
return con_result
}
104 changes: 63 additions & 41 deletions brutespray/brutespray.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ var masterServiceList = []string{"ssh", "ftp", "smtp", "mssql", "telnet", "smbnt

var alphaServiceList = []string{"asterisk"}

var version = "v2.1.5"
var version = "v2.1.6"

func Execute() {
user := flag.String("u", "", "Username or user list to bruteforce")
password := flag.String("p", "", "Password or password file to use for bruteforce")
output := flag.String("o", "brutespray-output", "Directory containing successful attempts")
threads := flag.Int("t", 10, "Number of threads to use")
hostParallelism := flag.Int("T", 5, "Number of hosts to bruteforce at the same time")
serviceType := flag.String("s", "all", "Service type: ssh, ftp, smtp, etc; Default all")
listServices := flag.Bool("S", false, "List all supported services")
file := flag.String("f", "", "File to parse; Supported: Nmap, Nessus, Nexpose, Lists, etc")
Expand Down Expand Up @@ -102,11 +104,11 @@ func Execute() {
}
}
}

bar, _ := pterm.DefaultProgressbar.WithTotal(len(hostsList)*(totalCombinations) - nopassServices).WithTitle("Bruteforcing...").Start()
bar, _ := pterm.DefaultProgressbar.WithTotal((totalCombinations) - nopassServices).WithTitle("Bruteforcing...").Start()
var wg sync.WaitGroup
var bruteForceWg sync.WaitGroup
sem := make(chan struct{}, *threads)
sem := make(chan struct{}, *threads**hostParallelism)
hostSem := make(chan struct{}, *hostParallelism)
sigs := make(chan os.Signal, 1)
progressCh := make(chan int, totalCombinations)

Expand All @@ -133,45 +135,20 @@ func Execute() {
if service == "vnc" || service == "snmp" {
u := ""
for _, h := range hostsList {
h := h
if h.Service == service {
_, passwords := modules.GetUsersAndPasswords(&h, *user, *password, version)
stopChan := make(chan struct{})
for _, p := range passwords {
wg.Add(1)
sem <- struct{}{}
go func(h modules.Host, p string) {
defer func() {
<-sem
wg.Done()
bruteForceWg.Done()
}()

select {
case <-stopChan:
default:
brute.RunBrute(h, u, p, progressCh, *timeout, *retry)
bruteForceWg.Add(1)
}
progressCh <- 1
}(h, p)
}
}
}
} else {
for _, h := range hostsList {
if h.Service == service {
for _, alpha := range alphaServiceList {
if alpha == h.Service {
modules.PrintWarningAlpha(h.Service)
}
}
users, passwords := modules.GetUsersAndPasswords(&h, *user, *password, version)
stopChan := make(chan struct{})
for _, u := range users {
hostSem <- struct{}{}

go func() {
defer func() { <-hostSem }()
for _, p := range passwords {
p := p
wg.Add(1)
sem <- struct{}{}
go func(h modules.Host, u, p string) {

go func(h modules.Host, p string) {
defer func() {
<-sem
wg.Done()
Expand All @@ -180,22 +157,67 @@ func Execute() {

select {
case <-stopChan:
return
default:
brute.RunBrute(h, u, p, progressCh, *timeout, *retry)
brute.RunBrute(h, u, p, progressCh, *timeout, *retry, *output)
bruteForceWg.Add(1)
}
progressCh <- 1
}(h, u, p)
}(h, p)
}
}()
}
}
} else {
for _, h := range hostsList {
h := h
if h.Service == service {
for _, alpha := range alphaServiceList {
if alpha == h.Service {
modules.PrintWarningAlpha(h.Service)
}
}

users, passwords := modules.GetUsersAndPasswords(&h, *user, *password, version)
stopChan := make(chan struct{})
hostSem <- struct{}{}

go func() {
defer func() { <-hostSem }()
for _, u := range users {
u := u
for _, p := range passwords {
p := p
wg.Add(1)
sem <- struct{}{}

go func(h modules.Host, u, p string) {
defer func() {
<-sem
wg.Done()
bruteForceWg.Done()
}()

select {
case <-stopChan:
return
default:
brute.RunBrute(h, u, p, progressCh, *timeout, *retry, *output)
bruteForceWg.Add(1)
}
progressCh <- 1
}(h, u, p)
}
}
}()
}
}
}
}(service)
}

wg.Wait()
for i := 0; i < cap(hostSem); i++ {
hostSem <- struct{}{}
}
for i := 0; i < cap(sem); i++ {
sem <- struct{}{}
}
Expand Down
34 changes: 22 additions & 12 deletions modules/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,36 @@ func getResultString(result bool) string {
}
}

func getConResultString(con_result bool, retrying bool) string {
func getConResultString(con_result bool, retrying bool, delayTime time.Duration) string {
var delaying bool
if delayTime > 2 {
delaying = true
}
if !retrying {
return "connection failed, giving up..."
} else if retrying && delaying {
return fmt.Sprintf("connection failed, retrying... delayed %s", delayTime)
} else {
return "connection failed, retrying..."
}
}

func WriteToFile(filename string, content string) error {
timestamp := time.Now().Format("2006010215")
dir := "output"
func WriteToFile(service string, content string, port int, output string) error {
var dir string
if output != "brutespray-output" {
dir = output
} else {
dir = output
}

if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.Mkdir(dir, 0755)
if err != nil {
return err
}
}
filename = filepath.Join(dir, filename+"_"+timestamp)

filename := filepath.Join(dir, fmt.Sprintf("%d-%s-success.txt", port, service))
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
Expand All @@ -48,22 +60,20 @@ func WriteToFile(filename string, content string) error {
return nil
}

func PrintResult(service string, host string, port int, user string, pass string, result bool, con_result bool, progressCh chan<- int, retrying bool) {
func PrintResult(service string, host string, port int, user string, pass string, result bool, con_result bool, progressCh chan<- int, retrying bool, output string, delayTime time.Duration) {

if result && con_result {
if service == "vnc" {
pterm.Success.Println("Attempt", service, "SUCCESS on host", host, "port", port, "with password", pass, getResultString(result))
content := fmt.Sprintf("Attempt %s SUCCESS on host %s port %d with password %s %s\n", service, host, port, pass, getResultString(result))
filename := filepath.Base(host)
err := WriteToFile(filename, content)
err := WriteToFile(service, content, port, output)
if err != nil {
fmt.Println("write file error:", err)
}
} else {
pterm.Success.Println("Attempt", service, "SUCCESS on host", host, "port", port, "with username", user, "and password", pass, getResultString(result))
content := fmt.Sprintf("Attempt %s SUCCESS on host %s port %d with username %s and password %s %s\n", service, host, port, user, pass, getResultString(result))
filename := filepath.Base(host)
err := WriteToFile(filename, content)
err := WriteToFile(service, content, port, output)
if err != nil {
fmt.Println("write file error:", err)
}
Expand All @@ -76,9 +86,9 @@ func PrintResult(service string, host string, port int, user string, pass string
}
} else if !result && !con_result {
if service == "vnc" {
pterm.Color(pterm.FgRed).Println("Attempt", service, "on host", host, "port", port, "with password", pass, getConResultString(con_result, retrying))
pterm.Color(pterm.FgRed).Println("Attempt", service, "on host", host, "port", port, "with password", pass, getConResultString(con_result, retrying, delayTime))
} else {
pterm.Color(pterm.FgRed).Println("Attempt", service, "on host", host, "port", port, "with username", user, "and password", pass, getConResultString(con_result, retrying))
pterm.Color(pterm.FgRed).Println("Attempt", service, "on host", host, "port", port, "with username", user, "and password", pass, getConResultString(con_result, retrying, delayTime))
}
}
}
Expand Down
Loading

0 comments on commit 74131f1

Please sign in to comment.