Skip to content

Commit 38e7329

Browse files
author
ekultek
committed
created a terminal output for the program that implements #64 and #49
1 parent 778bcce commit 38e7329

File tree

5 files changed

+288
-0
lines changed

5 files changed

+288
-0
lines changed
File renamed without changes.

lib/exploitation/__init__.py

Whitespace-only changes.

lib/exploitation/exploiter.py

Whitespace-only changes.

lib/term/__init__.py

Whitespace-only changes.

lib/term/terminal.py

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
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

Comments
 (0)