moriarty-project 0.1.20__py3-none-any.whl → 0.1.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,851 +0,0 @@
1
- """
2
- Utility functions for WifiPPLER.
3
-
4
- This module provides various utility functions used throughout the WifiPPLER
5
- package, including network interface management, dependency checking, and
6
- other helper functions.
7
- """
8
- import os
9
- import re
10
- import sys
11
- import time
12
- import logging
13
- import subprocess
14
- import shutil
15
- import fcntl
16
- import struct
17
- import array
18
- import socket
19
- import platform
20
- from typing import List, Dict, Tuple, Optional, Union, Any, Callable, Set
21
- from dataclasses import asdict
22
-
23
- # Configure logging
24
- logging.basicConfig(level=logging.INFO)
25
- logger = logging.getLogger(__name__)
26
-
27
- # Constants
28
- WIRELESS_EXT = 0x8B01 # SIOCGIWNAME
29
- SIOCGIFHWADDR = 0x8927 # Get hardware address
30
- SIOCGIFADDR = 0x8915 # Get IP address
31
- SIOCGIFNETMASK = 0x891B # Get netmask
32
- SIOCGIFBRDADDR = 0x8919 # Get broadcast address
33
- SIOCGIFMTU = 0x8921 # Get MTU
34
- SIOCGIFINDEX = 0x8933 # Get interface index
35
- SIOCGIFNAME = 0x8910 # Get interface name
36
- SIOCGIFFLAGS = 0x8913 # Get interface flags
37
- SIOCSIFFLAGS = 0x8914 # Set interface flags
38
-
39
- # Platform-specific constants
40
- IS_LINUX = platform.system() == 'Linux'
41
- IS_MAC = platform.system() == 'Darwin'
42
- IS_WINDOWS = platform.system() == 'Windows'
43
-
44
- # Network interface flags
45
- IFF_UP = 0x1
46
- IFF_BROADCAST = 0x2
47
- IFF_DEBUG = 0x4
48
- IFF_LOOPBACK = 0x8
49
- IFF_POINTOPOINT = 0x10
50
- IFF_NOTRAILERS = 0x20
51
- IFF_RUNNING = 0x40
52
- IFF_NOARP = 0x80
53
- IFF_PROMISC = 0x100
54
- IFF_ALLMULTI = 0x200
55
- IFF_MASTER = 0x400
56
- IFF_SLAVE = 0x800
57
- IFF_MULTICAST = 0x1000
58
- IFF_PORTSEL = 0x2000
59
- IFF_AUTOMEDIA = 0x4000
60
- IFF_DYNAMIC = 0x8000
61
-
62
- def is_root() -> bool:
63
- """
64
- Check if the script is running with root privileges.
65
-
66
- Returns:
67
- bool: True if running as root, False otherwise
68
- """
69
- return os.geteuid() == 0
70
-
71
- def check_dependencies() -> List[str]:
72
- """
73
- Check for required system dependencies.
74
-
75
- Returns:
76
- List[str]: List of missing dependencies
77
- """
78
- required = [
79
- 'iwconfig', 'iw', 'ifconfig', 'aircrack-ng', 'airodump-ng',
80
- 'aireplay-ng', 'airmon-ng', 'wash', 'reaver', 'bully', 'hcxdumptool',
81
- 'hcxpcapngtool', 'hashcat', 'tshark', 'macchanger', 'rfkill'
82
- ]
83
-
84
- missing = []
85
- for cmd in required:
86
- if not command_exists(cmd):
87
- missing.append(cmd)
88
-
89
- return missing
90
-
91
- def command_exists(cmd: str) -> bool:
92
- """
93
- Check if a command exists in the system PATH.
94
-
95
- Args:
96
- cmd: Command to check
97
-
98
- Returns:
99
- bool: True if command exists, False otherwise
100
- """
101
- return shutil.which(cmd) is not None
102
-
103
- def get_network_interfaces() -> List[Dict[str, Any]]:
104
- """
105
- Get a list of all network interfaces.
106
-
107
- Returns:
108
- List[Dict[str, Any]]: List of interfaces with their properties
109
- """
110
- interfaces = []
111
-
112
- if IS_LINUX:
113
- # Linux implementation using /sys/class/net
114
- net_path = '/sys/class/net'
115
- if os.path.exists(net_path):
116
- for ifname in os.listdir(net_path):
117
- if ifname == 'lo':
118
- continue
119
-
120
- iface = {
121
- 'name': ifname,
122
- 'wireless': os.path.exists(f"{net_path}/{ifname}/wireless"),
123
- 'state': 'down',
124
- 'mac': get_interface_mac(ifname),
125
- 'ip': get_interface_ip(ifname),
126
- 'netmask': get_interface_netmask(ifname),
127
- 'broadcast': get_interface_broadcast(ifname),
128
- 'mtu': get_interface_mtu(ifname)
129
- }
130
-
131
- # Check if interface is up
132
- try:
133
- with open(f"{net_path}/{ifname}/operstate", 'r') as f:
134
- state = f.read().strip()
135
- iface['state'] = state if state in ['up', 'down'] else 'unknown'
136
- except:
137
- pass
138
-
139
- interfaces.append(iface)
140
-
141
- elif IS_MAC:
142
- # macOS implementation using ifconfig
143
- try:
144
- result = subprocess.run(['ifconfig', '-l'], capture_output=True, text=True)
145
- if result.returncode == 0:
146
- for ifname in result.stdout.strip().split():
147
- if ifname == 'lo0':
148
- continue
149
-
150
- iface = {
151
- 'name': ifname,
152
- 'wireless': ifname.startswith(('en', 'wl')), # Approximate
153
- 'state': 'unknown',
154
- 'mac': get_interface_mac(ifname),
155
- 'ip': get_interface_ip(ifname),
156
- 'netmask': get_interface_netmask(ifname),
157
- 'broadcast': get_interface_broadcast(ifname),
158
- 'mtu': get_interface_mtu(ifname)
159
- }
160
-
161
- # Check if interface is up
162
- result = subprocess.run(['ifconfig', ifname], capture_output=True, text=True)
163
- if 'status: active' in result.stdout or 'UP' in result.stdout:
164
- iface['state'] = 'up'
165
- else:
166
- iface['state'] = 'down'
167
-
168
- interfaces.append(iface)
169
- except Exception as e:
170
- logger.error(f"Error getting network interfaces: {e}")
171
-
172
- return interfaces
173
-
174
- def get_wireless_interfaces() -> List[Dict[str, Any]]:
175
- """
176
- Obtém uma lista de interfaces de rede sem fio.
177
-
178
- Returns:
179
- List[Dict[str, Any]]: Lista de interfaces sem fio com suas propriedades.
180
- Cada dicionário contém as seguintes chaves:
181
- - name: Nome da interface
182
- - mac: Endereço MAC da interface
183
- - ip: Endereço IP da interface
184
- - wireless: True se for uma interface sem fio
185
- - up: True se a interface estiver ativa
186
- - mtu: Tamanho máximo de unidade de transmissão
187
-
188
- Raises:
189
- RuntimeError: Se ocorrer um erro ao obter as interfaces de rede
190
- """
191
- try:
192
- interfaces = get_network_interfaces()
193
- if not interfaces:
194
- logger.warning("Nenhuma interface de rede encontrada")
195
- return []
196
-
197
- wireless_interfaces = []
198
- for iface in interfaces:
199
- try:
200
- if iface.get('wireless', False):
201
- # Adiciona informações adicionais à interface
202
- iface_info = {
203
- 'name': iface.get('name', ''),
204
- 'mac': iface.get('mac', ''),
205
- 'ip': iface.get('ip', ''),
206
- 'wireless': True,
207
- 'up': iface.get('up', False),
208
- 'mtu': iface.get('mtu', 0)
209
- }
210
- wireless_interfaces.append(iface_info)
211
- except Exception as e:
212
- logger.error(f"Erro ao processar interface {iface.get('name', 'desconhecida')}: {e}")
213
- continue
214
-
215
- if not wireless_interfaces:
216
- logger.warning("Nenhuma interface sem fio encontrada")
217
-
218
- return wireless_interfaces
219
-
220
- except Exception as e:
221
- error_msg = f"Erro ao obter interfaces sem fio: {e}"
222
- logger.error(error_msg)
223
- raise RuntimeError(error_msg) from e
224
-
225
- def get_interface_mac(interface: str) -> Optional[str]:
226
- """
227
- Get the MAC address of a network interface.
228
-
229
- Args:
230
- interface: Interface name
231
-
232
- Returns:
233
- Optional[str]: MAC address or None if not found
234
- """
235
- try:
236
- if IS_LINUX or IS_MAC:
237
- with open(f"/sys/class/net/{interface}/address") as f:
238
- return f.read().strip()
239
- except:
240
- pass
241
-
242
- try:
243
- if IS_LINUX:
244
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
245
- info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', interface[:15].encode()))
246
- return ':'.join(f'{b:02x}' for b in info[18:24])
247
- elif IS_MAC:
248
- result = subprocess.run(['ifconfig', interface], capture_output=True, text=True)
249
- match = re.search(r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})', result.stdout)
250
- if match:
251
- return match.group(0).lower()
252
- except:
253
- pass
254
-
255
- return None
256
-
257
- def get_interface_ip(interface: str) -> Optional[str]:
258
- """
259
- Get the IP address of a network interface.
260
-
261
- Args:
262
- interface: Interface name
263
-
264
- Returns:
265
- Optional[str]: IP address or None if not found
266
- """
267
- try:
268
- if IS_LINUX or IS_MAC:
269
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
270
- try:
271
- # Works for both IPv4 and IPv6
272
- return socket.inet_ntoa(fcntl.ioctl(
273
- s.fileno(),
274
- 0x8915, # SIOCGIFADDR
275
- struct.pack('256s', interface[:15].encode())
276
- )[20:24])
277
- except:
278
- pass
279
- except:
280
- pass
281
-
282
- try:
283
- if IS_MAC:
284
- result = subprocess.run(['ifconfig', interface, 'inet'], capture_output=True, text=True)
285
- match = re.search(r'inet (\d+\.\d+\.\d+\.\d+)', result.stdout)
286
- if match:
287
- return match.group(1)
288
- except:
289
- pass
290
-
291
- return None
292
-
293
- def get_interface_netmask(interface: str) -> Optional[str]:
294
- """
295
- Get the netmask of a network interface.
296
-
297
- Args:
298
- interface: Interface name
299
-
300
- Returns:
301
- Optional[str]: Netmask or None if not found
302
- """
303
- try:
304
- if IS_LINUX or IS_MAC:
305
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
306
- try:
307
- netmask = socket.inet_ntoa(fcntl.ioctl(
308
- s.fileno(),
309
- 0x891B, # SIOCGIFNETMASK
310
- struct.pack('256s', interface[:15].encode())
311
- )[20:24])
312
- return netmask
313
- except:
314
- pass
315
- except:
316
- pass
317
-
318
- try:
319
- if IS_MAC:
320
- result = subprocess.run(['ifconfig', interface, 'inet'], capture_output=True, text=True)
321
- match = re.search(r'netmask (0x[0-9a-fA-F]+)', result.stdout)
322
- if match:
323
- # Convert hex netmask to dotted decimal
324
- netmask_hex = match.group(1)
325
- netmask_int = int(netmask_hex, 16)
326
- return socket.inet_ntoa(struct.pack('>I', netmask_int))
327
- except:
328
- pass
329
-
330
- return None
331
-
332
- def get_interface_broadcast(interface: str) -> Optional[str]:
333
- """
334
- Get the broadcast address of a network interface.
335
-
336
- Args:
337
- interface: Interface name
338
-
339
- Returns:
340
- Optional[str]: Broadcast address or None if not found
341
- """
342
- try:
343
- if IS_LINUX or IS_MAC:
344
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
345
- try:
346
- broadcast = socket.inet_ntoa(fcntl.ioctl(
347
- s.fileno(),
348
- 0x8919, # SIOCGIFBRDADDR
349
- struct.pack('256s', interface[:15].encode())
350
- )[20:24])
351
- return broadcast
352
- except:
353
- pass
354
- except:
355
- pass
356
-
357
- try:
358
- if IS_MAC:
359
- result = subprocess.run(['ifconfig', interface, 'inet'], capture_output=True, text=True)
360
- match = re.search(r'broadcast (\d+\.\d+\.\d+\.\d+)', result.stdout)
361
- if match:
362
- return match.group(1)
363
- except:
364
- pass
365
-
366
- return None
367
-
368
- def get_interface_mtu(interface: str) -> Optional[int]:
369
- """
370
- Get the MTU of a network interface.
371
-
372
- Args:
373
- interface: Interface name
374
-
375
- Returns:
376
- Optional[int]: MTU or None if not found
377
- """
378
- try:
379
- if IS_LINUX:
380
- with open(f"/sys/class/net/{interface}/mtu", 'r') as f:
381
- return int(f.read().strip())
382
- elif IS_MAC:
383
- result = subprocess.run(['ifconfig', interface], capture_output=True, text=True)
384
- match = re.search(r'mtu (\d+)', result.stdout)
385
- if match:
386
- return int(match.group(1))
387
- except:
388
- pass
389
-
390
- return None
391
-
392
- def set_monitor_mode(interface: str, channel: int = None) -> bool:
393
- """
394
- Set a wireless interface to monitor mode.
395
-
396
- Args:
397
- interface: Interface name
398
- channel: Optional channel to set
399
-
400
- Returns:
401
- bool: True if successful, False otherwise
402
- """
403
- if not is_root():
404
- logger.error("Root privileges required to set monitor mode")
405
- return False
406
-
407
- try:
408
- # Bring interface down
409
- subprocess.run(['ip', 'link', 'set', interface, 'down'], check=True)
410
-
411
- # Set monitor mode
412
- subprocess.run(['iw', 'dev', interface, 'set', 'monitor', 'none'], check=True)
413
-
414
- # Bring interface up
415
- subprocess.run(['ip', 'link', 'set', interface, 'up'], check=True)
416
-
417
- # Set channel if specified
418
- if channel is not None:
419
- subprocess.run(['iw', 'dev', interface, 'set', 'channel', str(channel)], check=True)
420
-
421
- return True
422
- except subprocess.CalledProcessError as e:
423
- logger.error(f"Failed to set monitor mode: {e}")
424
- return False
425
-
426
- def set_managed_mode(interface: str) -> bool:
427
- """
428
- Set a wireless interface to managed mode.
429
-
430
- Args:
431
- interface: Interface name
432
-
433
- Returns:
434
- bool: True if successful, False otherwise
435
- """
436
- if not is_root():
437
- logger.error("Root privileges required to set managed mode")
438
- return False
439
-
440
- try:
441
- # Bring interface down
442
- subprocess.run(['ip', 'link', 'set', interface, 'down'], check=True)
443
-
444
- # Set managed mode
445
- subprocess.run(['iw', 'dev', interface, 'set', 'type', 'managed'], check=True)
446
-
447
- # Bring interface up
448
- subprocess.run(['ip', 'link', 'set', interface, 'up'], check=True)
449
-
450
- # Restart network manager
451
- if command_exists('systemctl'):
452
- subprocess.run(['systemctl', 'restart', 'NetworkManager'], check=False)
453
- elif command_exists('service'):
454
- subprocess.run(['service', 'network-manager', 'restart'], check=False)
455
-
456
- return True
457
- except subprocess.CalledProcessError as e:
458
- logger.error(f"Failed to set managed mode: {e}")
459
- return False
460
-
461
- def get_monitor_interfaces() -> List[str]:
462
- """
463
- Get a list of interfaces in monitor mode.
464
-
465
- Returns:
466
- List[str]: List of interface names in monitor mode
467
- """
468
- interfaces = []
469
-
470
- try:
471
- if IS_LINUX:
472
- # List all interfaces
473
- for iface in os.listdir('/sys/class/net'):
474
- if iface.startswith(('mon', 'wlan', 'wlp', 'wlo')):
475
- # Check if in monitor mode
476
- proc = subprocess.Popen(['iwconfig', iface],
477
- stdout=subprocess.PIPE,
478
- stderr=subprocess.PIPE)
479
- out, _ = proc.communicate()
480
-
481
- if b'Mode:Monitor' in out:
482
- interfaces.append(iface)
483
- elif IS_MAC:
484
- # On macOS, interfaces in monitor mode typically start with 'mon'
485
- result = subprocess.run(['ifconfig', '-l'], capture_output=True, text=True)
486
- interfaces = [iface for iface in result.stdout.strip().split()
487
- if iface.startswith('en') and 'monitor' in
488
- subprocess.run(['ifconfig', iface], capture_output=True, text=True).stdout]
489
- except Exception as e:
490
- logger.error(f"Error getting monitor interfaces: {e}")
491
-
492
- return interfaces
493
-
494
- def get_interface_signal(interface: str) -> Optional[int]:
495
- """
496
- Get the signal strength of a wireless interface in dBm.
497
-
498
- Args:
499
- interface: Interface name
500
-
501
- Returns:
502
- Optional[int]: Signal strength in dBm or None if not available
503
- """
504
- try:
505
- if IS_LINUX or IS_MAC:
506
- proc = subprocess.Popen(['iwconfig', interface],
507
- stdout=subprocess.PIPE,
508
- stderr=subprocess.PIPE)
509
- out, _ = proc.communicate()
510
-
511
- # Look for signal level in the format "Signal level=-XX dBm"
512
- match = re.search(r'Signal level=(-\d+)\s*dBm', out.decode('utf-8', 'ignore'))
513
- if match:
514
- return int(match.group(1))
515
- except:
516
- pass
517
-
518
- return None
519
-
520
- def get_interface_ssid(interface: str) -> Optional[str]:
521
- """
522
- Get the SSID that a wireless interface is connected to.
523
-
524
- Args:
525
- interface: Interface name
526
-
527
- Returns:
528
- Optional[str]: SSID or None if not connected
529
- """
530
- try:
531
- if IS_LINUX:
532
- proc = subprocess.Popen(['iwconfig', interface],
533
- stdout=subprocess.PIPE,
534
- stderr=subprocess.PIPE)
535
- out, _ = proc.communicate()
536
-
537
- # Look for ESSID in the format "ESSID:"MyWiFi""
538
- match = re.search(r'ESSID:"([^"]+)"', out.decode('utf-8', 'ignore'))
539
- if match and match.group(1) != 'off/any':
540
- return match.group(1)
541
- elif IS_MAC:
542
- result = subprocess.run(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'],
543
- capture_output=True, text=True)
544
- match = re.search(r' SSID: (.+)', result.stdout)
545
- if match:
546
- return match.group(1).strip()
547
- except:
548
- pass
549
-
550
- return None
551
-
552
- def get_interface_channel(interface: str) -> Optional[int]:
553
- """
554
- Get the current channel of a wireless interface.
555
-
556
- Args:
557
- interface: Interface name
558
-
559
- Returns:
560
- Optional[int]: Channel number or None if not available
561
- """
562
- try:
563
- if IS_LINUX or IS_MAC:
564
- proc = subprocess.Popen(['iwconfig', interface],
565
- stdout=subprocess.PIPE,
566
- stderr=subprocess.PIPE)
567
- out, _ = proc.communicate()
568
-
569
- # Look for channel in the format "Channel:XX"
570
- match = re.search(r'Channel:(\d+)', out.decode('utf-8', 'ignore'))
571
- if match:
572
- return int(match.group(1))
573
- except:
574
- pass
575
-
576
- return None
577
-
578
- def get_interface_bitrate(interface: str) -> Optional[float]:
579
- """
580
- Get the current bitrate of a wireless interface in Mbps.
581
-
582
- Args:
583
- interface: Interface name
584
-
585
- Returns:
586
- Optional[float]: Bitrate in Mbps or None if not available
587
- """
588
- try:
589
- if IS_LINUX or IS_MAC:
590
- proc = subprocess.Popen(['iwconfig', interface],
591
- stdout=subprocess.PIPE,
592
- stderr=subprocess.PIPE)
593
- out, _ = proc.communicate()
594
-
595
- # Look for bit rate in the format "Bit Rate=XX Mb/s"
596
- match = re.search(r'Bit Rate[:=](\d+(?:\.\d+)?)\s*Mb/s', out.decode('utf-8', 'ignore'))
597
- if match:
598
- return float(match.group(1))
599
- except:
600
- pass
601
-
602
- return None
603
-
604
- def randomize_mac(interface: str) -> bool:
605
- """
606
- Randomize the MAC address of a network interface.
607
-
608
- Args:
609
- interface: Interface name
610
-
611
- Returns:
612
- bool: True if successful, False otherwise
613
- """
614
- if not is_root():
615
- logger.error("Root privileges required to change MAC address")
616
- return False
617
-
618
- try:
619
- # Generate a random MAC address
620
- import random
621
- new_mac = ':'.join(['%02x' % random.randint(0x00, 0xff) for _ in range(6)])
622
-
623
- # Bring interface down
624
- subprocess.run(['ip', 'link', 'set', interface, 'down'], check=True)
625
-
626
- # Set new MAC address
627
- subprocess.run(['ip', 'link', 'set', 'dev', interface, 'address', new_mac], check=True)
628
-
629
- # Bring interface up
630
- subprocess.run(['ip', 'link', 'set', interface, 'up'], check=True)
631
-
632
- return True
633
- except subprocess.CalledProcessError as e:
634
- logger.error(f"Failed to randomize MAC address: {e}")
635
- return False
636
-
637
- def run_command(cmd: Union[str, List[str]], capture_output: bool = False,
638
- check: bool = True, **kwargs) -> subprocess.CompletedProcess:
639
- """
640
- Run a shell command with error handling.
641
-
642
- Args:
643
- cmd: Command to run (string or list)
644
- capture_output: Whether to capture stdout/stderr
645
- check: Whether to raise an exception on non-zero exit code
646
- **kwargs: Additional arguments to subprocess.run()
647
-
648
- Returns:
649
- subprocess.CompletedProcess: Command execution result
650
- """
651
- if isinstance(cmd, str):
652
- cmd = cmd.split()
653
-
654
- kwargs.setdefault('stdout', subprocess.PIPE if capture_output else None)
655
- kwargs.setdefault('stderr', subprocess.PIPE if capture_output else None)
656
- kwargs.setdefault('text', True)
657
-
658
- try:
659
- return subprocess.run(cmd, check=check, **kwargs)
660
- except subprocess.CalledProcessError as e:
661
- logger.error(f"Command failed with exit code {e.returncode}: {' '.join(cmd)}")
662
- if capture_output and e.stderr:
663
- logger.error(f"Error output: {e.stderr.strip()}")
664
- raise
665
-
666
- async def run_command_async(cmd: Union[str, List[str]], **kwargs) -> subprocess.CompletedProcess:
667
- """
668
- Run a shell command asynchronously.
669
-
670
- Args:
671
- cmd: Command to run (string or list)
672
- **kwargs: Additional arguments to asyncio.create_subprocess_exec()
673
-
674
- Returns:
675
- subprocess.CompletedProcess: Command execution result
676
- """
677
- if isinstance(cmd, str):
678
- cmd = cmd.split()
679
-
680
- process = await asyncio.create_subprocess_exec(
681
- *cmd,
682
- stdout=asyncio.subprocess.PIPE,
683
- stderr=asyncio.subprocess.PIPE,
684
- **kwargs
685
- )
686
-
687
- stdout, stderr = await process.communicate()
688
-
689
- return subprocess.CompletedProcess(
690
- args=cmd,
691
- returncode=process.returncode,
692
- stdout=stdout.decode() if stdout else '',
693
- stderr=stderr.decode() if stderr else ''
694
- )
695
-
696
- def get_wireless_drivers() -> List[Dict[str, str]]:
697
- """
698
- Get a list of wireless drivers and their information.
699
-
700
- Returns:
701
- List[Dict[str, str]]: List of driver information
702
- """
703
- drivers = []
704
-
705
- if IS_LINUX:
706
- try:
707
- # Check loaded kernel modules
708
- with open('/proc/modules', 'r') as f:
709
- for line in f:
710
- module = line.split()[0]
711
- if any(x in module.lower() for x in ['wlan', 'wireless', '80211', 'ath', 'rtl', 'rtw', 'mt76']):
712
- drivers.append({
713
- 'name': module,
714
- 'type': 'kernel',
715
- 'status': 'loaded'
716
- })
717
-
718
- # Check loaded kernel modules with modinfo
719
- for driver in drivers[:]: # Iterate over a copy of the list
720
- try:
721
- result = subprocess.run(['modinfo', driver['name']],
722
- capture_output=True, text=True)
723
- if result.returncode == 0:
724
- # Parse modinfo output
725
- info = {}
726
- for line in result.stdout.splitlines():
727
- if ':' in line:
728
- key, value = line.split(':', 1)
729
- info[key.strip()] = value.strip()
730
-
731
- # Update driver info
732
- driver.update({
733
- 'description': info.get('description', ''),
734
- 'version': info.get('version', ''),
735
- 'author': info.get('author', ''),
736
- 'license': info.get('license', '')
737
- })
738
- except:
739
- pass
740
-
741
- # Check for USB wireless devices
742
- if os.path.exists('/sys/bus/usb/drivers'):
743
- for driver in os.listdir('/sys/bus/usb/drivers'):
744
- if any(x in driver.lower() for x in ['wlan', 'wireless', '80211', 'ath', 'rtl', 'rtw']):
745
- drivers.append({
746
- 'name': driver,
747
- 'type': 'usb',
748
- 'status': 'available'
749
- })
750
-
751
- # Check for PCI wireless devices
752
- if os.path.exists('/sys/bus/pci/drivers'):
753
- for driver in os.listdir('/sys/bus/pci/drivers'):
754
- if any(x in driver.lower() for x in ['wlan', 'wireless', '80211', 'ath', 'rtl', 'rtw']):
755
- drivers.append({
756
- 'name': driver,
757
- 'type': 'pci',
758
- 'status': 'available'
759
- })
760
-
761
- except Exception as e:
762
- logger.error(f"Error getting wireless drivers: {e}")
763
-
764
- return drivers
765
-
766
- def check_wireless_extensions(interface: str) -> bool:
767
- """
768
- Check if a network interface supports wireless extensions.
769
-
770
- Args:
771
- interface: Interface name
772
-
773
- Returns:
774
- bool: True if wireless extensions are supported, False otherwise
775
- """
776
- try:
777
- if IS_LINUX:
778
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
779
- try:
780
- # Try to get wireless name
781
- fcntl.ioctl(s.fileno(), WIRELESS_EXT, interface.encode() + b'\x00' * 32)
782
- return True
783
- except IOError:
784
- return False
785
- elif IS_MAC:
786
- # macOS always supports wireless extensions
787
- return True
788
- else:
789
- return False
790
- except:
791
- return False
792
-
793
- def get_wireless_capabilities(interface: str) -> Dict[str, Any]:
794
- """
795
- Get the wireless capabilities of an interface.
796
-
797
- Args:
798
- interface: Interface name
799
-
800
- Returns:
801
- Dict[str, Any]: Dictionary of wireless capabilities
802
- """
803
- capabilities = {
804
- 'monitor': False,
805
- 'injection': False,
806
- 'frequency_bands': [],
807
- 'encryption': [],
808
- 'modes': []
809
- }
810
-
811
- if not check_wireless_extensions(interface):
812
- return capabilities
813
-
814
- try:
815
- # Check if interface supports monitor mode
816
- result = subprocess.run(['iw', 'phy', interface, 'info'],
817
- capture_output=True, text=True)
818
-
819
- if 'monitor' in result.stdout.lower():
820
- capabilities['monitor'] = True
821
-
822
- # Check for packet injection support
823
- if 'RX invalid nwid' in result.stdout:
824
- capabilities['injection'] = True
825
-
826
- # Check supported frequency bands
827
- if '5180 MHz' in result.stdout:
828
- capabilities['frequency_bands'].append('5GHz')
829
- if '2412 MHz' in result.stdout:
830
- capabilities['frequency_bands'].append('2.4GHz')
831
-
832
- # Check supported encryption types
833
- if 'WPA' in result.stdout:
834
- capabilities['encryption'].append('WPA')
835
- if 'WPA2' in result.stdout:
836
- capabilities['encryption'].append('WPA2')
837
- if 'WEP' in result.stdout:
838
- capabilities['encryption'].append('WEP')
839
-
840
- # Check supported modes
841
- if 'AP' in result.stdout:
842
- capabilities['modes'].append('AP')
843
- if 'station' in result.stdout.lower():
844
- capabilities['modes'].append('station')
845
- if 'monitor' in result.stdout.lower():
846
- capabilities['modes'].append('monitor')
847
-
848
- except Exception as e:
849
- logger.error(f"Error getting wireless capabilities: {e}")
850
-
851
- return capabilities