-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
146 lines (131 loc) · 3.04 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
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"strings"
"text/template"
)
const (
defaultBg = "-"
defaultFg = "N"
)
// Default behavior. Can be changed with command line arguments.
var (
userAgent = "graffiti"
repeats = 1
verbose = false
dryRun = false
silent = false
bg = defaultBg
fg = defaultFg
)
var summaryTmpl = `Text: {{.Text}}
Destination: {{.BaseURL}}
User Agent: {{.UserAgent}}
{{if (gt .Repeats 1)}}Repeats: {{.Repeats}}
{{end}}{{if .DryRun}}** Dry Run Mode **
{{end}}{{if not .Verbose}}** Use -v to switch verbose mode on **
{{end}}`
// Prints a summary before starting http requests.
func printSummary(text, baseURL string) {
t, err := template.New("summary_tmpl").Parse(summaryTmpl)
if err != nil {
log.Fatalln(err)
}
err = t.Execute(os.Stdout, struct {
Text string
BaseURL string
UserAgent string
Repeats int
DryRun bool
Verbose bool
}{
text, baseURL, userAgent, repeats, dryRun, verbose,
})
if err != nil {
log.Fatalln(err)
}
}
// 404 party, graffiti in action
func graffitiAttack(text, baseURL string) {
graffiti := toBanner(text)
for i := 0; i < repeats; i++ {
for _, line := range graffiti {
if verbose {
fmt.Println(line)
}
if !dryRun {
_, err := requestLine(baseURL + line)
if err != nil {
log.Fatalln(err)
}
}
}
}
}
// Adds protocol prefix if necessary
func formatBaseURL(destination string) string {
baseURL := destination
if !strings.HasPrefix(destination, "http://") && !strings.HasPrefix(destination, "https://") {
baseURL = "http://" + baseURL
} else {
baseURL = destination
}
if !strings.HasSuffix(baseURL, "/") {
baseURL = baseURL + "/"
}
return baseURL
}
// Single requests to a remote server. Contains a single line
// of the banner as a request path. A 404 error is expected.
func requestLine(url string) (status int, err error) {
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return
}
req.Header.Set("User-Agent", userAgent)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
status = resp.StatusCode
return
}
func main() {
var (
text string
destination string
)
// Command line Args parsing
flag.StringVar(&text, "t", "", "Text to send to the remote server")
flag.StringVar(&destination, "d", "", "Destination (ie: www.example.com)")
flag.StringVar(&userAgent, "a", userAgent, "User Agent")
flag.IntVar(&repeats, "r", repeats, "Number of times to execute")
flag.BoolVar(&verbose, "v", verbose, "Verbose output")
flag.BoolVar(&dryRun, "n", dryRun, "Dry Run")
flag.BoolVar(&silent, "s", silent, "Silent or quiet mode")
flag.StringVar(&bg, "bg", defaultBg, "Background")
flag.StringVar(&fg, "fg", defaultFg, "Foreground")
flag.Parse()
// Configuration
if dryRun {
verbose = true
}
if silent {
verbose = false
}
if text == "" || destination == "" {
flag.PrintDefaults()
os.Exit(1)
}
baseURL := formatBaseURL(destination)
if !silent {
printSummary(text, baseURL)
}
graffitiAttack(text, baseURL)
}