moriarty-project 0.1.24__py3-none-any.whl → 0.1.25__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.24"
4
+ __version__ = "0.1.25"
@@ -8,8 +8,14 @@ import re
8
8
  import socket
9
9
  import ssl
10
10
  from dataclasses import dataclass, field
11
- from datetime import datetime
12
- from typing import Dict, List, Optional, Tuple, Any
11
+ from datetime import datetime, timedelta
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional, Tuple, Any, Set, Union
14
+ from urllib.parse import urlparse
15
+ import aiofiles
16
+ import yaml
17
+ import requests
18
+ from packaging import version
13
19
 
14
20
  # Importa a classe ServiceInfo para uso no código
15
21
 
@@ -37,6 +43,34 @@ PROFILES = {
37
43
  "all": list(range(1, 65536)),
38
44
  }
39
45
 
46
+ # URL base para atualizações de serviços e vulnerabilidades
47
+ SERVICES_DB_URL = "https://raw.githubusercontent.com/nmap/nmap/master/nmap-services"
48
+ VULN_DB_URL = "https://cve.mitre.org/data/downloads/allitems.csv"
49
+
50
+ # Diretório para armazenar dados locais
51
+ DATA_DIR = Path.home() / ".moriarty" / "data"
52
+ SERVICES_DB = DATA_DIR / "services.yml"
53
+ VULN_DB = DATA_DIR / "vulnerabilities.yml"
54
+
55
+ # Garante que o diretório de dados existe
56
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
57
+
58
+ # Estrutura para armazenar assinaturas de serviços
59
+ @dataclass
60
+ class ServiceSignature:
61
+ name: str
62
+ port: int
63
+ protocol: str = "tcp"
64
+ banner_patterns: List[str] = field(default_factory=list)
65
+ ssl_ports: Set[int] = field(default_factory=set)
66
+ version_pattern: Optional[str] = None
67
+ cpe: Optional[str] = None
68
+ vulns: List[Dict[str, str]] = field(default_factory=list)
69
+ last_updated: Optional[datetime] = None
70
+
71
+ # Dicionário para armazenar assinaturas de serviços
72
+ SERVICE_SIGNATURES: Dict[str, ServiceSignature] = {}
73
+
40
74
  # Mapeamento de portas para serviços comuns
41
75
  SERVICE_MAP = {
42
76
  21: "FTP",
@@ -117,9 +151,10 @@ SERVICE_MAP = {
117
151
  27018: "MongoDB",
118
152
  27019: "MongoDB",
119
153
  28017: "MongoDB",
120
- 32608: "Kubernetes",
154
+ 32608: "Kubernetes"
121
155
  }
122
156
 
157
+
123
158
  # Vulnerabilidades comuns por serviço
124
159
  VULNERABILITIES = {
125
160
  "SSH": ["CVE-2016-0777", "CVE-2016-0778", "CVE-2018-15473"],
@@ -147,9 +182,25 @@ class ServiceInfo:
147
182
  ssl: bool = False
148
183
  ssl_info: Optional[Dict[str, Any]] = None
149
184
  banner: Optional[str] = None
150
- vulns: List[str] = field(default_factory=list)
185
+ vulns: List[Dict[str, str]] = field(default_factory=list)
151
186
  cpe: Optional[str] = None
152
187
  extra: Dict[str, Any] = field(default_factory=dict)
188
+ confidence: float = 0.0 # Nível de confiança na identificação (0.0 a 1.0)
189
+ last_checked: Optional[datetime] = None
190
+
191
+ def to_dict(self) -> Dict[str, Any]:
192
+ """Converte o objeto para dicionário."""
193
+ return {
194
+ "name": self.name,
195
+ "version": self.version,
196
+ "ssl": self.ssl,
197
+ "ssl_info": self.ssl_info,
198
+ "banner": self.banner,
199
+ "vulns": self.vulns,
200
+ "cpe": self.cpe,
201
+ "confidence": self.confidence,
202
+ "last_checked": self.last_checked.isoformat() if self.last_checked else None
203
+ }
153
204
 
154
205
  @dataclass
155
206
  class PortScanResult:
@@ -299,14 +350,32 @@ class PortScanner:
299
350
  # Tenta obter o banner do serviço
300
351
  try:
301
352
  # Configura timeout para leitura
302
- read_timeout = max(0.5, self.timeout - 0.5)
353
+ read_timeout = max(1.0, self.timeout - 1.0)
354
+
355
+ # Envia uma requisição específica baseada no serviço comum da porta
356
+ banner_bytes = b""
357
+ if port in [80, 8080, 8000, 8008, 8081, 8443, 443]:
358
+ # HTTP/HTTPS - envia um HEAD / HTTP/1.0
359
+ writer.write(b"HEAD / HTTP/1.0\r\nHost: " + self.target.encode() + b"\r\n\r\n")
360
+ elif port == 21:
361
+ # FTP - envia um comando USER anonymous
362
+ writer.write(b"USER anonymous\r\n")
363
+ elif port == 22:
364
+ # SSH - apenas lê a versão do servidor
365
+ pass
366
+ elif port == 25 or port == 587 or port == 465:
367
+ # SMTP - envia EHLO
368
+ writer.write(b"EHLO moriarty-scanner\r\n")
369
+ elif port == 53:
370
+ # DNS - envia uma query DNS padrão
371
+ query = b'\x00\x01\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x07version\x04bind\x00\x00\x10\x00\x03'
372
+ writer.write(query)
303
373
 
304
- # Lê o banner (se houver)
305
- writer.write(b"\r\n\r\n")
306
374
  await writer.drain()
307
375
 
308
376
  # Lê até 1024 bytes
309
377
  banner_bytes = await asyncio.wait_for(reader.read(1024), timeout=read_timeout)
378
+
310
379
  if banner_bytes:
311
380
  # Tenta decodificar como texto
312
381
  try:
@@ -320,6 +389,14 @@ class PortScanner:
320
389
  except UnicodeDecodeError:
321
390
  # Se não for texto, mostra como hexdump
322
391
  result.banner = banner_bytes.hex(' ', 1)
392
+ else:
393
+ # Se não recebeu banner, verifica se a porta é conhecida
394
+ if port in SERVICE_MAP:
395
+ result.service = ServiceInfo(name=SERVICE_MAP[port])
396
+ else:
397
+ # Se não recebeu resposta, marca como filtrada
398
+ result.status = "filtered"
399
+ return result
323
400
  except (asyncio.TimeoutError, ConnectionResetError, OSError):
324
401
  # Ignora erros de leitura do banner
325
402
  pass
@@ -341,10 +418,15 @@ class PortScanner:
341
418
  # Se não identificou o serviço, tenta pelo número da porta
342
419
  if not result.service and port in SERVICE_MAP:
343
420
  result.service = ServiceInfo(name=SERVICE_MAP[port])
421
+
422
+ # Se ainda não identificou o serviço e não recebeu banner, marca como filtrada
423
+ if not result.service and not result.banner:
424
+ result.status = "filtered"
425
+ return result
344
426
 
345
- # Verifica vulnerabilidades conhecidas
346
- if self.check_vulns:
347
- result.service.vulns = self._check_known_vulns(port, result.service.name)
427
+ # Verifica vulnerabilidades conhecidas para portas abertas
428
+ if result.status == "open" and self.check_vulns and result.service:
429
+ result.service.vulns = self._check_known_vulns(port, result.service.name)
348
430
 
349
431
  return result
350
432
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moriarty-project
3
- Version: 0.1.24
3
+ Version: 0.1.25
4
4
  Summary: Client-side OSINT toolkit with forensic-grade evidence handling.
5
5
  Project-URL: Homepage, https://github.com/DonatoReis/moriarty
6
6
  Project-URL: Documentation, https://github.com/DonatoReis/moriarty#readme
@@ -98,7 +98,7 @@ Description-Content-Type: text/markdown
98
98
  <!-- Badges -->
99
99
  <p align="center">
100
100
  <a href="https://pypi.org/project/moriarty-project/">
101
- <img src="https://img.shields.io/badge/version-0.1.24-blue" alt="Version 0.1.24">
101
+ <img src="https://img.shields.io/badge/version-0.1.23-blue" alt="Version 0.1.23">
102
102
  </a>
103
103
  <a href="https://www.python.org/downloads/">
104
104
  <img src="https://img.shields.io/pypi/pyversions/moriarty-project?color=blue" alt="Python Versions">
@@ -152,7 +152,7 @@ Description-Content-Type: text/markdown
152
152
  pipx install moriarty-project
153
153
 
154
154
  # OU para instalar uma versão específica
155
- # pipx install moriarty-project==0.1.24
155
+ # pipx install moriarty-project==0.1.23
156
156
 
157
157
  # Verificar a instalação
158
158
  moriarty --help
@@ -1,4 +1,4 @@
1
- moriarty/__init__.py,sha256=p4Djdhmv6FeCw-z_OFHcm4SkmafU1L00Iny0SkEY3Kk,85
1
+ moriarty/__init__.py,sha256=6gfNgVpti1BJIBlPYh_ygBNbEQ7CuvrDMFT3oL7q6UA,85
2
2
  moriarty/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  moriarty/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  moriarty/assets/modules/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -386,7 +386,7 @@ moriarty/modules/orchestrator.py,sha256=uhK4UP69uWUxCK4a_bGk_BI8I-coBM8mO8Ear3pc
386
386
  moriarty/modules/passive_recon.py,sha256=5XUJgyWvITMUf4W76QyNfbRgF1AitQ5xK9MbwzVURxM,16568
387
387
  moriarty/modules/phone_extractor.py,sha256=Bv4VVWPqf67CQfkMDJddggtEU5UUbra2FP5DLik2Gxw,5298
388
388
  moriarty/modules/pipeline_orchestrator.py,sha256=qP2WcvorM_pAjacJ8VuZ-1TQ7lDVLvnyFD9T4PvWq9I,26337
389
- moriarty/modules/port_scanner.py,sha256=FNExysXgxHU-z77yYIRL2om7C23WkiF-AMliPjSmQhQ,33432
389
+ moriarty/modules/port_scanner.py,sha256=eyrtmJ4z5-IyOizbDODeQWTNI9Z0DnlHcWEPH3ckp3Q,36913
390
390
  moriarty/modules/rdap.py,sha256=XlrTDalbSxszEwIQFHt-XWON_P9UsLLiR84DGSKAwrk,1859
391
391
  moriarty/modules/rdap_extended.py,sha256=Gef7zyOY5nuS2qn8a9iaXA7Tx3TJHZJBWpqa-BZaq4U,6447
392
392
  moriarty/modules/stealth_mode.py,sha256=9LJWXSgBjDsTZYslHz4zSnzDoC3JFdBcu3oOYN1IPhA,24459
@@ -413,7 +413,7 @@ moriarty/tests/test_email_service.py,sha256=mWqimjQRlljZNBuNePvSzhfq5FZ4mljrILGW
413
413
  moriarty/tests/test_models.py,sha256=etklIISEUts3banaSRDSjhv-g6kd4wxucchCmlJkx6Y,1282
414
414
  moriarty/tests/test_orchestrator.py,sha256=Do3M1qnbqPf_1pR3v89FXxhiwfYPZfXRvcfl05isQvs,856
415
415
  moriarty/tests/test_tls_client.py,sha256=bQ46yXlIYNZwPTd8WGs6eUynHj56hVosxBycSU1gJe4,461
416
- moriarty_project-0.1.24.dist-info/METADATA,sha256=y2VGfhCSIvtkV5IfEcieRpC4sMLhSRRlEJjsasUJ_gw,11709
417
- moriarty_project-0.1.24.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
418
- moriarty_project-0.1.24.dist-info/entry_points.txt,sha256=L4TAUKy7HAy5hT46ZqS6eNOCmUTMi4x7ehZkIkTNnuE,51
419
- moriarty_project-0.1.24.dist-info/RECORD,,
416
+ moriarty_project-0.1.25.dist-info/METADATA,sha256=JCScdJfoDJl7lQRQv23CQl_UkFXeqRUspQFl2OIIA0k,11709
417
+ moriarty_project-0.1.25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
418
+ moriarty_project-0.1.25.dist-info/entry_points.txt,sha256=L4TAUKy7HAy5hT46ZqS6eNOCmUTMi4x7ehZkIkTNnuE,51
419
+ moriarty_project-0.1.25.dist-info/RECORD,,