Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
derv82
GitHub Repository: derv82/wifite2
Path: blob/master/wifite/util/crack.py
412 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
from ..config import Configuration
5
from ..model.handshake import Handshake
6
from ..model.wpa_result import CrackResultWPA
7
from ..model.pmkid_result import CrackResultPMKID
8
from ..util.process import Process
9
from ..util.color import Color
10
from ..util.input import raw_input
11
from ..tools.aircrack import Aircrack
12
from ..tools.cowpatty import Cowpatty
13
from ..tools.hashcat import Hashcat, HcxPcapTool
14
from ..tools.john import John
15
16
from json import loads
17
18
import os
19
20
21
# TODO: Bring back the 'print' option, for easy copy/pasting. Just one-liners people can paste into terminal.
22
23
# TODO: --no-crack option while attacking targets (implies user will run --crack later)
24
25
class CrackHelper:
26
'''Manages handshake retrieval, selection, and running the cracking commands.'''
27
28
TYPES = {
29
'4-WAY': '4-Way Handshake',
30
'PMKID': 'PMKID Hash'
31
}
32
33
@classmethod
34
def run(cls):
35
Configuration.initialize(False)
36
37
# Get wordlist
38
if not Configuration.wordlist:
39
Color.p('\n{+} Enter wordlist file to use for cracking: {G}')
40
Configuration.wordlist = raw_input()
41
if not os.path.exists(Configuration.wordlist):
42
Color.pl('{!} {R}Wordlist {O}%s{R} not found. Exiting.' % Configuration.wordlist)
43
return
44
Color.pl('')
45
46
# Get handshakes
47
handshakes = cls.get_handshakes()
48
if len(handshakes) == 0:
49
Color.pl('{!} {O}No handshakes found{W}')
50
return
51
52
hs_to_crack = cls.get_user_selection(handshakes)
53
all_pmkid = all([hs['type'] == 'PMKID' for hs in hs_to_crack])
54
55
# Tools for cracking & their dependencies.
56
available_tools = {
57
'aircrack': [Aircrack],
58
'hashcat': [Hashcat, HcxPcapTool],
59
'john': [John, HcxPcapTool],
60
'cowpatty': [Cowpatty]
61
}
62
# Identify missing tools
63
missing_tools = []
64
for tool, dependencies in available_tools.items():
65
missing = [
66
dep for dep in dependencies
67
if not Process.exists(dep.dependency_name)
68
]
69
if len(missing) > 0:
70
available_tools.pop(tool)
71
missing_tools.append( (tool, missing) )
72
73
if len(missing_tools) > 0:
74
Color.pl('\n{!} {O}Unavailable tools (install to enable):{W}')
75
for tool, deps in missing_tools:
76
dep_list = ', '.join([dep.dependency_name for dep in deps])
77
Color.pl(' {R}* {R}%s {W}({O}%s{W})' % (tool, dep_list))
78
79
if all_pmkid:
80
Color.pl('{!} {O}Note: PMKID hashes can only be cracked using {C}hashcat{W}')
81
tool_name = 'hashcat'
82
else:
83
Color.p('\n{+} Enter the {C}cracking tool{W} to use ({C}%s{W}): {G}' % (
84
'{W}, {C}'.join(available_tools.keys())))
85
tool_name = raw_input()
86
if tool_name not in available_tools:
87
Color.pl('{!} {R}"%s"{O} tool not found, defaulting to {C}aircrack{W}' % tool_name)
88
tool_name = 'aircrack'
89
90
try:
91
for hs in hs_to_crack:
92
if tool_name != 'hashcat' and hs['type'] == 'PMKID':
93
if 'hashcat' in missing_tools:
94
Color.pl('{!} {O}Hashcat is missing, therefore we cannot crack PMKID hash{W}')
95
cls.crack(hs, tool_name)
96
except KeyboardInterrupt:
97
Color.pl('\n{!} {O}Interrupted{W}')
98
99
@classmethod
100
def is_cracked(cls, file):
101
if not os.path.exists(Configuration.cracked_file):
102
return False
103
with open(Configuration.cracked_file) as f:
104
json = loads(f.read())
105
if json is None:
106
return False
107
for result in json:
108
for k in result.keys():
109
v = result[k]
110
if 'file' in k and os.path.basename(v) == file:
111
return True
112
return False
113
114
@classmethod
115
def get_handshakes(cls):
116
handshakes = []
117
118
skipped_pmkid_files = skipped_cracked_files = 0
119
120
hs_dir = Configuration.wpa_handshake_dir
121
if not os.path.exists(hs_dir) or not os.path.isdir(hs_dir):
122
Color.pl('\n{!} {O}directory not found: {R}%s{W}' % hs_dir)
123
return []
124
125
Color.pl('\n{+} Listing captured handshakes from {C}%s{W}:\n' % os.path.abspath(hs_dir))
126
for hs_file in os.listdir(hs_dir):
127
if hs_file.count('_') != 3:
128
continue
129
130
if cls.is_cracked(hs_file):
131
skipped_cracked_files += 1
132
continue
133
134
if hs_file.endswith('.cap'):
135
# WPA Handshake
136
hs_type = '4-WAY'
137
elif hs_file.endswith('.16800'):
138
# PMKID hash
139
if not Process.exists('hashcat'):
140
skipped_pmkid_files += 1
141
continue
142
hs_type = 'PMKID'
143
else:
144
continue
145
146
name, essid, bssid, date = hs_file.split('_')
147
date = date.rsplit('.', 1)[0]
148
days,hours = date.split('T')
149
hours = hours.replace('-', ':')
150
date = '%s %s' % (days, hours)
151
152
handshake = {
153
'filename': os.path.join(hs_dir, hs_file),
154
'bssid': bssid.replace('-', ':'),
155
'essid': essid,
156
'date': date,
157
'type': hs_type
158
}
159
160
if hs_file.endswith('.cap'):
161
# WPA Handshake
162
handshake['type'] = '4-WAY'
163
elif hs_file.endswith('.16800'):
164
# PMKID hash
165
handshake['type'] = 'PMKID'
166
else:
167
continue
168
169
handshakes.append(handshake)
170
171
if skipped_pmkid_files > 0:
172
Color.pl('{!} {O}Skipping %d {R}*.16800{O} files because {R}hashcat{O} is missing.{W}\n' % skipped_pmkid_files)
173
if skipped_cracked_files > 0:
174
Color.pl('{!} {O}Skipping %d already cracked files.{W}\n' % skipped_cracked_files)
175
176
# Sort by Date (Descending)
177
return sorted(handshakes, key=lambda x: x.get('date'), reverse=True)
178
179
180
@classmethod
181
def print_handshakes(cls, handshakes):
182
# Header
183
max_essid_len = max([len(hs['essid']) for hs in handshakes] + [len('ESSID (truncated)')])
184
Color.p('{W}{D} NUM')
185
Color.p(' ' + 'ESSID (truncated)'.ljust(max_essid_len))
186
Color.p(' ' + 'BSSID'.ljust(17))
187
Color.p(' ' + 'TYPE'.ljust(5))
188
Color.p(' ' + 'DATE CAPTURED\n')
189
Color.p(' ---')
190
Color.p(' ' + ('-' * max_essid_len))
191
Color.p(' ' + ('-' * 17))
192
Color.p(' ' + ('-' * 5))
193
Color.p(' ' + ('-' * 19) + '{W}\n')
194
# Handshakes
195
for index, handshake in enumerate(handshakes, start=1):
196
Color.p(' {G}%s{W}' % str(index).rjust(3))
197
Color.p(' {C}%s{W}' % handshake['essid'].ljust(max_essid_len))
198
Color.p(' {O}%s{W}' % handshake['bssid'].ljust(17))
199
Color.p(' {C}%s{W}' % handshake['type'].ljust(5))
200
Color.p(' {W}%s{W}\n' % handshake['date'])
201
202
203
@classmethod
204
def get_user_selection(cls, handshakes):
205
cls.print_handshakes(handshakes)
206
207
Color.p('{+} Select handshake(s) to crack ({G}%d{W}-{G}%d{W}, select multiple with {C},{W} or {C}-{W} or {C}all{W}): {G}' % (1, len(handshakes)))
208
choices = raw_input()
209
210
selection = []
211
for choice in choices.split(','):
212
if '-' in choice:
213
first, last = [int(x) for x in choice.split('-')]
214
for index in range(first, last + 1):
215
selection.append(handshakes[index-1])
216
elif choice.strip().lower() == 'all':
217
selection = handshakes[:]
218
break
219
elif [c.isdigit() for c in choice]:
220
index = int(choice)
221
selection.append(handshakes[index-1])
222
223
return selection
224
225
226
@classmethod
227
def crack(cls, hs, tool):
228
Color.pl('\n{+} Cracking {G}%s {C}%s{W} ({C}%s{W})' % (
229
cls.TYPES[hs['type']], hs['essid'], hs['bssid']))
230
231
if hs['type'] == 'PMKID':
232
crack_result = cls.crack_pmkid(hs, tool)
233
elif hs['type'] == '4-WAY':
234
crack_result = cls.crack_4way(hs, tool)
235
else:
236
raise ValueError('Cannot crack handshake: Type is not PMKID or 4-WAY. Handshake=%s' % hs)
237
238
if crack_result is None:
239
# Failed to crack
240
Color.pl('{!} {R}Failed to crack {O}%s{R} ({O}%s{R}): Passphrase not in dictionary' % (
241
hs['essid'], hs['bssid']))
242
else:
243
# Cracked, replace existing entry (if any), or add to
244
Color.pl('{+} {G}Cracked{W} {C}%s{W} ({C}%s{W}). Key: "{G}%s{W}"' % (
245
hs['essid'], hs['bssid'], crack_result.key))
246
crack_result.save()
247
248
249
@classmethod
250
def crack_4way(cls, hs, tool):
251
252
handshake = Handshake(hs['filename'],
253
bssid=hs['bssid'],
254
essid=hs['essid'])
255
try:
256
handshake.divine_bssid_and_essid()
257
except ValueError as e:
258
Color.pl('{!} {R}Error: {O}%s{W}' % e)
259
return None
260
261
if tool == 'aircrack':
262
key = Aircrack.crack_handshake(handshake, show_command=True)
263
elif tool == 'hashcat':
264
key = Hashcat.crack_handshake(handshake, show_command=True)
265
elif tool == 'john':
266
key = John.crack_handshake(handshake, show_command=True)
267
elif tool == 'cowpatty':
268
key = Cowpatty.crack_handshake(handshake, show_command=True)
269
270
if key is not None:
271
return CrackResultWPA(hs['bssid'], hs['essid'], hs['filename'], key)
272
else:
273
return None
274
275
276
@classmethod
277
def crack_pmkid(cls, hs, tool):
278
if tool != 'hashcat':
279
Color.pl('{!} {O}Note: PMKID hashes can only be cracked using {C}hashcat{W}')
280
281
key = Hashcat.crack_pmkid(hs['filename'], verbose=True)
282
283
if key is not None:
284
return CrackResultPMKID(hs['bssid'], hs['essid'], hs['filename'], key)
285
else:
286
return None
287
288
289
if __name__ == '__main__':
290
CrackHelper.run()
291
292
293