souleyez 2.43.26__py3-none-any.whl → 2.43.34__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.
Potentially problematic release.
This version of souleyez might be problematic. Click here for more details.
- souleyez/__init__.py +1 -2
- souleyez/ai/__init__.py +21 -15
- souleyez/ai/action_mapper.py +249 -150
- souleyez/ai/chain_advisor.py +116 -100
- souleyez/ai/claude_provider.py +29 -28
- souleyez/ai/context_builder.py +80 -62
- souleyez/ai/executor.py +158 -117
- souleyez/ai/feedback_handler.py +136 -121
- souleyez/ai/llm_factory.py +27 -20
- souleyez/ai/llm_provider.py +4 -2
- souleyez/ai/ollama_provider.py +6 -9
- souleyez/ai/ollama_service.py +44 -37
- souleyez/ai/path_scorer.py +91 -76
- souleyez/ai/recommender.py +176 -144
- souleyez/ai/report_context.py +74 -73
- souleyez/ai/report_service.py +84 -66
- souleyez/ai/result_parser.py +222 -229
- souleyez/ai/safety.py +67 -44
- souleyez/auth/__init__.py +23 -22
- souleyez/auth/audit.py +36 -26
- souleyez/auth/engagement_access.py +65 -48
- souleyez/auth/permissions.py +14 -3
- souleyez/auth/session_manager.py +54 -37
- souleyez/auth/user_manager.py +109 -64
- souleyez/commands/audit.py +40 -43
- souleyez/commands/auth.py +35 -15
- souleyez/commands/deliverables.py +55 -50
- souleyez/commands/engagement.py +47 -28
- souleyez/commands/license.py +32 -23
- souleyez/commands/screenshots.py +36 -32
- souleyez/commands/user.py +82 -36
- souleyez/config.py +52 -44
- souleyez/core/credential_tester.py +87 -81
- souleyez/core/cve_mappings.py +179 -192
- souleyez/core/cve_matcher.py +162 -148
- souleyez/core/msf_auto_mapper.py +100 -83
- souleyez/core/msf_chain_engine.py +294 -256
- souleyez/core/msf_database.py +153 -70
- souleyez/core/msf_integration.py +679 -673
- souleyez/core/msf_rpc_client.py +40 -42
- souleyez/core/msf_rpc_manager.py +77 -79
- souleyez/core/msf_sync_manager.py +241 -181
- souleyez/core/network_utils.py +22 -15
- souleyez/core/parser_handler.py +34 -25
- souleyez/core/pending_chains.py +114 -63
- souleyez/core/templates.py +158 -107
- souleyez/core/tool_chaining.py +9526 -2879
- souleyez/core/version_utils.py +79 -94
- souleyez/core/vuln_correlation.py +136 -89
- souleyez/core/web_utils.py +33 -32
- souleyez/data/wordlists/ad_users.txt +378 -0
- souleyez/data/wordlists/api_endpoints_large.txt +769 -0
- souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
- souleyez/data/wordlists/lfi_payloads.txt +82 -0
- souleyez/data/wordlists/passwords_brute.txt +1548 -0
- souleyez/data/wordlists/passwords_crack.txt +2479 -0
- souleyez/data/wordlists/passwords_spray.txt +386 -0
- souleyez/data/wordlists/subdomains_large.txt +5057 -0
- souleyez/data/wordlists/usernames_common.txt +694 -0
- souleyez/data/wordlists/web_dirs_large.txt +4769 -0
- souleyez/detection/__init__.py +1 -1
- souleyez/detection/attack_signatures.py +12 -17
- souleyez/detection/mitre_mappings.py +61 -55
- souleyez/detection/validator.py +97 -86
- souleyez/devtools.py +23 -10
- souleyez/docs/README.md +4 -4
- souleyez/docs/api-reference/cli-commands.md +2 -2
- souleyez/docs/developer-guide/adding-new-tools.md +562 -0
- souleyez/docs/user-guide/auto-chaining.md +30 -8
- souleyez/docs/user-guide/getting-started.md +1 -1
- souleyez/docs/user-guide/installation.md +26 -3
- souleyez/docs/user-guide/metasploit-integration.md +2 -2
- souleyez/docs/user-guide/rbac.md +1 -1
- souleyez/docs/user-guide/scope-management.md +1 -1
- souleyez/docs/user-guide/siem-integration.md +1 -1
- souleyez/docs/user-guide/tools-reference.md +1 -8
- souleyez/docs/user-guide/worker-management.md +1 -1
- souleyez/engine/background.py +1239 -535
- souleyez/engine/base.py +4 -1
- souleyez/engine/job_status.py +17 -49
- souleyez/engine/log_sanitizer.py +103 -77
- souleyez/engine/manager.py +38 -7
- souleyez/engine/result_handler.py +2200 -1550
- souleyez/engine/worker_manager.py +50 -41
- souleyez/export/evidence_bundle.py +72 -62
- souleyez/feature_flags/features.py +16 -20
- souleyez/feature_flags.py +5 -9
- souleyez/handlers/__init__.py +11 -0
- souleyez/handlers/base.py +188 -0
- souleyez/handlers/bash_handler.py +277 -0
- souleyez/handlers/bloodhound_handler.py +243 -0
- souleyez/handlers/certipy_handler.py +311 -0
- souleyez/handlers/crackmapexec_handler.py +486 -0
- souleyez/handlers/dnsrecon_handler.py +344 -0
- souleyez/handlers/enum4linux_handler.py +400 -0
- souleyez/handlers/evil_winrm_handler.py +493 -0
- souleyez/handlers/ffuf_handler.py +815 -0
- souleyez/handlers/gobuster_handler.py +1114 -0
- souleyez/handlers/gpp_extract_handler.py +334 -0
- souleyez/handlers/hashcat_handler.py +444 -0
- souleyez/handlers/hydra_handler.py +563 -0
- souleyez/handlers/impacket_getuserspns_handler.py +343 -0
- souleyez/handlers/impacket_psexec_handler.py +222 -0
- souleyez/handlers/impacket_secretsdump_handler.py +426 -0
- souleyez/handlers/john_handler.py +286 -0
- souleyez/handlers/katana_handler.py +425 -0
- souleyez/handlers/kerbrute_handler.py +298 -0
- souleyez/handlers/ldapsearch_handler.py +636 -0
- souleyez/handlers/lfi_extract_handler.py +464 -0
- souleyez/handlers/msf_auxiliary_handler.py +408 -0
- souleyez/handlers/msf_exploit_handler.py +380 -0
- souleyez/handlers/nikto_handler.py +413 -0
- souleyez/handlers/nmap_handler.py +821 -0
- souleyez/handlers/nuclei_handler.py +359 -0
- souleyez/handlers/nxc_handler.py +371 -0
- souleyez/handlers/rdp_sec_check_handler.py +353 -0
- souleyez/handlers/registry.py +292 -0
- souleyez/handlers/responder_handler.py +232 -0
- souleyez/handlers/service_explorer_handler.py +434 -0
- souleyez/handlers/smbclient_handler.py +344 -0
- souleyez/handlers/smbmap_handler.py +510 -0
- souleyez/handlers/smbpasswd_handler.py +296 -0
- souleyez/handlers/sqlmap_handler.py +1116 -0
- souleyez/handlers/theharvester_handler.py +601 -0
- souleyez/handlers/web_login_test_handler.py +327 -0
- souleyez/handlers/whois_handler.py +277 -0
- souleyez/handlers/wpscan_handler.py +554 -0
- souleyez/history.py +32 -16
- souleyez/importers/msf_importer.py +106 -75
- souleyez/importers/smart_importer.py +208 -147
- souleyez/integrations/siem/__init__.py +10 -10
- souleyez/integrations/siem/base.py +17 -18
- souleyez/integrations/siem/elastic.py +108 -122
- souleyez/integrations/siem/factory.py +207 -80
- souleyez/integrations/siem/googlesecops.py +146 -154
- souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
- souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
- souleyez/integrations/siem/sentinel.py +107 -109
- souleyez/integrations/siem/splunk.py +246 -212
- souleyez/integrations/siem/wazuh.py +65 -71
- souleyez/integrations/wazuh/__init__.py +5 -5
- souleyez/integrations/wazuh/client.py +70 -93
- souleyez/integrations/wazuh/config.py +85 -57
- souleyez/integrations/wazuh/host_mapper.py +28 -36
- souleyez/integrations/wazuh/sync.py +78 -68
- souleyez/intelligence/__init__.py +4 -5
- souleyez/intelligence/correlation_analyzer.py +309 -295
- souleyez/intelligence/exploit_knowledge.py +661 -623
- souleyez/intelligence/exploit_suggestions.py +159 -139
- souleyez/intelligence/gap_analyzer.py +132 -97
- souleyez/intelligence/gap_detector.py +251 -214
- souleyez/intelligence/sensitive_tables.py +266 -129
- souleyez/intelligence/service_parser.py +137 -123
- souleyez/intelligence/surface_analyzer.py +407 -268
- souleyez/intelligence/target_parser.py +159 -162
- souleyez/licensing/__init__.py +6 -6
- souleyez/licensing/validator.py +17 -19
- souleyez/log_config.py +79 -54
- souleyez/main.py +1505 -687
- souleyez/migrations/fix_job_counter.py +16 -14
- souleyez/parsers/bloodhound_parser.py +41 -39
- souleyez/parsers/crackmapexec_parser.py +178 -111
- souleyez/parsers/dalfox_parser.py +72 -77
- souleyez/parsers/dnsrecon_parser.py +103 -91
- souleyez/parsers/enum4linux_parser.py +183 -153
- souleyez/parsers/ffuf_parser.py +29 -25
- souleyez/parsers/gobuster_parser.py +301 -41
- souleyez/parsers/hashcat_parser.py +324 -79
- souleyez/parsers/http_fingerprint_parser.py +350 -103
- souleyez/parsers/hydra_parser.py +131 -111
- souleyez/parsers/impacket_parser.py +231 -178
- souleyez/parsers/john_parser.py +98 -86
- souleyez/parsers/katana_parser.py +316 -0
- souleyez/parsers/msf_parser.py +943 -498
- souleyez/parsers/nikto_parser.py +346 -65
- souleyez/parsers/nmap_parser.py +262 -174
- souleyez/parsers/nuclei_parser.py +40 -44
- souleyez/parsers/responder_parser.py +26 -26
- souleyez/parsers/searchsploit_parser.py +74 -74
- souleyez/parsers/service_explorer_parser.py +279 -0
- souleyez/parsers/smbmap_parser.py +180 -124
- souleyez/parsers/sqlmap_parser.py +434 -308
- souleyez/parsers/theharvester_parser.py +75 -57
- souleyez/parsers/whois_parser.py +135 -94
- souleyez/parsers/wpscan_parser.py +278 -190
- souleyez/plugins/afp.py +44 -36
- souleyez/plugins/afp_brute.py +114 -46
- souleyez/plugins/ard.py +48 -37
- souleyez/plugins/bloodhound.py +95 -61
- souleyez/plugins/certipy.py +303 -0
- souleyez/plugins/crackmapexec.py +186 -85
- souleyez/plugins/dalfox.py +120 -59
- souleyez/plugins/dns_hijack.py +146 -41
- souleyez/plugins/dnsrecon.py +97 -61
- souleyez/plugins/enum4linux.py +91 -66
- souleyez/plugins/evil_winrm.py +291 -0
- souleyez/plugins/ffuf.py +166 -90
- souleyez/plugins/firmware_extract.py +133 -29
- souleyez/plugins/gobuster.py +387 -190
- souleyez/plugins/gpp_extract.py +393 -0
- souleyez/plugins/hashcat.py +100 -73
- souleyez/plugins/http_fingerprint.py +854 -267
- souleyez/plugins/hydra.py +566 -200
- souleyez/plugins/impacket_getnpusers.py +117 -69
- souleyez/plugins/impacket_psexec.py +84 -64
- souleyez/plugins/impacket_secretsdump.py +103 -69
- souleyez/plugins/impacket_smbclient.py +89 -75
- souleyez/plugins/john.py +86 -69
- souleyez/plugins/katana.py +313 -0
- souleyez/plugins/kerbrute.py +237 -0
- souleyez/plugins/lfi_extract.py +541 -0
- souleyez/plugins/macos_ssh.py +117 -48
- souleyez/plugins/mdns.py +35 -30
- souleyez/plugins/msf_auxiliary.py +253 -130
- souleyez/plugins/msf_exploit.py +239 -161
- souleyez/plugins/nikto.py +134 -78
- souleyez/plugins/nmap.py +275 -91
- souleyez/plugins/nuclei.py +180 -89
- souleyez/plugins/nxc.py +285 -0
- souleyez/plugins/plugin_base.py +35 -36
- souleyez/plugins/plugin_template.py +13 -5
- souleyez/plugins/rdp_sec_check.py +130 -0
- souleyez/plugins/responder.py +112 -71
- souleyez/plugins/router_http_brute.py +76 -65
- souleyez/plugins/router_ssh_brute.py +118 -41
- souleyez/plugins/router_telnet_brute.py +124 -42
- souleyez/plugins/routersploit.py +91 -59
- souleyez/plugins/routersploit_exploit.py +77 -55
- souleyez/plugins/searchsploit.py +91 -77
- souleyez/plugins/service_explorer.py +1160 -0
- souleyez/plugins/smbmap.py +122 -72
- souleyez/plugins/smbpasswd.py +215 -0
- souleyez/plugins/sqlmap.py +301 -113
- souleyez/plugins/theharvester.py +127 -75
- souleyez/plugins/tr069.py +79 -57
- souleyez/plugins/upnp.py +65 -47
- souleyez/plugins/upnp_abuse.py +73 -55
- souleyez/plugins/vnc_access.py +129 -42
- souleyez/plugins/vnc_brute.py +109 -38
- souleyez/plugins/web_login_test.py +417 -0
- souleyez/plugins/whois.py +77 -58
- souleyez/plugins/wpscan.py +173 -69
- souleyez/reporting/__init__.py +2 -1
- souleyez/reporting/attack_chain.py +411 -346
- souleyez/reporting/charts.py +436 -501
- souleyez/reporting/compliance_mappings.py +334 -201
- souleyez/reporting/detection_report.py +126 -125
- souleyez/reporting/formatters.py +828 -591
- souleyez/reporting/generator.py +386 -302
- souleyez/reporting/metrics.py +72 -75
- souleyez/scanner.py +35 -29
- souleyez/security/__init__.py +37 -11
- souleyez/security/scope_validator.py +175 -106
- souleyez/security/validation.py +223 -149
- souleyez/security.py +22 -6
- souleyez/storage/credentials.py +247 -186
- souleyez/storage/crypto.py +296 -129
- souleyez/storage/database.py +73 -50
- souleyez/storage/db.py +58 -36
- souleyez/storage/deliverable_evidence.py +177 -128
- souleyez/storage/deliverable_exporter.py +282 -246
- souleyez/storage/deliverable_templates.py +134 -116
- souleyez/storage/deliverables.py +135 -130
- souleyez/storage/engagements.py +109 -56
- souleyez/storage/evidence.py +181 -152
- souleyez/storage/execution_log.py +31 -17
- souleyez/storage/exploit_attempts.py +93 -57
- souleyez/storage/exploits.py +67 -36
- souleyez/storage/findings.py +48 -61
- souleyez/storage/hosts.py +176 -144
- souleyez/storage/migrate_to_engagements.py +43 -19
- souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
- souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
- souleyez/storage/migrations/_003_add_execution_log.py +14 -8
- souleyez/storage/migrations/_005_screenshots.py +13 -5
- souleyez/storage/migrations/_006_deliverables.py +13 -5
- souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
- souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
- souleyez/storage/migrations/_010_evidence_linking.py +17 -10
- souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
- souleyez/storage/migrations/_012_team_collaboration.py +34 -21
- souleyez/storage/migrations/_013_add_host_tags.py +12 -6
- souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
- souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
- souleyez/storage/migrations/_016_add_domain_field.py +10 -4
- souleyez/storage/migrations/_017_msf_sessions.py +16 -8
- souleyez/storage/migrations/_018_add_osint_target.py +10 -6
- souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
- souleyez/storage/migrations/_020_add_rbac.py +36 -15
- souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
- souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
- souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
- souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
- souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
- souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
- souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
- souleyez/storage/migrations/__init__.py +26 -26
- souleyez/storage/migrations/migration_manager.py +19 -19
- souleyez/storage/msf_sessions.py +100 -65
- souleyez/storage/osint.py +17 -24
- souleyez/storage/recommendation_engine.py +269 -235
- souleyez/storage/screenshots.py +33 -32
- souleyez/storage/smb_shares.py +136 -92
- souleyez/storage/sqlmap_data.py +183 -128
- souleyez/storage/team_collaboration.py +135 -141
- souleyez/storage/timeline_tracker.py +122 -94
- souleyez/storage/wazuh_vulns.py +64 -66
- souleyez/storage/web_paths.py +33 -37
- souleyez/testing/credential_tester.py +221 -205
- souleyez/ui/__init__.py +1 -1
- souleyez/ui/ai_quotes.py +12 -12
- souleyez/ui/attack_surface.py +2439 -1516
- souleyez/ui/chain_rules_view.py +914 -382
- souleyez/ui/correlation_view.py +312 -230
- souleyez/ui/dashboard.py +2382 -1130
- souleyez/ui/deliverables_view.py +148 -62
- souleyez/ui/design_system.py +13 -13
- souleyez/ui/errors.py +49 -49
- souleyez/ui/evidence_linking_view.py +284 -179
- souleyez/ui/evidence_vault.py +393 -285
- souleyez/ui/exploit_suggestions_view.py +555 -349
- souleyez/ui/export_view.py +100 -66
- souleyez/ui/gap_analysis_view.py +315 -171
- souleyez/ui/help_system.py +105 -97
- souleyez/ui/intelligence_view.py +436 -293
- souleyez/ui/interactive.py +23434 -10286
- souleyez/ui/interactive_selector.py +75 -68
- souleyez/ui/log_formatter.py +47 -39
- souleyez/ui/menu_components.py +22 -13
- souleyez/ui/msf_auxiliary_menu.py +184 -133
- souleyez/ui/pending_chains_view.py +336 -172
- souleyez/ui/progress_indicators.py +5 -3
- souleyez/ui/recommendations_view.py +195 -137
- souleyez/ui/rule_builder.py +343 -225
- souleyez/ui/setup_wizard.py +678 -284
- souleyez/ui/shortcuts.py +217 -165
- souleyez/ui/splunk_gap_analysis_view.py +452 -270
- souleyez/ui/splunk_vulns_view.py +139 -86
- souleyez/ui/team_dashboard.py +498 -335
- souleyez/ui/template_selector.py +196 -105
- souleyez/ui/terminal.py +6 -6
- souleyez/ui/timeline_view.py +198 -127
- souleyez/ui/tool_setup.py +264 -164
- souleyez/ui/tutorial.py +202 -72
- souleyez/ui/tutorial_state.py +40 -40
- souleyez/ui/wazuh_vulns_view.py +235 -141
- souleyez/ui/wordlist_browser.py +260 -107
- souleyez/ui.py +464 -312
- souleyez/utils/tool_checker.py +427 -367
- souleyez/utils.py +33 -29
- souleyez/wordlists.py +134 -167
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
- souleyez-2.43.34.dist-info/RECORD +443 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
- souleyez-2.43.26.dist-info/RECORD +0 -379
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Impacket secretsdump handler.
|
|
4
|
+
|
|
5
|
+
Consolidates parsing and display logic for Impacket secretsdump credential extraction jobs.
|
|
6
|
+
"""
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
from typing import Any, Dict, Optional
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from souleyez.engine.job_status import STATUS_DONE, STATUS_NO_RESULTS
|
|
15
|
+
from souleyez.handlers.base import BaseToolHandler
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ImpacketSecretsdumpHandler(BaseToolHandler):
|
|
21
|
+
"""Handler for Impacket secretsdump credential extraction jobs."""
|
|
22
|
+
|
|
23
|
+
tool_name = "impacket-secretsdump" # Match the actual tool name with hyphen
|
|
24
|
+
display_name = "Secretsdump"
|
|
25
|
+
|
|
26
|
+
# All handlers enabled
|
|
27
|
+
has_error_handler = True
|
|
28
|
+
has_warning_handler = True
|
|
29
|
+
has_no_results_handler = True
|
|
30
|
+
has_done_handler = True
|
|
31
|
+
|
|
32
|
+
def parse_job(
|
|
33
|
+
self,
|
|
34
|
+
engagement_id: int,
|
|
35
|
+
log_path: str,
|
|
36
|
+
job: Dict[str, Any],
|
|
37
|
+
host_manager: Optional[Any] = None,
|
|
38
|
+
findings_manager: Optional[Any] = None,
|
|
39
|
+
credentials_manager: Optional[Any] = None,
|
|
40
|
+
) -> Dict[str, Any]:
|
|
41
|
+
"""
|
|
42
|
+
Parse secretsdump job results.
|
|
43
|
+
|
|
44
|
+
Extracts NTLM hashes, plaintext credentials, and Kerberos tickets.
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
from souleyez.parsers.impacket_parser import parse_secretsdump
|
|
48
|
+
|
|
49
|
+
# Import managers if not provided
|
|
50
|
+
if host_manager is None:
|
|
51
|
+
from souleyez.storage.hosts import HostManager
|
|
52
|
+
|
|
53
|
+
host_manager = HostManager()
|
|
54
|
+
if credentials_manager is None:
|
|
55
|
+
from souleyez.storage.credentials import CredentialsManager
|
|
56
|
+
|
|
57
|
+
credentials_manager = CredentialsManager()
|
|
58
|
+
|
|
59
|
+
target = job.get("target", "")
|
|
60
|
+
parsed = parse_secretsdump(log_path, target)
|
|
61
|
+
|
|
62
|
+
if "error" in parsed:
|
|
63
|
+
return parsed
|
|
64
|
+
|
|
65
|
+
# Get or create host
|
|
66
|
+
host_id = None
|
|
67
|
+
ip_match = re.search(r"@?(\d+\.\d+\.\d+\.\d+)", target)
|
|
68
|
+
if ip_match:
|
|
69
|
+
host_ip = ip_match.group(1)
|
|
70
|
+
host_id = host_manager.add_or_update_host(
|
|
71
|
+
engagement_id, {"ip": host_ip, "status": "up"}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
creds_added = 0
|
|
75
|
+
hashes_added = 0
|
|
76
|
+
|
|
77
|
+
# Store plaintext credentials
|
|
78
|
+
for cred in parsed.get("credentials", []):
|
|
79
|
+
try:
|
|
80
|
+
credentials_manager.add_credential(
|
|
81
|
+
engagement_id=engagement_id,
|
|
82
|
+
host_id=host_id,
|
|
83
|
+
username=cred.get("username"),
|
|
84
|
+
password=cred.get("password"),
|
|
85
|
+
service="windows",
|
|
86
|
+
status="valid",
|
|
87
|
+
credential_type="password",
|
|
88
|
+
tool="impacket_secretsdump",
|
|
89
|
+
domain=cred.get("domain"),
|
|
90
|
+
)
|
|
91
|
+
creds_added += 1
|
|
92
|
+
except Exception:
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
# Store NTLM hashes
|
|
96
|
+
for hash_data in parsed.get("hashes", []):
|
|
97
|
+
try:
|
|
98
|
+
credentials_manager.add_credential(
|
|
99
|
+
engagement_id=engagement_id,
|
|
100
|
+
host_id=host_id,
|
|
101
|
+
username=hash_data.get("username"),
|
|
102
|
+
password=hash_data.get("nt_hash"),
|
|
103
|
+
service="windows",
|
|
104
|
+
status="valid",
|
|
105
|
+
credential_type="hash",
|
|
106
|
+
tool="impacket_secretsdump",
|
|
107
|
+
notes=f"RID: {hash_data.get('rid')}, LM: {hash_data.get('lm_hash')}",
|
|
108
|
+
)
|
|
109
|
+
hashes_added += 1
|
|
110
|
+
except Exception:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
"tool": "impacket_secretsdump",
|
|
115
|
+
"status": (
|
|
116
|
+
STATUS_DONE
|
|
117
|
+
if (creds_added > 0 or hashes_added > 0)
|
|
118
|
+
else STATUS_NO_RESULTS
|
|
119
|
+
),
|
|
120
|
+
"target": target,
|
|
121
|
+
"credentials_added": creds_added,
|
|
122
|
+
"hashes_added": hashes_added,
|
|
123
|
+
"hashes_count": parsed.get("hashes_count", 0),
|
|
124
|
+
"credentials_count": parsed.get("credentials_count", 0),
|
|
125
|
+
"tickets_count": parsed.get("tickets_count", 0),
|
|
126
|
+
"hashes": parsed.get("hashes", []), # For chaining to hashcat
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
except Exception as e:
|
|
130
|
+
logger.error(f"Error parsing secretsdump job: {e}")
|
|
131
|
+
return {"error": str(e)}
|
|
132
|
+
|
|
133
|
+
def display_done(
|
|
134
|
+
self,
|
|
135
|
+
job: Dict[str, Any],
|
|
136
|
+
log_path: str,
|
|
137
|
+
show_all: bool = False,
|
|
138
|
+
show_passwords: bool = False,
|
|
139
|
+
) -> None:
|
|
140
|
+
"""Display successful secretsdump results."""
|
|
141
|
+
try:
|
|
142
|
+
from souleyez.parsers.impacket_parser import parse_secretsdump
|
|
143
|
+
|
|
144
|
+
if not log_path or not os.path.exists(log_path):
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
target = job.get("target", "unknown")
|
|
148
|
+
parsed = parse_secretsdump(log_path, target)
|
|
149
|
+
|
|
150
|
+
hashes = parsed.get("hashes", [])
|
|
151
|
+
credentials = parsed.get("credentials", [])
|
|
152
|
+
tickets = parsed.get("tickets", [])
|
|
153
|
+
lsa_secrets = parsed.get("lsa_secrets", [])
|
|
154
|
+
kerberos_keys = parsed.get("kerberos_keys", [])
|
|
155
|
+
hashes_count = parsed.get("hashes_count", 0)
|
|
156
|
+
creds_count = parsed.get("credentials_count", 0)
|
|
157
|
+
tickets_count = parsed.get("tickets_count", 0)
|
|
158
|
+
|
|
159
|
+
if not (hashes or credentials or tickets or lsa_secrets or kerberos_keys):
|
|
160
|
+
self.display_no_results(job, log_path)
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
164
|
+
click.echo(
|
|
165
|
+
click.style("SECRETSDUMP - DOMAIN COMPROMISE!", bold=True, fg="green")
|
|
166
|
+
)
|
|
167
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
168
|
+
click.echo()
|
|
169
|
+
|
|
170
|
+
# Show summary
|
|
171
|
+
click.echo(click.style("Summary:", bold=True))
|
|
172
|
+
click.echo(f" NTLM Hashes: {hashes_count}")
|
|
173
|
+
click.echo(f" LSA Secrets: {len(lsa_secrets)}")
|
|
174
|
+
click.echo(f" Kerberos Keys: {len(kerberos_keys)}")
|
|
175
|
+
click.echo(f" Plaintext Creds: {creds_count}")
|
|
176
|
+
click.echo()
|
|
177
|
+
|
|
178
|
+
# Highlight critical accounts
|
|
179
|
+
critical_accounts = ["administrator", "krbtgt", "domain admins"]
|
|
180
|
+
critical_found = [
|
|
181
|
+
h
|
|
182
|
+
for h in hashes
|
|
183
|
+
if any(c in h.get("username", "").lower() for c in critical_accounts)
|
|
184
|
+
]
|
|
185
|
+
if critical_found:
|
|
186
|
+
click.echo(click.style("CRITICAL ACCOUNTS:", bold=True, fg="red"))
|
|
187
|
+
for h in critical_found:
|
|
188
|
+
username = h.get("username", "?")
|
|
189
|
+
nt_hash = (
|
|
190
|
+
h.get("nt_hash", "?")
|
|
191
|
+
if show_passwords
|
|
192
|
+
else h.get("nt_hash", "?")[:16] + "..."
|
|
193
|
+
)
|
|
194
|
+
click.echo(
|
|
195
|
+
click.style(f" {username}: {nt_hash}", fg="red", bold=True)
|
|
196
|
+
)
|
|
197
|
+
click.echo()
|
|
198
|
+
|
|
199
|
+
# Show LSA secrets (DefaultPassword, etc.)
|
|
200
|
+
if lsa_secrets:
|
|
201
|
+
click.echo(click.style("LSA Secrets:", bold=True, fg="magenta"))
|
|
202
|
+
for secret in lsa_secrets:
|
|
203
|
+
secret_type = secret.get("secret_type", "Unknown")
|
|
204
|
+
value = secret.get("value", "***") if show_passwords else "***"
|
|
205
|
+
click.echo(click.style(f" {secret_type}: {value}", fg="magenta"))
|
|
206
|
+
click.echo()
|
|
207
|
+
|
|
208
|
+
# Show hashes (limited)
|
|
209
|
+
if hashes:
|
|
210
|
+
click.echo(
|
|
211
|
+
click.style(f"NTLM Hashes ({len(hashes)}):", bold=True, fg="yellow")
|
|
212
|
+
)
|
|
213
|
+
max_show = None if show_all else 5
|
|
214
|
+
display_hashes = hashes if max_show is None else hashes[:max_show]
|
|
215
|
+
for h in display_hashes:
|
|
216
|
+
username = h.get("username", "?")
|
|
217
|
+
if show_passwords:
|
|
218
|
+
nt_hash = h.get("nt_hash", "?")
|
|
219
|
+
else:
|
|
220
|
+
nt_hash = (
|
|
221
|
+
h.get("nt_hash", "?")[:16] + "..."
|
|
222
|
+
if h.get("nt_hash")
|
|
223
|
+
else "?"
|
|
224
|
+
)
|
|
225
|
+
click.echo(f" {username}: {nt_hash}")
|
|
226
|
+
if max_show and len(hashes) > max_show:
|
|
227
|
+
click.echo(
|
|
228
|
+
click.style(
|
|
229
|
+
f" ... and {len(hashes) - max_show} more hashes", dim=True
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
click.echo()
|
|
233
|
+
|
|
234
|
+
# Show plaintext credentials
|
|
235
|
+
if credentials:
|
|
236
|
+
click.echo(
|
|
237
|
+
click.style(
|
|
238
|
+
f"Plaintext Credentials ({len(credentials)}):",
|
|
239
|
+
bold=True,
|
|
240
|
+
fg="green",
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
max_show = None if show_all else 5
|
|
244
|
+
display_creds = (
|
|
245
|
+
credentials if max_show is None else credentials[:max_show]
|
|
246
|
+
)
|
|
247
|
+
for c in display_creds:
|
|
248
|
+
domain = c.get("domain", "")
|
|
249
|
+
username = c.get("username", "?")
|
|
250
|
+
password = c.get("password", "?") if show_passwords else "***"
|
|
251
|
+
if domain:
|
|
252
|
+
click.echo(
|
|
253
|
+
click.style(
|
|
254
|
+
f" {domain}\\{username}:{password}", fg="green"
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
else:
|
|
258
|
+
click.echo(click.style(f" {username}:{password}", fg="green"))
|
|
259
|
+
if max_show and len(credentials) > max_show:
|
|
260
|
+
click.echo(
|
|
261
|
+
click.style(
|
|
262
|
+
f" ... and {len(credentials) - max_show} more", dim=True
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
click.echo()
|
|
266
|
+
|
|
267
|
+
# Show Kerberos keys (for golden ticket potential)
|
|
268
|
+
if kerberos_keys:
|
|
269
|
+
krbtgt_keys = [
|
|
270
|
+
k
|
|
271
|
+
for k in kerberos_keys
|
|
272
|
+
if "krbtgt" in k.get("username", "").lower()
|
|
273
|
+
]
|
|
274
|
+
if krbtgt_keys:
|
|
275
|
+
click.echo(
|
|
276
|
+
click.style(
|
|
277
|
+
"GOLDEN TICKET MATERIAL (krbtgt keys):", bold=True, fg="red"
|
|
278
|
+
)
|
|
279
|
+
)
|
|
280
|
+
for k in krbtgt_keys:
|
|
281
|
+
key_type = k.get("key_type", "?")
|
|
282
|
+
click.echo(click.style(f" {key_type}: [AVAILABLE]", fg="red"))
|
|
283
|
+
click.echo()
|
|
284
|
+
|
|
285
|
+
# Show Kerberos tickets
|
|
286
|
+
if tickets:
|
|
287
|
+
click.echo(
|
|
288
|
+
click.style(
|
|
289
|
+
f"Kerberos Tickets ({len(tickets)}):", bold=True, fg="cyan"
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
max_show = None if show_all else 3
|
|
293
|
+
display_tickets = tickets if max_show is None else tickets[:max_show]
|
|
294
|
+
for t in display_tickets:
|
|
295
|
+
username = t.get("username", "?")
|
|
296
|
+
ticket_type = t.get("ticket_type", "Kerberos")
|
|
297
|
+
click.echo(f" {username}: {ticket_type}")
|
|
298
|
+
if max_show and len(tickets) > max_show:
|
|
299
|
+
click.echo(
|
|
300
|
+
click.style(
|
|
301
|
+
f" ... and {len(tickets) - max_show} more tickets",
|
|
302
|
+
dim=True,
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
click.echo()
|
|
306
|
+
|
|
307
|
+
# Next steps
|
|
308
|
+
click.echo(click.style("Next Steps:", bold=True))
|
|
309
|
+
click.echo(" - Use hashes for Pass-the-Hash attacks")
|
|
310
|
+
click.echo(" - Crack hashes with hashcat -m 1000")
|
|
311
|
+
if any("krbtgt" in h.get("username", "").lower() for h in hashes):
|
|
312
|
+
click.echo(
|
|
313
|
+
click.style(" - Create Golden Tickets with krbtgt hash!", fg="red")
|
|
314
|
+
)
|
|
315
|
+
click.echo()
|
|
316
|
+
|
|
317
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
318
|
+
click.echo()
|
|
319
|
+
|
|
320
|
+
except Exception as e:
|
|
321
|
+
logger.debug(f"Error in display_done: {e}")
|
|
322
|
+
|
|
323
|
+
def display_warning(
|
|
324
|
+
self,
|
|
325
|
+
job: Dict[str, Any],
|
|
326
|
+
log_path: str,
|
|
327
|
+
log_content: Optional[str] = None,
|
|
328
|
+
) -> None:
|
|
329
|
+
"""Display warning status for secretsdump - but show results if we got them."""
|
|
330
|
+
# Check if we actually got results (should be treated as success)
|
|
331
|
+
if log_content is None and log_path and os.path.exists(log_path):
|
|
332
|
+
try:
|
|
333
|
+
with open(log_path, "r", encoding="utf-8", errors="replace") as f:
|
|
334
|
+
log_content = f.read()
|
|
335
|
+
except Exception:
|
|
336
|
+
log_content = ""
|
|
337
|
+
|
|
338
|
+
# If we have NTLM hashes, treat as success
|
|
339
|
+
if log_content and (
|
|
340
|
+
":::" in log_content or "Dumping Domain Credentials" in log_content
|
|
341
|
+
):
|
|
342
|
+
self.display_done(job, log_path)
|
|
343
|
+
return
|
|
344
|
+
|
|
345
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
346
|
+
click.echo(click.style("[WARNING] SECRETSDUMP", bold=True, fg="yellow"))
|
|
347
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
348
|
+
click.echo()
|
|
349
|
+
click.echo(" Credential dump completed with warnings.")
|
|
350
|
+
click.echo(" Check raw logs for details (press 'r').")
|
|
351
|
+
click.echo()
|
|
352
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
353
|
+
click.echo()
|
|
354
|
+
|
|
355
|
+
def display_error(
|
|
356
|
+
self,
|
|
357
|
+
job: Dict[str, Any],
|
|
358
|
+
log_path: str,
|
|
359
|
+
log_content: Optional[str] = None,
|
|
360
|
+
) -> None:
|
|
361
|
+
"""Display error status for secretsdump."""
|
|
362
|
+
# Read log if not provided
|
|
363
|
+
if log_content is None and log_path and os.path.exists(log_path):
|
|
364
|
+
try:
|
|
365
|
+
with open(log_path, "r", encoding="utf-8", errors="replace") as f:
|
|
366
|
+
log_content = f.read()
|
|
367
|
+
except Exception:
|
|
368
|
+
log_content = ""
|
|
369
|
+
|
|
370
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
371
|
+
click.echo(click.style("[ERROR] SECRETSDUMP FAILED", bold=True, fg="red"))
|
|
372
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
373
|
+
click.echo()
|
|
374
|
+
|
|
375
|
+
# Check for common secretsdump errors
|
|
376
|
+
error_msg = None
|
|
377
|
+
if log_content:
|
|
378
|
+
if "Connection refused" in log_content:
|
|
379
|
+
error_msg = "Connection refused - target SMB service may be down"
|
|
380
|
+
elif (
|
|
381
|
+
"Access denied" in log_content.lower()
|
|
382
|
+
or "STATUS_ACCESS_DENIED" in log_content
|
|
383
|
+
):
|
|
384
|
+
error_msg = "Access denied - insufficient privileges to dump secrets"
|
|
385
|
+
elif "STATUS_LOGON_FAILURE" in log_content:
|
|
386
|
+
error_msg = "Logon failure - invalid credentials"
|
|
387
|
+
elif "timed out" in log_content.lower() or "timeout" in log_content.lower():
|
|
388
|
+
error_msg = "Connection timed out - target may be unreachable"
|
|
389
|
+
elif "DRSUAPI method not supported" in log_content:
|
|
390
|
+
error_msg = (
|
|
391
|
+
"DRSUAPI not supported - may need different method (-use-vss)"
|
|
392
|
+
)
|
|
393
|
+
elif "Cannot reach" in log_content:
|
|
394
|
+
error_msg = "Cannot reach target - check network connectivity"
|
|
395
|
+
|
|
396
|
+
if error_msg:
|
|
397
|
+
click.echo(f" {error_msg}")
|
|
398
|
+
else:
|
|
399
|
+
click.echo(
|
|
400
|
+
" Credential dump failed - check raw logs for details (press 'r')"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
click.echo()
|
|
404
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
405
|
+
click.echo()
|
|
406
|
+
|
|
407
|
+
def display_no_results(
|
|
408
|
+
self,
|
|
409
|
+
job: Dict[str, Any],
|
|
410
|
+
log_path: str,
|
|
411
|
+
) -> None:
|
|
412
|
+
"""Display no_results status for secretsdump."""
|
|
413
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
414
|
+
click.echo(click.style("SECRETSDUMP RESULTS", bold=True, fg="yellow"))
|
|
415
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
416
|
+
click.echo()
|
|
417
|
+
click.echo(" No credentials or hashes were extracted.")
|
|
418
|
+
click.echo()
|
|
419
|
+
click.echo(click.style("Possible reasons:", dim=True))
|
|
420
|
+
click.echo(" - Target has no stored credentials")
|
|
421
|
+
click.echo(" - Insufficient privileges (need admin/SYSTEM)")
|
|
422
|
+
click.echo(" - SAM/NTDS database is protected or unavailable")
|
|
423
|
+
click.echo(" - Try -use-vss flag for VSS shadow copy extraction")
|
|
424
|
+
click.echo()
|
|
425
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
426
|
+
click.echo()
|