moriarty-project 0.1.21__py3-none-any.whl → 0.1.23__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.
Files changed (26) hide show
  1. moriarty/__init__.py +1 -1
  2. moriarty/cli/app.py +5 -6
  3. moriarty/modules/port_scanner.py +1 -5
  4. {moriarty_project-0.1.21.dist-info → moriarty_project-0.1.23.dist-info}/METADATA +36 -49
  5. {moriarty_project-0.1.21.dist-info → moriarty_project-0.1.23.dist-info}/RECORD +7 -26
  6. moriarty/cli/wifippler.py +0 -124
  7. moriarty/modules/wifippler/__init__.py +0 -92
  8. moriarty/modules/wifippler/cli/__init__.py +0 -8
  9. moriarty/modules/wifippler/cli/commands.py +0 -123
  10. moriarty/modules/wifippler/core/__init__.py +0 -94
  11. moriarty/modules/wifippler/core/attacks/__init__.py +0 -146
  12. moriarty/modules/wifippler/core/attacks/deauth.py +0 -262
  13. moriarty/modules/wifippler/core/attacks/handshake.py +0 -402
  14. moriarty/modules/wifippler/core/attacks/pmkid.py +0 -424
  15. moriarty/modules/wifippler/core/attacks/wep.py +0 -467
  16. moriarty/modules/wifippler/core/attacks/wpa.py +0 -446
  17. moriarty/modules/wifippler/core/attacks/wps.py +0 -474
  18. moriarty/modules/wifippler/core/models/__init__.py +0 -10
  19. moriarty/modules/wifippler/core/models/network.py +0 -216
  20. moriarty/modules/wifippler/core/scanner.py +0 -901
  21. moriarty/modules/wifippler/core/utils/__init__.py +0 -636
  22. moriarty/modules/wifippler/core/utils/exec.py +0 -182
  23. moriarty/modules/wifippler/core/utils/network.py +0 -223
  24. moriarty/modules/wifippler/core/utils/system.py +0 -153
  25. {moriarty_project-0.1.21.dist-info → moriarty_project-0.1.23.dist-info}/WHEEL +0 -0
  26. {moriarty_project-0.1.21.dist-info → moriarty_project-0.1.23.dist-info}/entry_points.txt +0 -0
@@ -1,636 +0,0 @@
1
- """
2
- Módulo de utilidades do WiFiPPLER.
3
-
4
- Este módulo fornece funções auxiliares para operações comuns de rede e sistema.
5
- """
6
- from typing import Optional, List, Dict, Any
7
-
8
- # Importações principais
9
- from .network import (
10
- get_interface_ip,
11
- get_interface_netmask,
12
- get_interface_gateway,
13
- is_wireless_interface,
14
- get_network_interfaces,
15
- is_interface_up,
16
- get_interface_mac
17
- )
18
-
19
- from .system import (
20
- is_root,
21
- check_dependencies,
22
- command_exists,
23
- ensure_root,
24
- ensure_dependencies,
25
- get_available_interfaces,
26
- get_wireless_interfaces
27
- )
28
-
29
- from .exec import (
30
- run_command,
31
- run_command_async,
32
- run_sudo_command,
33
- command_success,
34
- get_command_output,
35
- get_command_output_safe
36
- )
37
-
38
- # Configuração de logging
39
- import logging
40
- logging.basicConfig(level=logging.INFO)
41
- logger = logging.getLogger(__name__)
42
-
43
- # Exporta apenas o que é necessário para uso externo
44
- __all__ = [
45
- # Funções de rede
46
- 'get_interface_ip',
47
- 'get_interface_netmask',
48
- 'get_interface_gateway',
49
- 'is_wireless_interface',
50
- 'get_network_interfaces',
51
- 'is_interface_up',
52
- 'get_interface_mac',
53
-
54
- # Funções do sistema
55
- 'is_root',
56
- 'check_dependencies',
57
- 'command_exists',
58
- 'ensure_root',
59
- 'ensure_dependencies',
60
- 'get_available_interfaces',
61
- 'get_wireless_interfaces',
62
-
63
- # Funções de execução de comandos
64
- 'run_command',
65
- 'run_command_async',
66
- 'run_sudo_command',
67
- 'command_success',
68
- 'get_command_output',
69
- 'get_command_output_safe',
70
-
71
- # Logger
72
- 'logger'
73
- ]
74
- SIOCGIFNETMASK = 0x891B
75
- SIOCGIFBRDADDR = 0x8919
76
- SIOCGIFMTU = 0x8921
77
- SIOCGIFINDEX = 0x8933
78
- SIOCGIFNAME = 0x8910
79
- SIOCGIFFLAGS = 0x8913
80
- SIOCSIFFLAGS = 0x8914
81
-
82
- # Mapeamento de códigos de segurança
83
- SECURITY_MAP = {
84
- 'WPA2': WiFiSecurityType.WPA2,
85
- 'WPA3': WiFiSecurityType.WPA3,
86
- 'WPA2-EAP': WiFiSecurityType.WPA2_ENTERPRISE,
87
- 'WPA3-EAP': WiFiSecurityType.WPA3_ENTERPRISE,
88
- 'WEP': WiFiSecurityType.WEP,
89
- 'OPEN': WiFiSecurityType.NONE,
90
- 'NONE': WiFiSecurityType.NONE,
91
- 'WPA': WiFiSecurityType.WPA,
92
- 'WPA2-PSK': WiFiSecurityType.WPA2,
93
- 'WPA3-PSK': WiFiSecurityType.WPA3,
94
- 'WPA2-PSK-CCMP': WiFiSecurityType.WPA2,
95
- 'WPA2-PSK-TKIP': WiFiSecurityType.WPA2,
96
- 'WPA-PSK': WiFiSecurityType.WPA,
97
- 'WPA-PSK-CCMP': WiFiSecurityType.WPA,
98
- 'WPA-PSK-TKIP': WiFiSecurityType.WPA,
99
- }
100
-
101
- # Mapeamento de cifras
102
- CIPHER_MAP = {
103
- 'CCMP': WiFiCipherType.CCMP,
104
- 'TKIP': WiFiCipherType.TKIP,
105
- 'WEP': WiFiCipherType.WEP_40, # Usando WEP_40 como padrão para WEP
106
- 'WEP-40': WiFiCipherType.WEP_40,
107
- 'WEP-104': WiFiCipherType.WEP_104,
108
- 'WEP-128': WiFiCipherType.WEP_104, # WEP-128 não está definido, usando WEP_104 como alternativa
109
- 'NONE': WiFiCipherType.NONE,
110
- 'GCMP': WiFiCipherType.GCMP
111
- }
112
-
113
- # Mapeamento de autenticação
114
- AUTH_MAP = {
115
- 'PSK': WiFiAuthType.WPA_PSK, # Usando WPA_PSK para PSK
116
- 'WPA-PSK': WiFiAuthType.WPA_PSK,
117
- 'WPA2-PSK': WiFiAuthType.WPA2_PSK,
118
- 'WPA3-SAE': WiFiAuthType.WPA3_SAE,
119
- 'EAP': WiFiAuthType.WPA_EAP, # Usando WPA_EAP para EAP
120
- 'WPA-EAP': WiFiAuthType.WPA_EAP,
121
- 'WPA2-EAP': WiFiAuthType.WPA2_EAP,
122
- 'WPA3-EAP': WiFiAuthType.WPA3_EAP,
123
- 'OPEN': WiFiAuthType.OPEN,
124
- 'SHARED': WiFiAuthType.SHARED,
125
- 'OWE': WiFiAuthType.OWE,
126
- 'NONE': WiFiAuthType.OPEN,
127
- }
128
-
129
- def is_root() -> bool:
130
- """Verifica se o script está sendo executado como root."""
131
- return os.geteuid() == 0
132
-
133
- def check_dependencies() -> List[str]:
134
- """Verifica as dependências necessárias."""
135
- required = ['iwconfig', 'iwlist', 'aircrack-ng', 'airodump-ng', 'aireplay-ng', 'airmon-ng']
136
- missing = []
137
-
138
- for dep in required:
139
- if not command_exists(dep):
140
- missing.append(dep)
141
-
142
-
143
- def command_exists(cmd: str) -> bool:
144
- """Verifica se um comando existe no sistema."""
145
- return shutil.which(cmd) is not None
146
-
147
- # A função get_wireless_interfaces já está definida acima, então não precisamos duplicá-la
148
-
149
- def run_command(cmd: Union[str, List[str]], capture_output: bool = False,
150
- check: bool = True, **kwargs) -> subprocess.CompletedProcess:
151
- """
152
- Executa um comando no shell com tratamento de erros.
153
-
154
- Args:
155
- cmd: Comando a ser executado (string ou lista)
156
- capture_output: Se deve capturar a saída padrão e de erro
157
- check: Se deve lançar uma exceção em caso de código de saída diferente de zero
158
- **kwargs: Argumentos adicionais para subprocess.run()
159
-
160
- Returns:
161
- subprocess.ClosedProcess: Resultado da execução do comando
162
- """
163
- if isinstance(cmd, str):
164
- cmd = cmd.split()
165
-
166
- kwargs.setdefault('stdout', subprocess.PIPE if capture_output else None)
167
- kwargs.setdefault('stderr', subprocess.PIPE if capture_output else None)
168
- kwargs.setdefault('text', True)
169
-
170
- try:
171
- return subprocess.run(cmd, check=check, **kwargs)
172
- except Exception as e:
173
- logger.error(f"Erro ao executar comando: {e}")
174
- raise
175
-
176
- def set_monitor_mode(interface: str, channel: int = None) -> bool:
177
- """Ativa o modo monitor em uma interface."""
178
- if not is_root():
179
- logger.error("Privilégios de root são necessários para ativar o modo monitor")
180
- return False
181
-
182
- try:
183
- # Para processos que podem interferir
184
- subprocess.run(['airmon-ng', 'check', 'kill'],
185
- stdout=subprocess.PIPE,
186
- stderr=subprocess.PIPE)
187
-
188
- # Ativa o modo monitor
189
- cmd = ['airmon-ng', 'start', interface]
190
- if channel:
191
- cmd.extend(['-c', str(channel)])
192
-
193
- result = subprocess.run(cmd,
194
- stdout=subprocess.PIPE,
195
- stderr=subprocess.PIPE,
196
- text=True)
197
-
198
- if result.returncode != 0:
199
- logger.error(f"Falha ao ativar o modo monitor: {result.stderr}")
200
- return False
201
-
202
- return True
203
-
204
- except subprocess.CalledProcessError as e:
205
- logger.error(f"Erro ao executar airmon-ng: {e}")
206
- return False
207
- except Exception as e:
208
- logger.error(f"Erro inesperado: {e}")
209
- return False
210
-
211
- def restore_network_interface(interface: str) -> bool:
212
- """Restaura a interface para o modo gerenciado."""
213
- if not is_root():
214
- logger.error("Privilégios de root são necessários para restaurar a interface")
215
- return False
216
-
217
- try:
218
- # Para o modo monitor
219
- subprocess.run(['airmon-ng', 'stop', interface], check=True)
220
-
221
- # Reinicia o gerenciador de rede
222
- if command_exists('systemctl'):
223
- subprocess.run(['systemctl', 'restart', 'NetworkManager'], check=False)
224
- elif command_exists('service'):
225
- subprocess.run(['service', 'network-manager', 'restart'], check=False)
226
-
227
- return True
228
- except subprocess.CalledProcessError as e:
229
- logger.error(f"Erro ao parar o modo monitor: {e}")
230
- return False
231
- except Exception as e:
232
- logger.error(f"Erro inesperado: {e}")
233
- return False
234
-
235
- def start_monitor_mode(interface: str, channel: int = None) -> Optional[str]:
236
- """Inicia o modo monitor em uma interface usando airmon-ng."""
237
- if not is_root():
238
- logger.error("Privilégios de root são necessários para iniciar o modo monitor")
239
- return None
240
-
241
- try:
242
- # Para processos que podem interferir
243
- subprocess.run(['airmon-ng', 'check', 'kill'],
244
- stdout=subprocess.PIPE,
245
- stderr=subprocess.PIPE)
246
-
247
- # Inicia o modo monitor
248
- cmd = ['airmon-ng', 'start', interface]
249
- if channel:
250
- cmd.extend(['-c', str(channel)])
251
-
252
- result = subprocess.run(cmd,
253
- stdout=subprocess.PIPE,
254
- stderr=subprocess.PIPE,
255
- text=True)
256
-
257
- if result.returncode != 0:
258
- logger.error(f"Falha ao iniciar o modo monitor: {result.stderr}")
259
- return None
260
-
261
- # Obtém o nome da interface em modo monitor (pode mudar, ex: wlan0 -> wlan0mon)
262
- for line in result.stdout.split('\n'):
263
- if 'monitor mode' in line and 'enabled' in line:
264
- parts = line.split()
265
- if len(parts) > 0:
266
- return parts[0].strip('()')
267
-
268
- return f"{interface}mon" # Padrão comum
269
-
270
- except subprocess.CalledProcessError as e:
271
- logger.error(f"Erro ao executar airmon-ng: {e}")
272
- return None
273
- except Exception as e:
274
- logger.error(f"Erro inesperado: {e}")
275
- return None
276
-
277
- def stop_monitor_mode(interface: str) -> bool:
278
- """Para o modo monitor em uma interface usando airmon-ng."""
279
- if not is_root():
280
- logger.error("Privilégios de root são necessários para parar o modo monitor")
281
- return False
282
-
283
- try:
284
- # Para o modo monitor
285
- subprocess.run(['airmon-ng', 'stop', interface], check=True)
286
-
287
- # Reinicia o gerenciador de rede
288
- if command_exists('systemctl'):
289
- subprocess.run(['systemctl', 'restart', 'NetworkManager'], check=False)
290
- elif command_exists('service'):
291
- subprocess.run(['service', 'network-manager', 'restart'], check=False)
292
-
293
- return True
294
- except subprocess.CalledProcessError as e:
295
- logger.error(f"Erro ao parar modo monitor: {e}")
296
- return False
297
- except Exception as e:
298
- logger.error(f"Erro inesperado: {e}")
299
- return False
300
-
301
- def get_interface_mac(interface: str) -> Optional[str]:
302
- """Obtém o endereço MAC de uma interface de rede."""
303
- try:
304
- with open(f"/sys/class/net/{interface}/address") as f:
305
- return f.read().strip()
306
- except (IOError, FileNotFoundError):
307
- return None
308
-
309
- def get_interface_ip(interface: str) -> Optional[str]:
310
- """Obtém o endereço IP de uma interface de rede."""
311
- try:
312
- return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
313
- except (KeyError, IndexError):
314
- return None
315
-
316
- def get_interface_netmask(interface: str) -> Optional[str]:
317
- """Obtém a máscara de rede de uma interface de rede."""
318
- try:
319
- return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['netmask']
320
- except (KeyError, IndexError):
321
- return None
322
-
323
- def get_interface_gateway(interface: str) -> Optional[str]:
324
- """Obtém o gateway padrão de uma interface de rede."""
325
- try:
326
- gateways = netifaces.gateways()
327
- return gateways['default'][netifaces.AF_INET][0]
328
- except (KeyError, IndexError):
329
- return None
330
-
331
- def is_wireless_interface(interface: str) -> bool:
332
- """Verifica se uma interface é sem fio."""
333
- try:
334
- with open(f"/sys/class/net/{interface}/wireless/uevent", 'r') as f:
335
- return True
336
- except (IOError, FileNotFoundError):
337
- return False
338
-
339
- def get_interface_signal(interface: str) -> Optional[int]:
340
- """Obtém a intensidade do sinal de uma interface sem fio em dBm."""
341
- try:
342
- result = subprocess.run(
343
- ['iwconfig', interface],
344
- stdout=subprocess.PIPE,
345
- stderr=subprocess.PIPE,
346
- text=True
347
- )
348
-
349
- if result.returncode != 0:
350
- return None
351
-
352
- match = re.search(r'Signal level=(-?\d+) dBm', result.stdout)
353
- if match:
354
- return int(match.group(1))
355
- return None
356
- except (subprocess.SubprocessError, ValueError):
357
- return None
358
-
359
- def get_interface_ssid(interface: str) -> Optional[str]:
360
- """Obtém o SSID ao qual a interface está conectada."""
361
- try:
362
- result = subprocess.run(
363
- ['iwgetid', '-r', interface],
364
- stdout=subprocess.PIPE,
365
- stderr=subprocess.PIPE,
366
- text=True
367
- )
368
-
369
- if result.returncode == 0 and result.stdout.strip():
370
- return result.stdout.strip()
371
- return None
372
- except (subprocess.SubprocessError, FileNotFoundError):
373
- return None
374
-
375
- def get_interface_channel(interface: str) -> Optional[int]:
376
- """Obtém o canal em que a interface está operando."""
377
- try:
378
- result = subprocess.run(
379
- ['iwlist', interface, 'channel'],
380
- stdout=subprocess.PIPE,
381
- stderr=subprocess.PIPE,
382
- text=True
383
- )
384
-
385
- if result.returncode != 0:
386
- return None
387
-
388
- match = re.search(r'Channel (\d+)', result.stdout)
389
- if match:
390
- return int(match.group(1))
391
- return None
392
- except (subprocess.SubprocessError, ValueError):
393
- return None
394
-
395
- def get_interface_bitrate(interface: str) -> Optional[float]:
396
- """Obtém a taxa de transmissão da interface em Mbps."""
397
- try:
398
- result = subprocess.run(
399
- ['iwconfig', interface],
400
- stdout=subprocess.PIPE,
401
- stderr=subprocess.PIPE,
402
- text=True
403
- )
404
-
405
- if result.returncode != 0:
406
- return None
407
-
408
- match = re.search(r'Bit Rate[:=]([\d.]+) (\w+)', result.stdout)
409
- if match:
410
- rate, unit = match.groups()
411
- rate = float(rate)
412
- if unit == 'Mb/s':
413
- return rate
414
- elif unit == 'Kb/s':
415
- return rate / 1000
416
- return None
417
- except (subprocess.SubprocessError, ValueError):
418
- return None
419
-
420
- # Funções para manipulação de pacotes
421
- def create_deauth_packet(bssid: str, client: str, reason: int = 7, count: int = 1) -> bytes:
422
- """Cria um pacote de desautenticação."""
423
- # Cabeçalho do pacote 802.11
424
- frame = [
425
- 0x00, 0x00, 0x0c, 0x00, # Radiotap header (versão, pad, len, presente)
426
- 0x04, 0x80, 0x00, 0x00, # Presente flags
427
- 0x00, 0x00, 0x00, 0x00, # Timestamp
428
- 0x00, 0x00, 0x00, 0x00, # Flags e taxa de dados
429
- 0x00, 0x00, # Canal, sinal, ruído, etc.
430
- 0x00, 0x00, 0x00, 0x00, # MCS conhecido, flags, mcs
431
- 0x00, 0x00, 0x00, 0x00, # A-MPDU
432
-
433
- # Cabeçalho 802.11 (tipo Management, subtipo Deauthentication)
434
- 0x00, 0x00, 0x0c, 0x00, # Controle de versão, tipo, subtipo, etc.
435
- 0x00, 0x00, # Duração
436
- ]
437
-
438
- # Endereço de destino (broadcast ou cliente específico)
439
- dest = [int(x, 16) for x in client.split(':')]
440
- frame.extend(dest)
441
-
442
- # Endereço de origem (BSSID)
443
- src = [int(x, 16) for x in bssid.split(':')]
444
- frame.extend(src)
445
-
446
- # BSSID (mesmo que origem para redes de infraestrutura)
447
- frame.extend(src)
448
-
449
- # Número de sequência
450
- frame.extend([0x00, 0x00])
451
-
452
- # Código de motivo (2 bytes, little-endian)
453
- frame.extend([reason, 0x00])
454
-
455
- return bytes(frame) * count
456
-
457
- # Funções para execução de comandos
458
- async def run_command_async(cmd: Union[str, List[str]], **kwargs) -> subprocess.CompletedProcess:
459
- """
460
- Executa um comando de forma assíncrona.
461
-
462
- Args:
463
- cmd: Comando a ser executado (string ou lista)
464
- **kwargs: Argumentos adicionais para asyncio.create_subprocess_exec()
465
-
466
- Returns:
467
- subprocess.CompletedProcess: Resultado da execução do comando
468
- """
469
- if isinstance(cmd, str):
470
- cmd = cmd.split()
471
-
472
- process = await asyncio.create_subprocess_exec(
473
- *cmd,
474
- stdout=asyncio.subprocess.PIPE,
475
- stderr=asyncio.subprocess.PIPE,
476
- **kwargs
477
- )
478
-
479
- stdout, stderr = await process.communicate()
480
-
481
- return subprocess.CompletedProcess(
482
- args=cmd,
483
- returncode=process.returncode,
484
- stdout=stdout,
485
- stderr=stderr
486
- )
487
-
488
- # Funções para processamento de saída
489
- def parse_airodump_csv(csv_file: str) -> List[WiFiNetwork]:
490
- """Analisa o arquivo CSV gerado pelo airodump-ng."""
491
- networks = []
492
-
493
- try:
494
- with open(csv_file, 'r') as f:
495
- lines = f.readlines()
496
-
497
- # Encontra o início dos dados das redes
498
- start_idx = 0
499
- for i, line in enumerate(lines):
500
- if line.startswith('BSSID, First time seen,'):
501
- start_idx = i + 1
502
- break
503
-
504
- # Processa as redes
505
- for line in lines[start_idx:]:
506
- line = line.strip()
507
- if not line or line.startswith('Station'):
508
- break
509
-
510
- # Extrai os campos da linha
511
- parts = [p.strip() for p in line.split(',')]
512
- if len(parts) < 14: # Número mínimo de campos esperados
513
- continue
514
-
515
- bssid = parts[0].strip()
516
- first_seen = parts[1].strip()
517
- last_seen = parts[2].strip()
518
- channel = int(parts[3].strip())
519
- speed = parts[4].strip()
520
- privacy = parts[5].strip()
521
- cipher = parts[6].strip()
522
- auth = parts[7].strip()
523
- power = int(parts[8].strip())
524
- beacons = int(parts[9].strip())
525
- iv = int(parts[10].strip())
526
- ip = parts[11].strip()
527
- id_len = int(parts[12].strip())
528
- essid = parts[13].strip()
529
-
530
- # Cria o objeto da rede
531
- network = WiFiNetwork(
532
- bssid=bssid,
533
- ssid=essid,
534
- channel=channel,
535
- signal=power,
536
- encryption=privacy,
537
- cipher=cipher,
538
- authentication=auth,
539
- first_seen=first_seen,
540
- last_seen=last_seen,
541
- speed=speed,
542
- beacons=beacons,
543
- iv=iv,
544
- ip=ip if ip != '0.0.0.0' else None
545
- )
546
-
547
- networks.append(network)
548
-
549
- except Exception as e:
550
- logger.error(f"Erro ao analisar arquivo CSV: {e}")
551
-
552
- return networks
553
-
554
- def parse_airodump_stations(csv_file: str) -> List[WiFiClient]:
555
- """Analisa a seção de estações do arquivo CSV do airodump-ng."""
556
- clients = []
557
-
558
- try:
559
- with open(csv_file, 'r') as f:
560
- lines = f.readlines()
561
-
562
- # Encontra o início da seção de estações
563
- start_idx = 0
564
- for i, line in enumerate(lines):
565
- if line.startswith('Station MAC,'):
566
- start_idx = i + 1
567
- break
568
-
569
- # Processa as estações
570
- for line in lines[start_idx:]:
571
- line = line.strip()
572
- if not line:
573
- continue
574
-
575
- # Extrai os campos da linha
576
- parts = [p.strip() for p in line.split(',')]
577
- if len(parts) < 6: # Número mínimo de campos esperados
578
- continue
579
-
580
- mac = parts[0].strip()
581
- first_seen = parts[1].strip()
582
- last_seen = parts[2].strip()
583
- power = int(parts[3].strip())
584
- packets = int(parts[4].strip())
585
- bssid = parts[5].strip()
586
-
587
- # Cria o objeto do cliente
588
- client = WiFiClient(
589
- mac=mac,
590
- bssid=bssid,
591
- signal=power,
592
- packets=packets,
593
- first_seen=first_seen,
594
- last_seen=last_seen
595
- )
596
-
597
- clients.append(client)
598
-
599
- except Exception as e:
600
- logger.error(f"Erro ao analisar estações do arquivo CSV: {e}")
601
-
602
- return clients
603
-
604
- def randomize_mac(interface: str) -> bool:
605
- """
606
- Aleatoriza o endereço MAC de uma interface de rede.
607
-
608
- Args:
609
- interface: Nome da interface de rede
610
-
611
- Returns:
612
- bool: True se bem-sucedido, False caso contrário
613
- """
614
- if not is_root():
615
- logger.error("Privilégios de root são necessários para alterar o endereço MAC")
616
- return False
617
-
618
- try:
619
- # Gera um endereço MAC aleatório
620
- import random
621
- new_mac = ':'.join(['%02x' % random.randint(0x00, 0xff) for _ in range(6)])
622
-
623
- # Desativa a interface
624
- subprocess.run(['ip', 'link', 'set', interface, 'down'], check=True)
625
-
626
- # Define o novo endereço MAC
627
- subprocess.run(['ip', 'link', 'set', 'dev', interface, 'address', new_mac], check=True)
628
-
629
- # Reativa a interface
630
- subprocess.run(['ip', 'link', 'set', interface, 'up'], check=True)
631
-
632
- logger.info(f"Endereço MAC da interface {interface} alterado para {new_mac}")
633
- return True
634
- except subprocess.CalledProcessError as e:
635
- logger.error(f"Falha ao aleatorizar o endereço MAC: {e}")
636
- return False