Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
derv82
GitHub Repository: derv82/wifite2
Path: blob/master/wifite/tools/airmon.py
412 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
from .dependency import Dependency
5
from .ifconfig import Ifconfig
6
from .iwconfig import Iwconfig
7
from ..util.process import Process
8
from ..util.color import Color
9
from ..util.input import raw_input
10
from ..config import Configuration
11
12
import re
13
import os
14
import signal
15
16
class AirmonIface(object):
17
def __init__(self, phy, interface, driver, chipset):
18
self.phy = phy
19
self.interface = interface
20
self.driver = driver
21
self.chipset = chipset
22
23
# Max length of fields.
24
# Used for printing a table of interfaces.
25
INTERFACE_LEN = 12
26
PHY_LEN = 6
27
DRIVER_LEN = 20
28
CHIPSET_LEN = 30
29
30
def __str__(self):
31
''' Colored string representation of interface '''
32
s = ''
33
s += Color.s('{G}%s' % self.interface.ljust(self.INTERFACE_LEN))
34
s += Color.s('{W}%s' % self.phy.ljust(self.PHY_LEN))
35
s += Color.s('{C}%s' % self.driver.ljust(self.DRIVER_LEN))
36
s += Color.s('{W}%s' % self.chipset.ljust(self.CHIPSET_LEN))
37
return s
38
39
@staticmethod
40
def menu_header():
41
''' Colored header row for interfaces '''
42
s = ' ' # Space for index #
43
s += 'Interface'.ljust(AirmonIface.INTERFACE_LEN)
44
s += 'PHY'.ljust(AirmonIface.PHY_LEN)
45
s += 'Driver'.ljust(AirmonIface.DRIVER_LEN)
46
s += 'Chipset'.ljust(AirmonIface.CHIPSET_LEN)
47
s += '\n'
48
s += '-' * (AirmonIface.INTERFACE_LEN + AirmonIface.PHY_LEN + AirmonIface.DRIVER_LEN + AirmonIface.CHIPSET_LEN + 3)
49
return s
50
51
52
class Airmon(Dependency):
53
''' Wrapper around the 'airmon-ng' program '''
54
dependency_required = True
55
dependency_name = 'airmon-ng'
56
dependency_url = 'https://www.aircrack-ng.org/install.html'
57
58
base_interface = None
59
killed_network_manager = False
60
61
# Drivers that need to be manually put into monitor mode
62
BAD_DRIVERS = ['rtl8821au']
63
#see if_arp.h
64
ARPHRD_ETHER = 1 #managed
65
ARPHRD_IEEE80211_RADIOTAP = 803 #monitor
66
67
def __init__(self):
68
self.refresh()
69
70
def refresh(self):
71
''' Get airmon-recognized interfaces '''
72
self.interfaces = Airmon.get_interfaces()
73
74
def print_menu(self):
75
''' Prints menu '''
76
print(AirmonIface.menu_header())
77
for idx, iface in enumerate(self.interfaces, start=1):
78
Color.pl(' {G}%d{W}. %s' % (idx, iface))
79
80
def get(self, index):
81
''' Gets interface at index (starts at 1) '''
82
if type(index) is str:
83
index = int(index)
84
return self.interfaces[index - 1]
85
86
87
@staticmethod
88
def get_interfaces():
89
'''Returns List of AirmonIface objects known by airmon-ng'''
90
interfaces = []
91
p = Process('airmon-ng')
92
for line in p.stdout().split('\n'):
93
# [PHY ]IFACE DRIVER CHIPSET
94
airmon_re = re.compile(r'^(?:([^\t]*)\t+)?([^\t]*)\t+([^\t]*)\t+([^\t]*)$')
95
matches = airmon_re.match(line)
96
if not matches:
97
continue
98
99
phy, interface, driver, chipset = matches.groups()
100
if phy == 'PHY' or phy == 'Interface':
101
continue # Header
102
103
if len(interface.strip()) == 0:
104
continue
105
106
interfaces.append(AirmonIface(phy, interface, driver, chipset))
107
108
return interfaces
109
110
@staticmethod
111
def start_bad_driver(iface):
112
'''
113
Manually put interface into monitor mode (no airmon-ng or vif).
114
Fix for bad drivers like the rtl8812AU.
115
'''
116
Ifconfig.down(iface)
117
Iwconfig.mode(iface, 'monitor')
118
Ifconfig.up(iface)
119
120
# /sys/class/net/wlan0/type
121
iface_type_path = os.path.join('/sys/class/net', iface, 'type')
122
if os.path.exists(iface_type_path):
123
with open(iface_type_path, 'r') as f:
124
if (int(f.read()) == Airmon.ARPHRD_IEEE80211_RADIOTAP):
125
return iface
126
127
return None
128
129
@staticmethod
130
def stop_bad_driver(iface):
131
'''
132
Manually put interface into managed mode (no airmon-ng or vif).
133
Fix for bad drivers like the rtl8812AU.
134
'''
135
Ifconfig.down(iface)
136
Iwconfig.mode(iface, 'managed')
137
Ifconfig.up(iface)
138
139
# /sys/class/net/wlan0/type
140
iface_type_path = os.path.join('/sys/class/net', iface, 'type')
141
if os.path.exists(iface_type_path):
142
with open(iface_type_path, 'r') as f:
143
if (int(f.read()) == Airmon.ARPHRD_ETHER):
144
return iface
145
146
return None
147
148
@staticmethod
149
def start(iface):
150
'''
151
Starts an interface (iface) in monitor mode
152
Args:
153
iface - The interface to start in monitor mode
154
Either an instance of AirmonIface object,
155
or the name of the interface (string).
156
Returns:
157
Name of the interface put into monitor mode.
158
Throws:
159
Exception - If an interface can't be put into monitor mode
160
'''
161
# Get interface name from input
162
if type(iface) == AirmonIface:
163
iface_name = iface.interface
164
driver = iface.driver
165
else:
166
iface_name = iface
167
driver = None
168
169
# Remember this as the 'base' interface.
170
Airmon.base_interface = iface_name
171
172
Color.p('{+} enabling {G}monitor mode{W} on {C}%s{W}... ' % iface_name)
173
174
airmon_output = Process(['airmon-ng', 'start', iface_name]).stdout()
175
176
enabled_iface = Airmon._parse_airmon_start(airmon_output)
177
178
if enabled_iface is None and driver in Airmon.BAD_DRIVERS:
179
Color.p('{O}"bad driver" detected{W} ')
180
enabled_iface = Airmon.start_bad_driver(iface_name)
181
182
if enabled_iface is None:
183
Color.pl('{R}failed{W}')
184
185
monitor_interfaces = Iwconfig.get_interfaces(mode='Monitor')
186
187
# Assert that there is an interface in monitor mode
188
if len(monitor_interfaces) == 0:
189
Color.pl('{R}failed{W}')
190
raise Exception('Cannot find any interfaces in Mode:Monitor')
191
192
# Assert that the interface enabled by airmon-ng is in monitor mode
193
if enabled_iface not in monitor_interfaces:
194
Color.pl('{R}failed{W}')
195
raise Exception('Cannot find %s with Mode:Monitor' % enabled_iface)
196
197
# No errors found; the device 'enabled_iface' was put into Mode:Monitor.
198
Color.pl('{G}enabled {C}%s{W}' % enabled_iface)
199
200
return enabled_iface
201
202
@staticmethod
203
def _parse_airmon_start(airmon_output):
204
'''Find the interface put into monitor mode (if any)'''
205
206
# airmon-ng output: (mac80211 monitor mode vif enabled for [phy10]wlan0 on [phy10]wlan0mon)
207
enabled_re = re.compile(r'.*\(mac80211 monitor mode (?:vif )?enabled (?:for [^ ]+ )?on (?:\[\w+\])?(\w+)\)?.*')
208
209
for line in airmon_output.split('\n'):
210
matches = enabled_re.match(line)
211
if matches:
212
return matches.group(1)
213
214
return None
215
216
217
@staticmethod
218
def stop(iface):
219
Color.p('{!} {R}disabling {O}monitor mode{O} on {R}%s{O}... ' % iface)
220
221
airmon_output = Process(['airmon-ng', 'stop', iface]).stdout()
222
223
(disabled_iface, enabled_iface) = Airmon._parse_airmon_stop(airmon_output)
224
225
if not disabled_iface and iface in Airmon.BAD_DRIVERS:
226
Color.p('{O}"bad driver" detected{W} ')
227
disabled_iface = Airmon.stop_bad_driver(iface)
228
229
if disabled_iface:
230
Color.pl('{G}disabled %s{W}' % disabled_iface)
231
else:
232
Color.pl('{O}could not disable on {R}%s{W}' % iface)
233
234
return (disabled_iface, enabled_iface)
235
236
237
@staticmethod
238
def _parse_airmon_stop(airmon_output):
239
'''Find the interface taken out of into monitor mode (if any)'''
240
241
# airmon-ng 1.2rc2 output: (mac80211 monitor mode vif enabled for [phy10]wlan0 on [phy10]wlan0mon)
242
disabled_re = re.compile(r'\s*\(mac80211 monitor mode (?:vif )?disabled for (?:\[\w+\])?(\w+)\)\s*')
243
244
# airmon-ng 1.2rc1 output: wlan0mon (removed)
245
removed_re = re.compile(r'([a-zA-Z0-9]+).*\(removed\)')
246
247
# Enabled interface: (mac80211 station mode vif enabled on [phy4]wlan0)
248
enabled_re = re.compile(r'\s*\(mac80211 station mode (?:vif )?enabled on (?:\[\w+\])?(\w+)\)\s*')
249
250
disabled_iface = None
251
enabled_iface = None
252
for line in airmon_output.split('\n'):
253
matches = disabled_re.match(line)
254
if matches:
255
disabled_iface = matches.group(1)
256
257
matches = removed_re.match(line)
258
if matches:
259
disabled_iface = matches.group(1)
260
261
matches = enabled_re.match(line)
262
if matches:
263
enabled_iface = matches.group(1)
264
265
return (disabled_iface, enabled_iface)
266
267
268
@staticmethod
269
def ask():
270
'''
271
Asks user to define which wireless interface to use.
272
Does not ask if:
273
1. There is already an interface in monitor mode, or
274
2. There is only one wireless interface (automatically selected).
275
Puts selected device into Monitor Mode.
276
'''
277
278
Airmon.terminate_conflicting_processes()
279
280
Color.p('\n{+} Looking for {C}wireless interfaces{W}...')
281
monitor_interfaces = Iwconfig.get_interfaces(mode='Monitor')
282
if len(monitor_interfaces) == 1:
283
# Assume we're using the device already in montior mode
284
iface = monitor_interfaces[0]
285
Color.clear_entire_line()
286
Color.pl('{+} Using {G}%s{W} already in monitor mode' % iface);
287
Airmon.base_interface = None
288
return iface
289
290
Color.clear_entire_line()
291
Color.p('{+} Checking {C}airmon-ng{W}...')
292
a = Airmon()
293
count = len(a.interfaces)
294
if count == 0:
295
# No interfaces found
296
Color.pl('\n{!} {O}airmon-ng did not find {R}any{O} wireless interfaces')
297
Color.pl('{!} {O}Make sure your wireless device is connected')
298
Color.pl('{!} {O}See {C}http://www.aircrack-ng.org/doku.php?id=airmon-ng{O} for more info{W}')
299
raise Exception('airmon-ng did not find any wireless interfaces')
300
301
Color.clear_entire_line()
302
a.print_menu()
303
304
Color.pl('')
305
306
if count == 1:
307
# Only one interface, assume this is the one to use
308
choice = 1
309
else:
310
# Multiple interfaces found
311
question = Color.s('{+} Select wireless interface ({G}1-%d{W}): ' % (count))
312
choice = raw_input(question)
313
314
iface = a.get(choice)
315
316
if a.get(choice).interface in monitor_interfaces:
317
Color.pl('{+} {G}%s{W} is already in monitor mode' % iface.interface)
318
else:
319
iface.interface = Airmon.start(iface)
320
return iface.interface
321
322
323
@staticmethod
324
def terminate_conflicting_processes():
325
''' Deletes conflicting processes reported by airmon-ng '''
326
327
airmon_output = Process(['airmon-ng', 'check']).stdout()
328
329
# Conflicting process IDs and names
330
pid_pnames = []
331
332
# 2272 dhclient
333
# 2293 NetworkManager
334
pid_pname_re = re.compile(r'^\s*(\d+)\s*([a-zA-Z0-9_\-]+)\s*$')
335
for line in airmon_output.split('\n'):
336
match = pid_pname_re.match(line)
337
if match:
338
pid = match.group(1)
339
pname = match.group(2)
340
pid_pnames.append( (pid, pname) )
341
342
if len(pid_pnames) == 0:
343
return
344
345
if not Configuration.kill_conflicting_processes:
346
# Don't kill processes, warn user
347
names_and_pids = ', '.join([
348
'{R}%s{O} (PID {R}%s{O})' % (pname, pid)
349
for pid, pname in pid_pnames
350
])
351
Color.pl('{!} {O}Conflicting processes: %s' % names_and_pids)
352
Color.pl('{!} {O}If you have problems: {R}kill -9 PID{O} or re-run wifite with {R}--kill{O}){W}')
353
return
354
355
Color.pl('{!} {O}Killing {R}%d {O}conflicting processes' % len(pid_pnames))
356
for pid, pname in pid_pnames:
357
if pname == 'NetworkManager' and Process.exists('service'):
358
Color.pl('{!} {O}stopping network-manager ({R}service network-manager stop{O})')
359
# Can't just pkill network manager; it's a service
360
Process(['service', 'network-manager', 'stop']).wait()
361
Airmon.killed_network_manager = True
362
elif pname == 'avahi-daemon' and Process.exists('service'):
363
Color.pl('{!} {O}stopping avahi-daemon ({R}service avahi-daemon stop{O})')
364
# Can't just pkill avahi-daemon; it's a service
365
Process(['service', 'avahi-daemon', 'stop']).wait()
366
else:
367
Color.pl('{!} {R}Terminating {O}conflicting process {R}%s{O} (PID {R}%s{O})' % (pname, pid))
368
try:
369
os.kill(int(pid), signal.SIGTERM)
370
except:
371
pass
372
373
374
@staticmethod
375
def put_interface_up(iface):
376
Color.p('{!} {O}putting interface {R}%s up{O}...' % (iface))
377
Ifconfig.up(iface)
378
Color.pl(' {G}done{W}')
379
380
@staticmethod
381
def start_network_manager():
382
Color.p('{!} {O}restarting {R}NetworkManager{O}...')
383
384
if Process.exists('service'):
385
cmd = 'service network-manager start'
386
proc = Process(cmd)
387
(out, err) = proc.get_output()
388
if proc.poll() != 0:
389
Color.pl(' {R}Error executing {O}%s{W}' % cmd)
390
if out is not None and out.strip() != '':
391
Color.pl('{!} {O}STDOUT> %s{W}' % out)
392
if err is not None and err.strip() != '':
393
Color.pl('{!} {O}STDERR> %s{W}' % err)
394
else:
395
Color.pl(' {G}done{W} ({C}%s{W})' % cmd)
396
return
397
398
if Process.exists('systemctl'):
399
cmd = 'systemctl start NetworkManager'
400
proc = Process(cmd)
401
(out, err) = proc.get_output()
402
if proc.poll() != 0:
403
Color.pl(' {R}Error executing {O}%s{W}' % cmd)
404
if out is not None and out.strip() != '':
405
Color.pl('{!} {O}STDOUT> %s{W}' % out)
406
if err is not None and err.strip() != '':
407
Color.pl('{!} {O}STDERR> %s{W}' % err)
408
else:
409
Color.pl(' {G}done{W} ({C}%s{W})' % cmd)
410
return
411
else:
412
Color.pl(' {R}cannot restart NetworkManager: {O}systemctl{R} or {O}service{R} not found{W}')
413
414
if __name__ == '__main__':
415
stdout = '''
416
Found 2 processes that could cause trouble.
417
If airodump-ng, aireplay-ng or airtun-ng stops working after
418
a short period of time, you may want to run 'airmon-ng check kill'
419
420
PID Name
421
5563 avahi-daemon
422
5564 avahi-daemon
423
424
PHY Interface Driver Chipset
425
426
phy0 wlx00c0ca4ecae0 rtl8187 Realtek Semiconductor Corp. RTL8187
427
Interface 15mon is too long for linux so it will be renamed to the old style (wlan#) name.
428
429
(mac80211 monitor mode vif enabled on [phy0]wlan0mon
430
(mac80211 station mode vif disabled for [phy0]wlx00c0ca4ecae0)
431
'''
432
start_iface = Airmon._parse_airmon_start(stdout)
433
print('start_iface from stdout:', start_iface)
434
435
Configuration.initialize(False)
436
iface = Airmon.ask()
437
(disabled_iface, enabled_iface) = Airmon.stop(iface)
438
print('Disabled:', disabled_iface)
439
print('Enabled:', enabled_iface)
440
441