Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
derv82
GitHub Repository: derv82/wifite2
Path: blob/master/wifite/tools/tshark.py
412 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
from .dependency import Dependency
5
from ..model.target import WPSState
6
from ..util.process import Process
7
import re
8
9
class Tshark(Dependency):
10
''' Wrapper for Tshark program. '''
11
dependency_required = False
12
dependency_name = 'tshark'
13
dependency_url = 'apt-get install wireshark'
14
15
def __init__(self):
16
pass
17
18
19
@staticmethod
20
def _extract_src_dst_index_total(line):
21
# Extract BSSIDs, handshake # (1-4) and handshake 'total' (4)
22
mac_regex = ('[a-zA-Z0-9]{2}:' * 6)[:-1]
23
match = re.search('(%s)\s*.*\s*(%s).*Message.*(\d).*of.*(\d)' % (mac_regex, mac_regex), line)
24
if match is None:
25
# Line doesn't contain src, dst, Message numbers
26
return None, None, None, None
27
(src, dst, index, total) = match.groups()
28
return src, dst, index, total
29
30
31
@staticmethod
32
def _build_target_client_handshake_map(output, bssid=None):
33
# Map of target_ssid,client_ssid -> handshake #s
34
# E.g. 12:34:56,21:43:65 -> 3
35
target_client_msg_nums = {}
36
37
for line in output.split('\n'):
38
src, dst, index, total = Tshark._extract_src_dst_index_total(line)
39
40
if src is None: continue # Skip
41
42
index = int(index)
43
total = int(total)
44
45
if total != 4: continue # Handshake X of 5? X of 3? Skip it.
46
47
# Identify the client and target MAC addresses
48
if index % 2 == 1:
49
# First and Third messages
50
target = src
51
client = dst
52
else:
53
# Second and Fourth messages
54
client = src
55
target = dst
56
57
if bssid is not None and bssid.lower() != target.lower():
58
# We know the BSSID and this msg was not for the target
59
continue
60
61
target_client_key = '%s,%s' % (target, client)
62
63
# Ensure all 4 messages are:
64
# Between the same client and target (not different clients connecting).
65
# In numeric & chronological order (Message 1, then 2, then 3, then 4)
66
if index == 1:
67
target_client_msg_nums[target_client_key] = 1 # First message
68
69
elif target_client_key not in target_client_msg_nums:
70
continue # Not first message. We haven't gotten the first message yet. Skip.
71
72
elif index - 1 != target_client_msg_nums[target_client_key]:
73
continue # Message is not in sequence. Skip
74
75
else:
76
# Happy case: Message is > 1 and is received in-order
77
target_client_msg_nums[target_client_key] = index
78
79
return target_client_msg_nums
80
81
82
@staticmethod
83
def bssids_with_handshakes(capfile, bssid=None):
84
if not Tshark.exists():
85
return []
86
87
# Returns list of BSSIDs for which we have valid handshakes in the capfile.
88
command = [
89
'tshark',
90
'-r', capfile,
91
'-n', # Don't resolve addresses
92
'-Y', 'eapol' # Filter for only handshakes
93
]
94
tshark = Process(command, devnull=False)
95
96
target_client_msg_nums = Tshark._build_target_client_handshake_map(tshark.stdout(), bssid=bssid)
97
98
bssids = set()
99
# Check if we have all 4 messages for the handshake between the same MACs
100
for (target_client, num) in target_client_msg_nums.items():
101
if num == 4:
102
# We got a handshake!
103
this_bssid = target_client.split(',')[0]
104
bssids.add(this_bssid)
105
106
return list(bssids)
107
108
109
@staticmethod
110
def bssid_essid_pairs(capfile, bssid):
111
# Finds all BSSIDs (with corresponding ESSIDs) from cap file.
112
# Returns list of tuples(BSSID, ESSID)
113
114
if not Tshark.exists():
115
return []
116
117
ssid_pairs = set()
118
119
command = [
120
'tshark',
121
'-r', capfile, # Path to cap file
122
'-n', # Don't resolve addresses
123
# Extract beacon frames
124
'-Y', '"wlan.fc.type_subtype == 0x08 || wlan.fc.type_subtype == 0x05"',
125
]
126
tshark = Process(command, devnull=False)
127
128
for line in tshark.stdout().split('\n'):
129
# Extract src, dst, and essid
130
mac_regex = ('[a-zA-Z0-9]{2}:' * 6)[:-1]
131
match = re.search('(%s) [^ ]* (%s).*.*SSID=(.*)$' % (mac_regex, mac_regex), line)
132
if match is None:
133
continue # Line doesn't contain src, dst, ssid
134
135
(src, dst, essid) = match.groups()
136
137
if dst.lower() == 'ff:ff:ff:ff:ff:ff':
138
continue # Skip broadcast packets
139
140
if bssid is not None:
141
# We know the BSSID, only return the ESSID for this BSSID.
142
if bssid.lower() == src.lower():
143
ssid_pairs.add((src, essid)) # This is our BSSID, add it
144
else:
145
ssid_pairs.add((src, essid)) # We do not know BSSID, add it.
146
147
return list(ssid_pairs)
148
149
150
@staticmethod
151
def check_for_wps_and_update_targets(capfile, targets):
152
'''
153
Given a cap file and list of targets, use TShark to
154
find which BSSIDs in the cap file use WPS.
155
Then update the 'wps' flag for those BSSIDs in the targets.
156
157
Args:
158
capfile - .cap file from airodump containing packets
159
targets - list of Targets from scan, to be updated
160
'''
161
from ..config import Configuration
162
163
if not Tshark.exists():
164
raise ValueError('Cannot detect WPS networks: Tshark does not exist')
165
166
command = [
167
'tshark',
168
'-r', capfile, # Path to cap file
169
'-n', # Don't resolve addresses
170
# Filter WPS broadcast packets
171
'-Y', 'wps.wifi_protected_setup_state && wlan.da == ff:ff:ff:ff:ff:ff',
172
'-T', 'fields', # Only output certain fields
173
'-e', 'wlan.ta', # BSSID
174
'-e', 'wps.ap_setup_locked', # Locked status
175
'-E', 'separator=,' # CSV
176
]
177
p = Process(command)
178
179
try:
180
p.wait()
181
lines = p.stdout()
182
except:
183
# Failure is acceptable
184
return
185
186
wps_bssids = set()
187
locked_bssids = set()
188
for line in lines.split('\n'):
189
if ',' not in line:
190
continue
191
bssid, locked = line.split(',')
192
if '1' not in locked:
193
wps_bssids.add(bssid.upper())
194
else:
195
locked_bssids.add(bssid.upper())
196
197
for t in targets:
198
target_bssid = t.bssid.upper()
199
if target_bssid in wps_bssids:
200
t.wps = WPSState.UNLOCKED
201
elif target_bssid in locked_bssids:
202
t.wps = WPSState.LOCKED
203
else:
204
t.wps = WPSState.NONE
205
206
207
if __name__ == '__main__':
208
test_file = './tests/files/contains_wps_network.cap'
209
210
target_bssid = 'A4:2B:8C:16:6B:3A'
211
from ..model.target import Target
212
fields = [
213
'A4:2B:8C:16:6B:3A', # BSSID
214
'2015-05-27 19:28:44', '2015-05-27 19:28:46', # Dates
215
'11', # Channel
216
'54', # throughput
217
'WPA2', 'CCMP TKIP', 'PSK', # AUTH
218
'-58', '2', '0', '0.0.0.0', '9', # ???
219
'Test Router Please Ignore', # SSID
220
]
221
t = Target(fields)
222
targets = [t]
223
224
# Should update 'wps' field of a target
225
Tshark.check_for_wps_and_update_targets(test_file, targets)
226
227
print('Target(BSSID={}).wps = {} (Expected: 1)'.format(
228
targets[0].bssid, targets[0].wps))
229
assert targets[0].wps == WPSState.UNLOCKED
230
231
print(Tshark.bssids_with_handshakes(test_file, bssid=target_bssid))
232
233