forked from isaudits/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfastnetntlm.py
executable file
·215 lines (188 loc) · 11.6 KB
/
fastnetntlm.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
212
213
214
215
#!/usr/bin/env python
####################################################################################
# Orig Authors: Tim Medin & Dan Borkowski
# Description: An automated method of reading netntlm hashes and cracking them
####################################################################################
from __future__ import with_statement # Required in 2.5
from sys import *
import sys
import os
import time
import subprocess
import fileinput
from optparse import OptionParser
from optparse import OptionGroup
from datetime import datetime
from sets import Set
import signal
from contextlib import contextmanager
class AlreadyCracked(Exception): pass
#timeout code pulled from http://stackoverflow.com/questions/366682/how-to-limit-execution-time-of-a-function-call-in-python
class TimeoutException(Exception): pass
@contextmanager
def time_limit(seconds):
def signal_handler(signum, frame):
raise TimeoutException, "Timed out!"
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(seconds)
try:
yield
finally:
signal.alarm(0)
#originally SIGINT would occassionally require 'stty sane/reset'
def signal_handler(signal, frame):
try:
os.system("stty sane")
sys.exit(0)
except:
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
#set default file paths
path_perl = "/usr/bin/perl"
#path_johnnetntlm = "/usr/share/john/netntlm.pl" #default
path_johnnetntlm = "/usr/share/metasploit-framework/data/john/run.linux.x64.mmx/netntlm.pl" #kali
path_rcracki = "/usr/bin/rcracki_mt"
path_rt_alpha = "/opt/tables/rcracki_mt/Halflm_tables_alphanum"
path_rt_allspace = "/opt/tables/rcracki_mt/Halflm_tables_all-space"
usage = "usage: %prog [options] hash[or]hashfile"
parser = OptionParser(usage=usage, version="%prog 0.2")
parser.add_option("-a", "--alpha", action="store", type="string", dest="rt_alpha", help="path to halflmchall_alpha-numeric rainbow tables", default=path_rt_alpha)
parser.add_option("-b", "--all", action="store", type="string", dest="rt_allspace", help="path to halflmchall_all-space rainbow tables", default=path_rt_allspace)
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="print status messages", default=False)
parser.add_option("-o", "--output", action="store", type="string", dest="output", help="optional output file containing passwords", default=False)
parser.add_option("-t", "--timeout", action="store", type="int", dest="timeout", help="optional timeout for bruteforcing the 7+ characters of a particular hash. If the timeout if reached, <timeout> will be outputted as the password", default=0)
group = OptionGroup(parser, "Suplementary executable locations", "If your file locations differ from the default use these options")
group.add_option("-p", "--perlpath", action="store", type="string", dest="perl", help="path to perl [default: %default]", default=path_perl)
group.add_option("-j", "--johnnetntlm", action="store", type="string", dest="johnnetntlm", help="path to John the Ripper's netntlm.pl from Jumbo Pack [default: %default]", default=path_johnnetntlm)
group.add_option("-r", "--rcracki", action="store", type="string", dest="rcracki", help="path to rcracki_mt [default: %default]", default=path_rcracki)
parser.add_option_group(group)
(options, args) = parser.parse_args()
# check that files/tools exist
if not os.path.exists(options.johnnetntlm):
parser.error ("John's netntlm.pl does not exist")
if not os.path.exists(options.rcracki):
parser.error ("rcracki does not exist")
if not os.path.exists(options.perl):
parser.error ("Perl does not exist")
# put the rainbbow tables into a list
rtables = []
if options.rt_alpha:
rtables.append(options.rt_alpha)
if options.rt_allspace:
rtables.append(options.rt_allspace)
if len(rtables) == 0:
parser.error("No rainbow tables specified")
# ensure an input file is specified
if len(args) == 0:
parser.error("No hash or hash file specified")
# TODO: FIX THIS THE RIGHT WAY
#print "Make sure you copy the charset.txt file from the directory rcracki_mt runs in"
# open hashes file and remove duplidates
hashes = set([])
if os.path.exists(args[0]):
fin = open(args[0],"r")
for hashrow in fin:
hashes.add(hashrow)
fin.close()
elif args[0].count(":") == 4 or args[0].count(":") == 5:
hashes.add(args[0])
else:
"Bad hash or hash file. Try again."
parser.error("Bad hash or hash file. Try harder.")
OptionParser.print_usage()
# crack away baby
for line in hashes:
try:
with time_limit(options.timeout):
if options.verbose: print "Processing " + line.replace("\n","")
if line.count(":") == 5:
# parse the file
user = line.split(":")[0]
domain = line.split(":")[2]
lmhash = line.split(":")[3]
lmhash_first = lmhash[0:16]
elif line.count(":") == 4:
user = line.split(":")[0]
domain = line.split(":")[1]
lmhash = line.split(":")[3]
nthash = line.split(":")[4].replace("\n","")
lmchal = line.split(":")[2]
lmhash_first = lmhash[0:16]
line = user+"::"+domain+":"+lmhash+":"+nthash+":"+lmchal+"\n"
if options.verbose: print "Looks like Cain format. Converting to John "+line.replace("\n","")
else:
print "Unknown hash format. Exiting..."
sys.exit(0)
#check for and skip computer accounts
if "$" in user:
print domain + "/" + user + " looks like a computer account. Skipping."
continue
#check output file to see if hash has already been cracked
if options.output and os.path.exists(options.output):
outfile = open(options.output,'r')
for lineoutput in outfile:
if user in lineoutput:
if options.verbose: print user + " has already been cracked. Skipping\n"
raise AlreadyCracked
if options.verbose: print str(datetime.now()) + ": Processing " + user + " with tables " + rtables[0]
process = subprocess.Popen(options.rcracki + " -h " + lmhash_first + " " + rtables[0], shell=True, stdout=subprocess.PIPE)
lastline = process.communicate()[0].splitlines()[-1]
seed = lastline.split()[1]
if options.verbose: print str(datetime.now()) + ": Processing " + user + " seed: " + seed
if seed == "<notfound>" and len(rtables) == 2:
if options.verbose: print str(datetime.now()) + ": Processing " + user + " with tables " + rtables[0]
process = subprocess.Popen(options.rcracki + " -h " + lmhash_first + " " + rtables[1], shell=True, stdout=subprocess.PIPE)
lastline = process.communicate()[0].splitlines()[-1]
seed = lastline.split()[1]
if options.verbose: print str(datetime.now()) + ": Processing " + user + " seed: " + seed
if seed != "<notfound>":
singlehashfile = domain + "." + user + ".hash"
fout = open(singlehashfile, "w")
fout.write(line)
fout.close()
if options.verbose: print str(datetime.now()) + ": Bruteforcing the remainder of " + user + "'s password " + seed
process = subprocess.Popen(options.perl + " " + options.johnnetntlm + " --seed \'" + seed + "\' --file \'" + singlehashfile + "\'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#if options.verbose: print str(datetime.now()) + "Running: " + options.perl + " " + options.johnnetntlm + " --seed \'" + seed + "\' --file " + singlehashfile)
out = process.communicate()
#print "out=%s" % (out,)
#pull case insensitive password out of output and feed it as the seed of the same command
for line in out[0].splitlines():
if line.find("(" + user +")") > 0:
seed = line.split()[0]
process = subprocess.Popen(options.perl + " " + options.johnnetntlm + " --seed \'" + seed + "\' --file \'" + singlehashfile + "\'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out = process.communicate()
#print "out=%s" % (out,)
# check the output. the first part looks for a new crack
passwd = None
for line in out[0].splitlines():
if line.find("(" + user +")") > 0:
passwd = line.split()[0]
#print "passwd=" + passwd
# if the password was previously found use this to extract it from the output
if not passwd:
for line in out[0].splitlines():
if line.find(user) > 0:
passwd = line.split(":")[1]
#pass =print domain + " " + user + " " + line.split()[0]
#print "passwd=" + passwd
if not passwd:
print "Running netntlm.pl failed. John output:"
print "out=%s" % (out,)
sys.exit(0)
elif seed == "<notfound>":
print "Cannot find seed in rainbow tables for" + domain + "/" + user
passwd = "<notfound>"
except TimeoutException, msg:
passwd="<timeout>"
except AlreadyCracked, msg:
continue
print domain + "/" + user + " " + passwd
if options.output:
outputfile = open(options.output,'a')
outputfile.write(domain + "/" + user + " " + passwd + "\n")
outputfile.close()
#print passwd
try:
os.remove(singlehashfile)
except:
pass