souleyez 2.43.29__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.
- 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 +22827 -10678
- 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.29.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
- souleyez-2.43.34.dist-info/RECORD +443 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
- souleyez-2.43.29.dist-info/RECORD +0 -379
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
souleyez/ui/rule_builder.py
CHANGED
|
@@ -7,17 +7,17 @@ from typing import Optional, Dict, List, Any
|
|
|
7
7
|
from souleyez.ui.design_system import DesignSystem
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def show_rule_builder(mode: str =
|
|
10
|
+
def show_rule_builder(mode: str = "simple") -> Optional[Dict[str, Any]]:
|
|
11
11
|
"""
|
|
12
12
|
Show chain rule builder interface.
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
Args:
|
|
15
15
|
mode: 'simple' or 'advanced'
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
Returns:
|
|
18
18
|
Dict with rule definition or None if cancelled
|
|
19
19
|
"""
|
|
20
|
-
if mode ==
|
|
20
|
+
if mode == "simple":
|
|
21
21
|
return _simple_mode_builder()
|
|
22
22
|
else:
|
|
23
23
|
return _advanced_mode_builder()
|
|
@@ -27,59 +27,65 @@ def _simple_mode_builder() -> Optional[Dict[str, Any]]:
|
|
|
27
27
|
"""Guided step-by-step rule builder (simple mode)."""
|
|
28
28
|
DesignSystem.clear_screen()
|
|
29
29
|
width = 60
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
32
|
-
click.echo(
|
|
32
|
+
click.echo(
|
|
33
|
+
"│"
|
|
34
|
+
+ click.style(" CREATE CHAIN RULE ".center(width - 2), bold=True, fg="cyan")
|
|
35
|
+
+ "│"
|
|
36
|
+
)
|
|
33
37
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
34
38
|
click.echo()
|
|
35
|
-
click.echo(
|
|
39
|
+
click.echo(
|
|
40
|
+
" " + click.style("Simple Mode", fg="yellow") + " - Guided step-by-step"
|
|
41
|
+
)
|
|
36
42
|
click.echo(" Press 'q' at any step to cancel")
|
|
37
43
|
click.echo()
|
|
38
|
-
|
|
44
|
+
|
|
39
45
|
try:
|
|
40
46
|
# Step 1: Select trigger tool
|
|
41
47
|
trigger_tool = _select_trigger_tool()
|
|
42
48
|
if not trigger_tool:
|
|
43
49
|
return None
|
|
44
|
-
|
|
50
|
+
|
|
45
51
|
# Step 2: Select condition
|
|
46
52
|
condition = _select_condition_simple(trigger_tool)
|
|
47
53
|
if not condition:
|
|
48
54
|
return None
|
|
49
|
-
|
|
55
|
+
|
|
50
56
|
# Step 3: Select target tool
|
|
51
57
|
target_tool = _select_target_tool()
|
|
52
58
|
if not target_tool:
|
|
53
59
|
return None
|
|
54
|
-
|
|
60
|
+
|
|
55
61
|
# Step 4: Select args template
|
|
56
62
|
args_template = _select_args_template(target_tool)
|
|
57
|
-
|
|
63
|
+
|
|
58
64
|
# Step 5: Rule settings
|
|
59
65
|
rule_settings = _configure_rule_settings()
|
|
60
66
|
if not rule_settings:
|
|
61
67
|
return None
|
|
62
|
-
|
|
68
|
+
|
|
63
69
|
# Build rule
|
|
64
70
|
rule = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
"trigger_tool": trigger_tool,
|
|
72
|
+
"condition": condition,
|
|
73
|
+
"target_tool": target_tool,
|
|
74
|
+
"args": args_template,
|
|
75
|
+
"priority": rule_settings["priority"],
|
|
76
|
+
"category": rule_settings["category"],
|
|
77
|
+
"enabled": rule_settings["enabled"],
|
|
78
|
+
"description": rule_settings.get("description", ""),
|
|
73
79
|
}
|
|
74
|
-
|
|
80
|
+
|
|
75
81
|
# Show summary and confirm
|
|
76
82
|
if _confirm_rule(rule):
|
|
77
83
|
return rule
|
|
78
|
-
|
|
84
|
+
|
|
79
85
|
return None
|
|
80
|
-
|
|
86
|
+
|
|
81
87
|
except (KeyboardInterrupt, click.Abort):
|
|
82
|
-
click.echo(click.style("\n Rule creation cancelled", fg=
|
|
88
|
+
click.echo(click.style("\n Rule creation cancelled", fg="yellow"))
|
|
83
89
|
return None
|
|
84
90
|
|
|
85
91
|
|
|
@@ -87,64 +93,72 @@ def _select_trigger_tool() -> Optional[str]:
|
|
|
87
93
|
"""Step 1: Select trigger tool."""
|
|
88
94
|
DesignSystem.clear_screen()
|
|
89
95
|
width = 60
|
|
90
|
-
|
|
96
|
+
|
|
91
97
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
92
|
-
click.echo(
|
|
98
|
+
click.echo(
|
|
99
|
+
"│"
|
|
100
|
+
+ click.style(" STEP 1: TRIGGER TOOL ".center(width - 2), bold=True, fg="cyan")
|
|
101
|
+
+ "│"
|
|
102
|
+
)
|
|
93
103
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
94
104
|
click.echo()
|
|
95
105
|
click.echo(" When this tool completes...")
|
|
96
106
|
click.echo()
|
|
97
|
-
|
|
107
|
+
|
|
98
108
|
# Get all available tools from plugins
|
|
99
109
|
tools = [
|
|
100
|
-
(
|
|
101
|
-
(
|
|
102
|
-
(
|
|
103
|
-
(
|
|
104
|
-
(
|
|
105
|
-
(
|
|
106
|
-
(
|
|
107
|
-
(
|
|
108
|
-
(
|
|
109
|
-
(
|
|
110
|
-
(
|
|
111
|
-
(
|
|
112
|
-
(
|
|
113
|
-
(
|
|
114
|
-
(
|
|
115
|
-
(
|
|
116
|
-
(
|
|
117
|
-
(
|
|
118
|
-
(
|
|
110
|
+
("nmap", "Network scanner"),
|
|
111
|
+
("theHarvester", "OSINT gathering"),
|
|
112
|
+
("whois", "Domain information"),
|
|
113
|
+
("dnsrecon", "DNS reconnaissance"),
|
|
114
|
+
("gobuster", "Directory brute-force"),
|
|
115
|
+
("ffuf", "Web fuzzing"),
|
|
116
|
+
("nuclei", "Vulnerability scanner"),
|
|
117
|
+
("wpscan", "WordPress scanner"),
|
|
118
|
+
("sqlmap", "SQL injection tool"),
|
|
119
|
+
("hydra", "Credential brute-force"),
|
|
120
|
+
("crackmapexec", "Windows/AD testing"),
|
|
121
|
+
("smbmap", "SMB enumeration"),
|
|
122
|
+
("enum4linux", "SMB/Samba enum"),
|
|
123
|
+
("bloodhound", "AD attack paths"),
|
|
124
|
+
("responder", "LLMNR poisoning"),
|
|
125
|
+
("searchsploit", "Exploit search"),
|
|
126
|
+
("hashcat", "Hash cracking"),
|
|
127
|
+
("john", "Password cracking"),
|
|
128
|
+
("custom", "Enter custom tool name"),
|
|
119
129
|
]
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
for idx, (tool, desc) in enumerate(tools, 1):
|
|
122
132
|
click.echo(f" [{idx}] {tool:<15} - {desc}")
|
|
123
|
-
|
|
133
|
+
|
|
124
134
|
click.echo()
|
|
125
135
|
click.echo(" [q] Cancel")
|
|
126
136
|
click.echo()
|
|
127
|
-
|
|
137
|
+
|
|
128
138
|
try:
|
|
129
|
-
choice =
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
choice = (
|
|
140
|
+
click.prompt(" Select option", type=str, show_default=False)
|
|
141
|
+
.strip()
|
|
142
|
+
.lower()
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
if choice == "q":
|
|
132
146
|
return None
|
|
133
|
-
|
|
147
|
+
|
|
134
148
|
try:
|
|
135
149
|
idx = int(choice)
|
|
136
150
|
if 1 <= idx <= len(tools):
|
|
137
151
|
tool_name = tools[idx - 1][0]
|
|
138
|
-
if tool_name ==
|
|
152
|
+
if tool_name == "custom":
|
|
139
153
|
tool_name = click.prompt(" Enter tool name", type=str)
|
|
140
154
|
return tool_name
|
|
141
155
|
except ValueError:
|
|
142
156
|
pass
|
|
143
|
-
|
|
144
|
-
click.echo(click.style(" Invalid selection", fg=
|
|
157
|
+
|
|
158
|
+
click.echo(click.style(" Invalid selection", fg="red"))
|
|
145
159
|
click.pause()
|
|
146
160
|
return None
|
|
147
|
-
|
|
161
|
+
|
|
148
162
|
except (KeyboardInterrupt, click.Abort):
|
|
149
163
|
return None
|
|
150
164
|
|
|
@@ -153,97 +167,107 @@ def _select_condition_simple(trigger_tool: str) -> Optional[str]:
|
|
|
153
167
|
"""Step 2: Select condition (simple mode)."""
|
|
154
168
|
DesignSystem.clear_screen()
|
|
155
169
|
width = 60
|
|
156
|
-
|
|
170
|
+
|
|
157
171
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
158
|
-
click.echo(
|
|
172
|
+
click.echo(
|
|
173
|
+
"│"
|
|
174
|
+
+ click.style(" STEP 2: CONDITION ".center(width - 2), bold=True, fg="cyan")
|
|
175
|
+
+ "│"
|
|
176
|
+
)
|
|
159
177
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
160
178
|
click.echo()
|
|
161
179
|
click.echo(f" When {click.style(trigger_tool, fg='yellow')} finds...")
|
|
162
180
|
click.echo()
|
|
163
|
-
|
|
181
|
+
|
|
164
182
|
# Context-aware conditions based on trigger tool
|
|
165
|
-
if trigger_tool in [
|
|
183
|
+
if trigger_tool in ["nmap"]:
|
|
166
184
|
conditions = [
|
|
167
|
-
(
|
|
168
|
-
(
|
|
169
|
-
(
|
|
170
|
-
(
|
|
171
|
-
(
|
|
172
|
-
(
|
|
173
|
-
(
|
|
174
|
-
(
|
|
175
|
-
(
|
|
176
|
-
(
|
|
185
|
+
("service:http", "HTTP service discovered (port 80/443/8080)"),
|
|
186
|
+
("service:https", "HTTPS service discovered"),
|
|
187
|
+
("service:smb", "SMB service discovered (port 445)"),
|
|
188
|
+
("service:ssh", "SSH service discovered (port 22)"),
|
|
189
|
+
("service:ftp", "FTP service discovered (port 21)"),
|
|
190
|
+
("service:mysql", "MySQL service discovered (port 3306)"),
|
|
191
|
+
("service:mssql", "MSSQL service discovered (port 1433)"),
|
|
192
|
+
("service:rdp", "RDP service discovered (port 3389)"),
|
|
193
|
+
("port:*", "Any open port discovered"),
|
|
194
|
+
("custom", "Enter custom condition"),
|
|
177
195
|
]
|
|
178
|
-
elif trigger_tool in [
|
|
196
|
+
elif trigger_tool in ["theHarvester", "whois", "dnsrecon"]:
|
|
179
197
|
conditions = [
|
|
180
|
-
(
|
|
181
|
-
(
|
|
182
|
-
(
|
|
183
|
-
(
|
|
184
|
-
(
|
|
198
|
+
("has:domains", "Domain/subdomain discovered"),
|
|
199
|
+
("has:emails", "Email addresses found"),
|
|
200
|
+
("has:hosts", "Host records found"),
|
|
201
|
+
("has:ips", "IP addresses found"),
|
|
202
|
+
("custom", "Enter custom condition"),
|
|
185
203
|
]
|
|
186
|
-
elif trigger_tool in [
|
|
204
|
+
elif trigger_tool in ["gobuster", "ffuf", "nuclei"]:
|
|
187
205
|
conditions = [
|
|
188
|
-
(
|
|
189
|
-
(
|
|
190
|
-
(
|
|
191
|
-
(
|
|
206
|
+
("has:urls", "URLs/paths discovered"),
|
|
207
|
+
("finding:vulnerability", "Vulnerability found"),
|
|
208
|
+
("finding:cve", "CVE detected"),
|
|
209
|
+
("custom", "Enter custom condition"),
|
|
192
210
|
]
|
|
193
|
-
elif trigger_tool in [
|
|
211
|
+
elif trigger_tool in ["sqlmap"]:
|
|
194
212
|
conditions = [
|
|
195
|
-
(
|
|
196
|
-
(
|
|
197
|
-
(
|
|
198
|
-
(
|
|
199
|
-
(
|
|
213
|
+
("sqli_confirmed", "SQL injection confirmed"),
|
|
214
|
+
("has:databases", "Databases enumerated"),
|
|
215
|
+
("has:tables", "Tables enumerated"),
|
|
216
|
+
("has:columns", "Columns enumerated"),
|
|
217
|
+
("custom", "Enter custom condition"),
|
|
200
218
|
]
|
|
201
219
|
else:
|
|
202
220
|
# Generic conditions for other tools
|
|
203
221
|
conditions = [
|
|
204
|
-
(
|
|
205
|
-
(
|
|
206
|
-
(
|
|
207
|
-
(
|
|
208
|
-
(
|
|
209
|
-
(
|
|
210
|
-
(
|
|
222
|
+
("service:http", "HTTP service found"),
|
|
223
|
+
("service:smb", "SMB service found"),
|
|
224
|
+
("has:domains", "Domain/subdomain discovered"),
|
|
225
|
+
("has:databases", "Database found"),
|
|
226
|
+
("finding:vulnerability", "Vulnerability detected"),
|
|
227
|
+
("port:*", "Any open port"),
|
|
228
|
+
("custom", "Enter custom condition"),
|
|
211
229
|
]
|
|
212
|
-
|
|
230
|
+
|
|
213
231
|
for idx, (cond, desc) in enumerate(conditions, 1):
|
|
214
232
|
click.echo(f" [{idx}] {desc}")
|
|
215
|
-
|
|
233
|
+
|
|
216
234
|
click.echo()
|
|
217
235
|
click.echo(" [q] Cancel")
|
|
218
236
|
click.echo()
|
|
219
|
-
|
|
237
|
+
|
|
220
238
|
try:
|
|
221
|
-
choice =
|
|
222
|
-
|
|
223
|
-
|
|
239
|
+
choice = (
|
|
240
|
+
click.prompt(" Select option", type=str, show_default=False)
|
|
241
|
+
.strip()
|
|
242
|
+
.lower()
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
if choice == "q":
|
|
224
246
|
return None
|
|
225
|
-
|
|
247
|
+
|
|
226
248
|
try:
|
|
227
249
|
idx = int(choice)
|
|
228
250
|
if 1 <= idx <= len(conditions):
|
|
229
251
|
condition = conditions[idx - 1][0]
|
|
230
|
-
if condition ==
|
|
252
|
+
if condition == "custom":
|
|
231
253
|
click.echo()
|
|
232
|
-
click.echo(" " + click.style("Examples:", fg=
|
|
254
|
+
click.echo(" " + click.style("Examples:", fg="yellow"))
|
|
233
255
|
click.echo(" service:ftp, port:8080, has:tables, finding:xss")
|
|
234
256
|
condition = click.prompt(" Enter condition", type=str)
|
|
235
|
-
elif condition ==
|
|
236
|
-
port = click.prompt(
|
|
237
|
-
|
|
238
|
-
|
|
257
|
+
elif condition == "port:*":
|
|
258
|
+
port = click.prompt(
|
|
259
|
+
" Enter specific port (or * for any)", default="*"
|
|
260
|
+
)
|
|
261
|
+
if port != "*":
|
|
262
|
+
condition = f"port:{port}"
|
|
239
263
|
return condition
|
|
240
264
|
except ValueError:
|
|
241
265
|
pass
|
|
242
|
-
|
|
243
|
-
click.echo(click.style(" Invalid selection", fg=
|
|
266
|
+
|
|
267
|
+
click.echo(click.style(" Invalid selection", fg="red"))
|
|
244
268
|
click.pause()
|
|
245
269
|
return None
|
|
246
|
-
|
|
270
|
+
|
|
247
271
|
except (KeyboardInterrupt, click.Abort):
|
|
248
272
|
return None
|
|
249
273
|
|
|
@@ -252,62 +276,70 @@ def _select_target_tool() -> Optional[str]:
|
|
|
252
276
|
"""Step 3: Select target tool."""
|
|
253
277
|
DesignSystem.clear_screen()
|
|
254
278
|
width = 60
|
|
255
|
-
|
|
279
|
+
|
|
256
280
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
257
|
-
click.echo(
|
|
281
|
+
click.echo(
|
|
282
|
+
"│"
|
|
283
|
+
+ click.style(" STEP 3: TARGET TOOL ".center(width - 2), bold=True, fg="cyan")
|
|
284
|
+
+ "│"
|
|
285
|
+
)
|
|
258
286
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
259
287
|
click.echo()
|
|
260
288
|
click.echo(" Then run...")
|
|
261
289
|
click.echo()
|
|
262
|
-
|
|
290
|
+
|
|
263
291
|
# Comprehensive list of target tools
|
|
264
292
|
tools = [
|
|
265
|
-
(
|
|
266
|
-
(
|
|
267
|
-
(
|
|
268
|
-
(
|
|
269
|
-
(
|
|
270
|
-
(
|
|
271
|
-
(
|
|
272
|
-
(
|
|
273
|
-
(
|
|
274
|
-
(
|
|
275
|
-
(
|
|
276
|
-
(
|
|
277
|
-
(
|
|
278
|
-
(
|
|
279
|
-
(
|
|
280
|
-
(
|
|
281
|
-
(
|
|
293
|
+
("gobuster", "Directory brute-force"),
|
|
294
|
+
("ffuf", "Web fuzzing"),
|
|
295
|
+
("nuclei", "Vulnerability scanning"),
|
|
296
|
+
("wpscan", "WordPress scanning"),
|
|
297
|
+
("sqlmap", "SQL injection testing"),
|
|
298
|
+
("hydra", "Credential brute-force"),
|
|
299
|
+
("crackmapexec", "Windows/AD testing"),
|
|
300
|
+
("smbmap", "SMB share mapping"),
|
|
301
|
+
("enum4linux", "SMB/Samba enumeration"),
|
|
302
|
+
("bloodhound", "AD attack path mapping"),
|
|
303
|
+
("impacket-secretsdump", "Credential dumping"),
|
|
304
|
+
("impacket-getnpusers", "AS-REP roasting"),
|
|
305
|
+
("responder", "LLMNR poisoning"),
|
|
306
|
+
("searchsploit", "Exploit database search"),
|
|
307
|
+
("hashcat", "Hash cracking"),
|
|
308
|
+
("john", "Password cracking"),
|
|
309
|
+
("custom", "Enter custom tool name"),
|
|
282
310
|
]
|
|
283
|
-
|
|
311
|
+
|
|
284
312
|
for idx, (tool, desc) in enumerate(tools, 1):
|
|
285
313
|
click.echo(f" [{idx}] {tool:<15} - {desc}")
|
|
286
|
-
|
|
314
|
+
|
|
287
315
|
click.echo()
|
|
288
316
|
click.echo(" [q] Cancel")
|
|
289
317
|
click.echo()
|
|
290
|
-
|
|
318
|
+
|
|
291
319
|
try:
|
|
292
|
-
choice =
|
|
293
|
-
|
|
294
|
-
|
|
320
|
+
choice = (
|
|
321
|
+
click.prompt(" Select option", type=str, show_default=False)
|
|
322
|
+
.strip()
|
|
323
|
+
.lower()
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
if choice == "q":
|
|
295
327
|
return None
|
|
296
|
-
|
|
328
|
+
|
|
297
329
|
try:
|
|
298
330
|
idx = int(choice)
|
|
299
331
|
if 1 <= idx <= len(tools):
|
|
300
332
|
tool_name = tools[idx - 1][0]
|
|
301
|
-
if tool_name ==
|
|
333
|
+
if tool_name == "custom":
|
|
302
334
|
tool_name = click.prompt(" Enter tool name", type=str)
|
|
303
335
|
return tool_name
|
|
304
336
|
except ValueError:
|
|
305
337
|
pass
|
|
306
|
-
|
|
307
|
-
click.echo(click.style(" Invalid selection", fg=
|
|
338
|
+
|
|
339
|
+
click.echo(click.style(" Invalid selection", fg="red"))
|
|
308
340
|
click.pause()
|
|
309
341
|
return None
|
|
310
|
-
|
|
342
|
+
|
|
311
343
|
except (KeyboardInterrupt, click.Abort):
|
|
312
344
|
return None
|
|
313
345
|
|
|
@@ -316,59 +348,112 @@ def _select_args_template(tool: str) -> List[str]:
|
|
|
316
348
|
"""Step 4: Select args template."""
|
|
317
349
|
DesignSystem.clear_screen()
|
|
318
350
|
width = 60
|
|
319
|
-
|
|
351
|
+
|
|
320
352
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
321
|
-
click.echo(
|
|
353
|
+
click.echo(
|
|
354
|
+
"│"
|
|
355
|
+
+ click.style(" STEP 4: ARGUMENTS ".center(width - 2), bold=True, fg="cyan")
|
|
356
|
+
+ "│"
|
|
357
|
+
)
|
|
322
358
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
323
359
|
click.echo()
|
|
324
360
|
click.echo(f" Arguments for {click.style(tool, fg='yellow')} (optional)")
|
|
325
361
|
click.echo()
|
|
326
|
-
|
|
362
|
+
|
|
327
363
|
# Tool-specific presets with common use cases
|
|
328
364
|
presets = {
|
|
329
|
-
|
|
330
|
-
(
|
|
331
|
-
|
|
365
|
+
"gobuster": [
|
|
366
|
+
(
|
|
367
|
+
["dir", "-u", "{target}", "-w", "data/wordlists/web_dirs_common.txt"],
|
|
368
|
+
"Default - web_dirs_common.txt",
|
|
369
|
+
),
|
|
370
|
+
(
|
|
371
|
+
["dir", "-u", "{target}", "-w", "data/wordlists/web_dirs_large.txt"],
|
|
372
|
+
"Large - web_dirs_large.txt",
|
|
373
|
+
),
|
|
332
374
|
],
|
|
333
|
-
|
|
334
|
-
(
|
|
335
|
-
|
|
375
|
+
"ffuf": [
|
|
376
|
+
(
|
|
377
|
+
["-u", "{target}/FUZZ", "-w", "data/wordlists/web_dirs_common.txt"],
|
|
378
|
+
"Directory fuzzing",
|
|
379
|
+
),
|
|
380
|
+
(
|
|
381
|
+
[
|
|
382
|
+
"-u",
|
|
383
|
+
"{target}?FUZZ=value",
|
|
384
|
+
"-w",
|
|
385
|
+
"data/wordlists/web_files_common.txt",
|
|
386
|
+
],
|
|
387
|
+
"Parameter fuzzing",
|
|
388
|
+
),
|
|
336
389
|
],
|
|
337
|
-
|
|
338
|
-
(
|
|
339
|
-
|
|
340
|
-
|
|
390
|
+
"nuclei": [
|
|
391
|
+
(
|
|
392
|
+
["-u", "{target}", "-severity", "critical,high"],
|
|
393
|
+
"Critical/High severity only",
|
|
394
|
+
),
|
|
395
|
+
(["-u", "{target}", "-tags", "cve"], "CVE templates only"),
|
|
396
|
+
(["-u", "{target}"], "All templates (default)"),
|
|
341
397
|
],
|
|
342
|
-
|
|
343
|
-
([
|
|
344
|
-
(
|
|
398
|
+
"sqlmap": [
|
|
399
|
+
(["-u", "{target}", "--batch", "--dbs"], "Enumerate databases"),
|
|
400
|
+
(
|
|
401
|
+
["-u", "{target}", "--batch", "--forms", "--crawl=2"],
|
|
402
|
+
"Form-based with crawling",
|
|
403
|
+
),
|
|
345
404
|
],
|
|
346
|
-
|
|
347
|
-
(
|
|
348
|
-
|
|
405
|
+
"hydra": [
|
|
406
|
+
(
|
|
407
|
+
[
|
|
408
|
+
"-L",
|
|
409
|
+
"data/wordlists/usernames_common.txt",
|
|
410
|
+
"-P",
|
|
411
|
+
"data/wordlists/passwords_brute.txt",
|
|
412
|
+
"{target}",
|
|
413
|
+
"ssh",
|
|
414
|
+
],
|
|
415
|
+
"SSH brute-force",
|
|
416
|
+
),
|
|
417
|
+
(
|
|
418
|
+
[
|
|
419
|
+
"-L",
|
|
420
|
+
"data/wordlists/usernames_common.txt",
|
|
421
|
+
"-P",
|
|
422
|
+
"data/wordlists/passwords_brute.txt",
|
|
423
|
+
"{target}",
|
|
424
|
+
"ftp",
|
|
425
|
+
],
|
|
426
|
+
"FTP brute-force",
|
|
427
|
+
),
|
|
349
428
|
],
|
|
350
|
-
|
|
351
|
-
(
|
|
429
|
+
"wpscan": [
|
|
430
|
+
(
|
|
431
|
+
["--url", "{target}", "--enumerate", "vp,vt,u"],
|
|
432
|
+
"Enumerate plugins, themes, users",
|
|
433
|
+
),
|
|
434
|
+
],
|
|
435
|
+
"crackmapexec": [
|
|
436
|
+
(
|
|
437
|
+
["smb", "{target}", "-u", "Administrator", "-p", "password"],
|
|
438
|
+
"SMB authentication",
|
|
439
|
+
),
|
|
440
|
+
(["smb", "{target}", "--shares"], "Enumerate SMB shares"),
|
|
352
441
|
],
|
|
353
|
-
'crackmapexec': [
|
|
354
|
-
(['smb', '{target}', '-u', 'Administrator', '-p', 'password'], 'SMB authentication'),
|
|
355
|
-
(['smb', '{target}', '--shares'], 'Enumerate SMB shares'),
|
|
356
|
-
]
|
|
357
442
|
}
|
|
358
|
-
|
|
443
|
+
|
|
359
444
|
if tool in presets:
|
|
360
|
-
click.echo(" " + click.style("Common presets:", fg=
|
|
445
|
+
click.echo(" " + click.style("Common presets:", fg="yellow"))
|
|
361
446
|
for idx, (args, desc) in enumerate(presets[tool], 1):
|
|
362
447
|
click.echo(f" [{idx}] {desc}")
|
|
363
448
|
click.echo(f" [{len(presets[tool]) + 1}] Custom args...")
|
|
364
449
|
click.echo(" [ENTER] Skip (no args)")
|
|
365
450
|
click.echo()
|
|
366
|
-
|
|
367
|
-
choice = click.prompt(" Select option", default=
|
|
368
|
-
|
|
451
|
+
|
|
452
|
+
choice = click.prompt(" Select option", default="", show_default=False).strip()
|
|
453
|
+
|
|
369
454
|
if not choice:
|
|
370
455
|
return []
|
|
371
|
-
|
|
456
|
+
|
|
372
457
|
try:
|
|
373
458
|
idx = int(choice)
|
|
374
459
|
if 1 <= idx <= len(presets[tool]):
|
|
@@ -376,12 +461,16 @@ def _select_args_template(tool: str) -> List[str]:
|
|
|
376
461
|
elif idx == len(presets[tool]) + 1:
|
|
377
462
|
# Custom args
|
|
378
463
|
click.echo()
|
|
379
|
-
click.echo(" " + click.style("Placeholders available:", fg=
|
|
464
|
+
click.echo(" " + click.style("Placeholders available:", fg="yellow"))
|
|
380
465
|
click.echo(" {target} - Target URL/IP/host")
|
|
381
466
|
click.echo(" {port} - Target port")
|
|
382
467
|
click.echo(" {domain} - Domain name")
|
|
383
468
|
click.echo()
|
|
384
|
-
click.echo(
|
|
469
|
+
click.echo(
|
|
470
|
+
" "
|
|
471
|
+
+ click.style("Example:", fg="yellow")
|
|
472
|
+
+ " -u {target} -o /tmp/output.txt"
|
|
473
|
+
)
|
|
385
474
|
click.echo()
|
|
386
475
|
args_str = click.prompt(" Enter arguments", type=str)
|
|
387
476
|
return args_str.split()
|
|
@@ -389,23 +478,27 @@ def _select_args_template(tool: str) -> List[str]:
|
|
|
389
478
|
pass
|
|
390
479
|
else:
|
|
391
480
|
# No presets for this tool - show help and get custom args
|
|
392
|
-
click.echo(
|
|
481
|
+
click.echo(
|
|
482
|
+
" " + click.style("No presets available for this tool.", fg="yellow")
|
|
483
|
+
)
|
|
393
484
|
click.echo()
|
|
394
|
-
click.echo(" " + click.style("Available placeholders:", fg=
|
|
485
|
+
click.echo(" " + click.style("Available placeholders:", fg="cyan"))
|
|
395
486
|
click.echo(" {target} - Target URL/IP/host")
|
|
396
487
|
click.echo(" {port} - Target port")
|
|
397
488
|
click.echo(" {domain} - Domain name")
|
|
398
489
|
click.echo()
|
|
399
|
-
click.echo(" " + click.style("Examples:", fg=
|
|
490
|
+
click.echo(" " + click.style("Examples:", fg="cyan"))
|
|
400
491
|
click.echo(" -u {target} --threads 10")
|
|
401
492
|
click.echo(" --target {target}:{port}")
|
|
402
493
|
click.echo(" -d {domain} -o output.txt")
|
|
403
494
|
click.echo()
|
|
404
|
-
|
|
405
|
-
args_str = click.prompt(
|
|
495
|
+
|
|
496
|
+
args_str = click.prompt(
|
|
497
|
+
" Enter arguments (or ENTER to skip)", default="", show_default=False
|
|
498
|
+
)
|
|
406
499
|
if args_str:
|
|
407
500
|
return args_str.split()
|
|
408
|
-
|
|
501
|
+
|
|
409
502
|
return []
|
|
410
503
|
|
|
411
504
|
|
|
@@ -413,40 +506,51 @@ def _configure_rule_settings() -> Optional[Dict[str, Any]]:
|
|
|
413
506
|
"""Step 5: Configure rule settings."""
|
|
414
507
|
DesignSystem.clear_screen()
|
|
415
508
|
width = 60
|
|
416
|
-
|
|
509
|
+
|
|
417
510
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
418
|
-
click.echo(
|
|
511
|
+
click.echo(
|
|
512
|
+
"│"
|
|
513
|
+
+ click.style(" STEP 5: RULE SETTINGS ".center(width - 2), bold=True, fg="cyan")
|
|
514
|
+
+ "│"
|
|
515
|
+
)
|
|
419
516
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
420
517
|
click.echo()
|
|
421
|
-
|
|
518
|
+
|
|
422
519
|
try:
|
|
423
|
-
priority = click.prompt(
|
|
424
|
-
|
|
425
|
-
|
|
520
|
+
priority = click.prompt(
|
|
521
|
+
" Priority (1-10, higher = runs first)",
|
|
522
|
+
type=click.IntRange(1, 10),
|
|
523
|
+
default=5,
|
|
524
|
+
)
|
|
525
|
+
|
|
426
526
|
click.echo()
|
|
427
527
|
click.echo(" Category:")
|
|
428
528
|
click.echo(" [1] CTF - Aggressive scanning for practice environments")
|
|
429
529
|
click.echo(" [2] Enterprise - Conservative scanning for production")
|
|
430
530
|
click.echo(" [3] General - Balanced approach for most scenarios")
|
|
431
531
|
click.echo()
|
|
432
|
-
|
|
433
|
-
cat_choice = click.prompt(
|
|
434
|
-
|
|
532
|
+
|
|
533
|
+
cat_choice = click.prompt(
|
|
534
|
+
" Select option", type=click.IntRange(1, 3), default=3, show_default=False
|
|
535
|
+
)
|
|
536
|
+
categories = {1: "CTF", 2: "ENTERPRISE", 3: "GENERAL"}
|
|
435
537
|
category = categories[cat_choice]
|
|
436
|
-
|
|
538
|
+
|
|
437
539
|
click.echo()
|
|
438
540
|
enabled = click.confirm(" Enable immediately?", default=True)
|
|
439
|
-
|
|
541
|
+
|
|
440
542
|
click.echo()
|
|
441
|
-
description = click.prompt(
|
|
442
|
-
|
|
543
|
+
description = click.prompt(
|
|
544
|
+
" Description (optional)", default="", show_default=False
|
|
545
|
+
)
|
|
546
|
+
|
|
443
547
|
return {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
548
|
+
"priority": priority,
|
|
549
|
+
"category": category,
|
|
550
|
+
"enabled": enabled,
|
|
551
|
+
"description": description,
|
|
448
552
|
}
|
|
449
|
-
|
|
553
|
+
|
|
450
554
|
except (KeyboardInterrupt, click.Abort):
|
|
451
555
|
return None
|
|
452
556
|
|
|
@@ -455,40 +559,54 @@ def _confirm_rule(rule: Dict[str, Any]) -> bool:
|
|
|
455
559
|
"""Show rule summary and confirm creation."""
|
|
456
560
|
DesignSystem.clear_screen()
|
|
457
561
|
width = 60
|
|
458
|
-
|
|
562
|
+
|
|
459
563
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
460
|
-
click.echo(
|
|
564
|
+
click.echo(
|
|
565
|
+
"│"
|
|
566
|
+
+ click.style(" RULE CREATED! ".center(width - 2), bold=True, fg="green")
|
|
567
|
+
+ "│"
|
|
568
|
+
)
|
|
461
569
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
462
570
|
click.echo()
|
|
463
|
-
|
|
571
|
+
|
|
464
572
|
# Format rule display
|
|
465
|
-
click.echo(
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
573
|
+
click.echo(
|
|
574
|
+
" "
|
|
575
|
+
+ click.style("WHEN", fg="yellow", bold=True)
|
|
576
|
+
+ f" {rule['trigger_tool']} finds {rule['condition']}"
|
|
577
|
+
)
|
|
578
|
+
click.echo(
|
|
579
|
+
" "
|
|
580
|
+
+ click.style("THEN", fg="yellow", bold=True)
|
|
581
|
+
+ f" run {rule['target_tool']}"
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
if rule["args"]:
|
|
585
|
+
args_str = " ".join(rule["args"])
|
|
586
|
+
click.echo(" " + click.style("WITH", fg="yellow", bold=True) + f" {args_str}")
|
|
587
|
+
|
|
472
588
|
click.echo()
|
|
473
589
|
click.echo(f" Priority: {rule['priority']}/10")
|
|
474
590
|
click.echo(f" Category: {rule['category']}")
|
|
475
591
|
click.echo(f" Status: {'ENABLED' if rule['enabled'] else 'DISABLED'}")
|
|
476
|
-
|
|
477
|
-
if rule[
|
|
592
|
+
|
|
593
|
+
if rule["description"]:
|
|
478
594
|
click.echo(f" Description: {rule['description']}")
|
|
479
|
-
|
|
595
|
+
|
|
480
596
|
click.echo()
|
|
481
597
|
click.echo(" [ENTER] Save rule [+] Create another [q] Cancel")
|
|
482
598
|
click.echo()
|
|
483
|
-
|
|
484
|
-
choice =
|
|
485
|
-
|
|
486
|
-
|
|
599
|
+
|
|
600
|
+
choice = (
|
|
601
|
+
click.prompt(" Select option", default="", show_default=False).strip().lower()
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
return choice != "q"
|
|
487
605
|
|
|
488
606
|
|
|
489
607
|
def _advanced_mode_builder() -> Optional[Dict[str, Any]]:
|
|
490
608
|
"""Advanced mode with full control (to be implemented)."""
|
|
491
|
-
click.echo(click.style("\n Advanced mode coming soon!", fg=
|
|
609
|
+
click.echo(click.style("\n Advanced mode coming soon!", fg="yellow"))
|
|
492
610
|
click.pause()
|
|
493
611
|
return None
|
|
494
612
|
|
|
@@ -496,26 +614,26 @@ def _advanced_mode_builder() -> Optional[Dict[str, Any]]:
|
|
|
496
614
|
def _save_custom_rule(rule: Dict[str, Any]) -> bool:
|
|
497
615
|
"""
|
|
498
616
|
Save custom rule to file.
|
|
499
|
-
|
|
617
|
+
|
|
500
618
|
Args:
|
|
501
619
|
rule: Rule dictionary
|
|
502
|
-
|
|
620
|
+
|
|
503
621
|
Returns:
|
|
504
622
|
bool: True if saved successfully
|
|
505
623
|
"""
|
|
506
624
|
try:
|
|
507
625
|
from souleyez.core.tool_chaining import ToolChaining
|
|
508
|
-
|
|
626
|
+
|
|
509
627
|
tc = ToolChaining()
|
|
510
628
|
tc.add_custom_rule(rule)
|
|
511
|
-
|
|
629
|
+
|
|
512
630
|
click.echo()
|
|
513
|
-
click.echo(click.style(" ✓ Rule saved successfully!", fg=
|
|
631
|
+
click.echo(click.style(" ✓ Rule saved successfully!", fg="green"))
|
|
514
632
|
click.pause()
|
|
515
633
|
return True
|
|
516
|
-
|
|
634
|
+
|
|
517
635
|
except Exception as e:
|
|
518
636
|
click.echo()
|
|
519
|
-
click.echo(click.style(f" ✗ Failed to save rule: {e}", fg=
|
|
637
|
+
click.echo(click.style(f" ✗ Failed to save rule: {e}", fg="red"))
|
|
520
638
|
click.pause()
|
|
521
639
|
return False
|