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.
Files changed (358) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9526 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1239 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2200 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +292 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/web_login_test_handler.py +327 -0
  126. souleyez/handlers/whois_handler.py +277 -0
  127. souleyez/handlers/wpscan_handler.py +554 -0
  128. souleyez/history.py +32 -16
  129. souleyez/importers/msf_importer.py +106 -75
  130. souleyez/importers/smart_importer.py +208 -147
  131. souleyez/integrations/siem/__init__.py +10 -10
  132. souleyez/integrations/siem/base.py +17 -18
  133. souleyez/integrations/siem/elastic.py +108 -122
  134. souleyez/integrations/siem/factory.py +207 -80
  135. souleyez/integrations/siem/googlesecops.py +146 -154
  136. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  137. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  138. souleyez/integrations/siem/sentinel.py +107 -109
  139. souleyez/integrations/siem/splunk.py +246 -212
  140. souleyez/integrations/siem/wazuh.py +65 -71
  141. souleyez/integrations/wazuh/__init__.py +5 -5
  142. souleyez/integrations/wazuh/client.py +70 -93
  143. souleyez/integrations/wazuh/config.py +85 -57
  144. souleyez/integrations/wazuh/host_mapper.py +28 -36
  145. souleyez/integrations/wazuh/sync.py +78 -68
  146. souleyez/intelligence/__init__.py +4 -5
  147. souleyez/intelligence/correlation_analyzer.py +309 -295
  148. souleyez/intelligence/exploit_knowledge.py +661 -623
  149. souleyez/intelligence/exploit_suggestions.py +159 -139
  150. souleyez/intelligence/gap_analyzer.py +132 -97
  151. souleyez/intelligence/gap_detector.py +251 -214
  152. souleyez/intelligence/sensitive_tables.py +266 -129
  153. souleyez/intelligence/service_parser.py +137 -123
  154. souleyez/intelligence/surface_analyzer.py +407 -268
  155. souleyez/intelligence/target_parser.py +159 -162
  156. souleyez/licensing/__init__.py +6 -6
  157. souleyez/licensing/validator.py +17 -19
  158. souleyez/log_config.py +79 -54
  159. souleyez/main.py +1505 -687
  160. souleyez/migrations/fix_job_counter.py +16 -14
  161. souleyez/parsers/bloodhound_parser.py +41 -39
  162. souleyez/parsers/crackmapexec_parser.py +178 -111
  163. souleyez/parsers/dalfox_parser.py +72 -77
  164. souleyez/parsers/dnsrecon_parser.py +103 -91
  165. souleyez/parsers/enum4linux_parser.py +183 -153
  166. souleyez/parsers/ffuf_parser.py +29 -25
  167. souleyez/parsers/gobuster_parser.py +301 -41
  168. souleyez/parsers/hashcat_parser.py +324 -79
  169. souleyez/parsers/http_fingerprint_parser.py +350 -103
  170. souleyez/parsers/hydra_parser.py +131 -111
  171. souleyez/parsers/impacket_parser.py +231 -178
  172. souleyez/parsers/john_parser.py +98 -86
  173. souleyez/parsers/katana_parser.py +316 -0
  174. souleyez/parsers/msf_parser.py +943 -498
  175. souleyez/parsers/nikto_parser.py +346 -65
  176. souleyez/parsers/nmap_parser.py +262 -174
  177. souleyez/parsers/nuclei_parser.py +40 -44
  178. souleyez/parsers/responder_parser.py +26 -26
  179. souleyez/parsers/searchsploit_parser.py +74 -74
  180. souleyez/parsers/service_explorer_parser.py +279 -0
  181. souleyez/parsers/smbmap_parser.py +180 -124
  182. souleyez/parsers/sqlmap_parser.py +434 -308
  183. souleyez/parsers/theharvester_parser.py +75 -57
  184. souleyez/parsers/whois_parser.py +135 -94
  185. souleyez/parsers/wpscan_parser.py +278 -190
  186. souleyez/plugins/afp.py +44 -36
  187. souleyez/plugins/afp_brute.py +114 -46
  188. souleyez/plugins/ard.py +48 -37
  189. souleyez/plugins/bloodhound.py +95 -61
  190. souleyez/plugins/certipy.py +303 -0
  191. souleyez/plugins/crackmapexec.py +186 -85
  192. souleyez/plugins/dalfox.py +120 -59
  193. souleyez/plugins/dns_hijack.py +146 -41
  194. souleyez/plugins/dnsrecon.py +97 -61
  195. souleyez/plugins/enum4linux.py +91 -66
  196. souleyez/plugins/evil_winrm.py +291 -0
  197. souleyez/plugins/ffuf.py +166 -90
  198. souleyez/plugins/firmware_extract.py +133 -29
  199. souleyez/plugins/gobuster.py +387 -190
  200. souleyez/plugins/gpp_extract.py +393 -0
  201. souleyez/plugins/hashcat.py +100 -73
  202. souleyez/plugins/http_fingerprint.py +854 -267
  203. souleyez/plugins/hydra.py +566 -200
  204. souleyez/plugins/impacket_getnpusers.py +117 -69
  205. souleyez/plugins/impacket_psexec.py +84 -64
  206. souleyez/plugins/impacket_secretsdump.py +103 -69
  207. souleyez/plugins/impacket_smbclient.py +89 -75
  208. souleyez/plugins/john.py +86 -69
  209. souleyez/plugins/katana.py +313 -0
  210. souleyez/plugins/kerbrute.py +237 -0
  211. souleyez/plugins/lfi_extract.py +541 -0
  212. souleyez/plugins/macos_ssh.py +117 -48
  213. souleyez/plugins/mdns.py +35 -30
  214. souleyez/plugins/msf_auxiliary.py +253 -130
  215. souleyez/plugins/msf_exploit.py +239 -161
  216. souleyez/plugins/nikto.py +134 -78
  217. souleyez/plugins/nmap.py +275 -91
  218. souleyez/plugins/nuclei.py +180 -89
  219. souleyez/plugins/nxc.py +285 -0
  220. souleyez/plugins/plugin_base.py +35 -36
  221. souleyez/plugins/plugin_template.py +13 -5
  222. souleyez/plugins/rdp_sec_check.py +130 -0
  223. souleyez/plugins/responder.py +112 -71
  224. souleyez/plugins/router_http_brute.py +76 -65
  225. souleyez/plugins/router_ssh_brute.py +118 -41
  226. souleyez/plugins/router_telnet_brute.py +124 -42
  227. souleyez/plugins/routersploit.py +91 -59
  228. souleyez/plugins/routersploit_exploit.py +77 -55
  229. souleyez/plugins/searchsploit.py +91 -77
  230. souleyez/plugins/service_explorer.py +1160 -0
  231. souleyez/plugins/smbmap.py +122 -72
  232. souleyez/plugins/smbpasswd.py +215 -0
  233. souleyez/plugins/sqlmap.py +301 -113
  234. souleyez/plugins/theharvester.py +127 -75
  235. souleyez/plugins/tr069.py +79 -57
  236. souleyez/plugins/upnp.py +65 -47
  237. souleyez/plugins/upnp_abuse.py +73 -55
  238. souleyez/plugins/vnc_access.py +129 -42
  239. souleyez/plugins/vnc_brute.py +109 -38
  240. souleyez/plugins/web_login_test.py +417 -0
  241. souleyez/plugins/whois.py +77 -58
  242. souleyez/plugins/wpscan.py +173 -69
  243. souleyez/reporting/__init__.py +2 -1
  244. souleyez/reporting/attack_chain.py +411 -346
  245. souleyez/reporting/charts.py +436 -501
  246. souleyez/reporting/compliance_mappings.py +334 -201
  247. souleyez/reporting/detection_report.py +126 -125
  248. souleyez/reporting/formatters.py +828 -591
  249. souleyez/reporting/generator.py +386 -302
  250. souleyez/reporting/metrics.py +72 -75
  251. souleyez/scanner.py +35 -29
  252. souleyez/security/__init__.py +37 -11
  253. souleyez/security/scope_validator.py +175 -106
  254. souleyez/security/validation.py +223 -149
  255. souleyez/security.py +22 -6
  256. souleyez/storage/credentials.py +247 -186
  257. souleyez/storage/crypto.py +296 -129
  258. souleyez/storage/database.py +73 -50
  259. souleyez/storage/db.py +58 -36
  260. souleyez/storage/deliverable_evidence.py +177 -128
  261. souleyez/storage/deliverable_exporter.py +282 -246
  262. souleyez/storage/deliverable_templates.py +134 -116
  263. souleyez/storage/deliverables.py +135 -130
  264. souleyez/storage/engagements.py +109 -56
  265. souleyez/storage/evidence.py +181 -152
  266. souleyez/storage/execution_log.py +31 -17
  267. souleyez/storage/exploit_attempts.py +93 -57
  268. souleyez/storage/exploits.py +67 -36
  269. souleyez/storage/findings.py +48 -61
  270. souleyez/storage/hosts.py +176 -144
  271. souleyez/storage/migrate_to_engagements.py +43 -19
  272. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  273. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  274. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  275. souleyez/storage/migrations/_005_screenshots.py +13 -5
  276. souleyez/storage/migrations/_006_deliverables.py +13 -5
  277. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  278. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  279. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  280. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  281. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  282. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  283. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  284. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  285. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  286. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  287. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  288. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  289. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  290. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  291. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  292. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  293. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  294. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  295. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  296. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  297. souleyez/storage/migrations/__init__.py +26 -26
  298. souleyez/storage/migrations/migration_manager.py +19 -19
  299. souleyez/storage/msf_sessions.py +100 -65
  300. souleyez/storage/osint.py +17 -24
  301. souleyez/storage/recommendation_engine.py +269 -235
  302. souleyez/storage/screenshots.py +33 -32
  303. souleyez/storage/smb_shares.py +136 -92
  304. souleyez/storage/sqlmap_data.py +183 -128
  305. souleyez/storage/team_collaboration.py +135 -141
  306. souleyez/storage/timeline_tracker.py +122 -94
  307. souleyez/storage/wazuh_vulns.py +64 -66
  308. souleyez/storage/web_paths.py +33 -37
  309. souleyez/testing/credential_tester.py +221 -205
  310. souleyez/ui/__init__.py +1 -1
  311. souleyez/ui/ai_quotes.py +12 -12
  312. souleyez/ui/attack_surface.py +2439 -1516
  313. souleyez/ui/chain_rules_view.py +914 -382
  314. souleyez/ui/correlation_view.py +312 -230
  315. souleyez/ui/dashboard.py +2382 -1130
  316. souleyez/ui/deliverables_view.py +148 -62
  317. souleyez/ui/design_system.py +13 -13
  318. souleyez/ui/errors.py +49 -49
  319. souleyez/ui/evidence_linking_view.py +284 -179
  320. souleyez/ui/evidence_vault.py +393 -285
  321. souleyez/ui/exploit_suggestions_view.py +555 -349
  322. souleyez/ui/export_view.py +100 -66
  323. souleyez/ui/gap_analysis_view.py +315 -171
  324. souleyez/ui/help_system.py +105 -97
  325. souleyez/ui/intelligence_view.py +436 -293
  326. souleyez/ui/interactive.py +22827 -10678
  327. souleyez/ui/interactive_selector.py +75 -68
  328. souleyez/ui/log_formatter.py +47 -39
  329. souleyez/ui/menu_components.py +22 -13
  330. souleyez/ui/msf_auxiliary_menu.py +184 -133
  331. souleyez/ui/pending_chains_view.py +336 -172
  332. souleyez/ui/progress_indicators.py +5 -3
  333. souleyez/ui/recommendations_view.py +195 -137
  334. souleyez/ui/rule_builder.py +343 -225
  335. souleyez/ui/setup_wizard.py +678 -284
  336. souleyez/ui/shortcuts.py +217 -165
  337. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  338. souleyez/ui/splunk_vulns_view.py +139 -86
  339. souleyez/ui/team_dashboard.py +498 -335
  340. souleyez/ui/template_selector.py +196 -105
  341. souleyez/ui/terminal.py +6 -6
  342. souleyez/ui/timeline_view.py +198 -127
  343. souleyez/ui/tool_setup.py +264 -164
  344. souleyez/ui/tutorial.py +202 -72
  345. souleyez/ui/tutorial_state.py +40 -40
  346. souleyez/ui/wazuh_vulns_view.py +235 -141
  347. souleyez/ui/wordlist_browser.py +260 -107
  348. souleyez/ui.py +464 -312
  349. souleyez/utils/tool_checker.py +427 -367
  350. souleyez/utils.py +33 -29
  351. souleyez/wordlists.py +134 -167
  352. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
  353. souleyez-2.43.34.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
@@ -10,73 +10,73 @@ from urllib.parse import urlparse
10
10
 
11
11
  class TargetParser:
12
12
  """Parse job targets to extract host and port information."""
13
-
13
+
14
14
  # Common service-to-port mappings
15
15
  SERVICE_PORTS = {
16
- 'ftp': 21,
17
- 'ssh': 22,
18
- 'telnet': 23,
19
- 'smtp': 25,
20
- 'dns': 53,
21
- 'http': 80,
22
- 'pop3': 110,
23
- 'imap': 143,
24
- 'snmp': 161,
25
- 'ldap': 389,
26
- 'https': 443,
27
- 'smb': 445,
28
- 'smbold': 139,
29
- 'mssql': 1433,
30
- 'mysql': 3306,
31
- 'rdp': 3389,
32
- 'postgres': 5432,
33
- 'postgresql': 5432,
34
- 'vnc': 5900,
35
- 'redis': 6379,
36
- 'mongodb': 27017,
16
+ "ftp": 21,
17
+ "ssh": 22,
18
+ "telnet": 23,
19
+ "smtp": 25,
20
+ "dns": 53,
21
+ "http": 80,
22
+ "pop3": 110,
23
+ "imap": 143,
24
+ "snmp": 161,
25
+ "ldap": 389,
26
+ "https": 443,
27
+ "smb": 445,
28
+ "smbold": 139,
29
+ "mssql": 1433,
30
+ "mysql": 3306,
31
+ "rdp": 3389,
32
+ "postgres": 5432,
33
+ "postgresql": 5432,
34
+ "vnc": 5900,
35
+ "redis": 6379,
36
+ "mongodb": 27017,
37
37
  }
38
-
38
+
39
39
  # Reverse mapping: port to service
40
40
  PORT_SERVICES = {v: k for k, v in SERVICE_PORTS.items()}
41
41
  # Handle duplicates manually
42
- PORT_SERVICES[139] = 'smb'
43
- PORT_SERVICES[445] = 'smb'
42
+ PORT_SERVICES[139] = "smb"
43
+ PORT_SERVICES[445] = "smb"
44
44
 
45
45
  # Add common non-standard web ports for vulnerable web apps
46
- PORT_SERVICES[3000] = 'http' # Node.js/Express default, OWASP Juice Shop
47
- PORT_SERVICES[8080] = 'http' # Tomcat/alternative HTTP
48
- PORT_SERVICES[8000] = 'http' # Django/Python dev servers
49
- PORT_SERVICES[8888] = 'http' # Jupyter/alternative web servers
50
- PORT_SERVICES[9090] = 'http' # Cockpit/monitoring interfaces
51
-
46
+ PORT_SERVICES[3000] = "http" # Node.js/Express default, OWASP Juice Shop
47
+ PORT_SERVICES[8080] = "http" # Tomcat/alternative HTTP
48
+ PORT_SERVICES[8000] = "http" # Django/Python dev servers
49
+ PORT_SERVICES[8888] = "http" # Jupyter/alternative web servers
50
+ PORT_SERVICES[9090] = "http" # Cockpit/monitoring interfaces
51
+
52
52
  # MSF module patterns
53
53
  MSF_PATTERNS = {
54
- 'ftp': 21,
55
- 'ssh': 22,
56
- 'telnet': 23,
57
- 'smtp': 25,
58
- 'http': 80,
59
- 'pop3': 110,
60
- 'imap': 143,
61
- 'snmp': 161,
62
- 'smb': 445,
63
- 'mssql': 1433,
64
- 'mysql': 3306,
65
- 'rdp': 3389,
66
- 'postgres': 5432,
67
- 'vnc': 5900,
68
- 'redis': 6379,
54
+ "ftp": 21,
55
+ "ssh": 22,
56
+ "telnet": 23,
57
+ "smtp": 25,
58
+ "http": 80,
59
+ "pop3": 110,
60
+ "imap": 143,
61
+ "snmp": 161,
62
+ "smb": 445,
63
+ "mssql": 1433,
64
+ "mysql": 3306,
65
+ "rdp": 3389,
66
+ "postgres": 5432,
67
+ "vnc": 5900,
68
+ "redis": 6379,
69
69
  }
70
-
70
+
71
71
  def parse_target(self, tool: str, target: str, args: Optional[List] = None) -> Dict:
72
72
  """
73
73
  Parse job target to extract host and port.
74
-
74
+
75
75
  Args:
76
76
  tool: Tool name (nmap, nuclei, hydra, etc.)
77
77
  target: Target string (IP, URL, domain, etc.)
78
78
  args: Additional arguments (list or dict)
79
-
79
+
80
80
  Returns:
81
81
  {
82
82
  'host': str,
@@ -85,270 +85,267 @@ class TargetParser:
85
85
  'service': str (optional),
86
86
  'protocol': str (optional)
87
87
  }
88
-
88
+
89
89
  Examples:
90
90
  parse_target('nmap', '10.0.0.5', ['-p', '22,80'])
91
91
  → {'host': '10.0.0.5', 'ports': [22, 80]}
92
-
92
+
93
93
  parse_target('nuclei', 'http://10.0.0.5:443')
94
94
  → {'host': '10.0.0.5', 'port': 443, 'protocol': 'https'}
95
-
95
+
96
96
  parse_target('hydra', '10.0.0.5', ['ssh'])
97
97
  → {'host': '10.0.0.5', 'port': 22, 'service': 'ssh'}
98
98
  """
99
99
  result = {}
100
-
100
+
101
101
  # Check if target is a URL
102
- if target.startswith(('http://', 'https://', 'ftp://', 'ftps://')):
102
+ if target.startswith(("http://", "https://", "ftp://", "ftps://")):
103
103
  url_info = self.extract_from_url(target)
104
104
  result.update(url_info)
105
105
  return result
106
-
106
+
107
107
  # Extract host and port from various formats
108
108
  host, port = self._extract_host_port(target)
109
- result['host'] = host
110
-
109
+ result["host"] = host
110
+
111
111
  if port:
112
- result['port'] = port
113
-
112
+ result["port"] = port
113
+
114
114
  # Tool-specific parsing
115
- if tool == 'nmap':
115
+ if tool == "nmap":
116
116
  result.update(self._parse_nmap_args(args))
117
- elif tool in ['nuclei', 'gobuster', 'wpscan']:
117
+ elif tool in ["nuclei", "gobuster", "wpscan"]:
118
118
  result.update(self._parse_web_tool_target(target))
119
- elif tool == 'hydra':
119
+ elif tool == "hydra":
120
120
  result.update(self._parse_hydra_args(target, args))
121
- elif tool == 'msf_auxiliary':
121
+ elif tool == "msf_auxiliary":
122
122
  result.update(self._parse_msf_args(args))
123
- elif tool == 'enum4linux':
124
- result['port'] = 445
125
- result['service'] = 'smb'
126
- elif tool == 'smbmap':
127
- result['port'] = 445
128
- result['service'] = 'smb'
129
- elif tool == 'sqlmap':
123
+ elif tool == "enum4linux":
124
+ result["port"] = 445
125
+ result["service"] = "smb"
126
+ elif tool == "smbmap":
127
+ result["port"] = 445
128
+ result["service"] = "smb"
129
+ elif tool == "sqlmap":
130
130
  result.update(self._parse_sqlmap_target(target))
131
- elif tool == 'whois':
131
+ elif tool == "whois":
132
132
  # Whois is domain-level, no port
133
133
  pass
134
- elif tool == 'dnsrecon':
135
- result['port'] = 53
136
- result['service'] = 'dns'
137
- elif tool == 'theharvester':
134
+ elif tool == "dnsrecon":
135
+ result["port"] = 53
136
+ result["service"] = "dns"
137
+ elif tool == "theharvester":
138
138
  # OSINT, no specific port
139
139
  pass
140
-
140
+
141
141
  # If we have a port but no service, infer service
142
- if result.get('port') and not result.get('service'):
143
- result['service'] = self.infer_service_from_port(result['port'])
144
-
142
+ if result.get("port") and not result.get("service"):
143
+ result["service"] = self.infer_service_from_port(result["port"])
144
+
145
145
  # If we have a service but no port, infer port
146
- if result.get('service') and not result.get('port'):
147
- result['port'] = self.infer_port_from_service(result['service'])
148
-
146
+ if result.get("service") and not result.get("port"):
147
+ result["port"] = self.infer_port_from_service(result["service"])
148
+
149
149
  return result
150
-
150
+
151
151
  def _extract_host_port(self, target: str) -> tuple:
152
152
  """
153
153
  Extract host and port from target string.
154
-
154
+
155
155
  Handles:
156
156
  - 10.0.0.5
157
157
  - 10.0.0.5:3306
158
158
  - example.com
159
159
  - example.com:8080
160
-
160
+
161
161
  Returns:
162
162
  (host, port) tuple
163
163
  """
164
164
  # Check for IP:port or domain:port
165
- match = re.match(r'^([a-zA-Z0-9\.\-]+):(\d+)$', target)
165
+ match = re.match(r"^([a-zA-Z0-9\.\-]+):(\d+)$", target)
166
166
  if match:
167
167
  return match.group(1), int(match.group(2))
168
-
168
+
169
169
  # Just host
170
170
  return target, None
171
-
171
+
172
172
  def extract_from_url(self, url: str) -> Dict:
173
173
  """
174
174
  Parse URL to extract host, port, protocol.
175
-
175
+
176
176
  Examples:
177
177
  'http://10.0.0.5' → {'host': '10.0.0.5', 'port': 80, 'protocol': 'http'}
178
178
  'https://10.0.0.5:8443' → {'host': '10.0.0.5', 'port': 8443, 'protocol': 'https'}
179
179
  'ftp://10.0.0.5:21' → {'host': '10.0.0.5', 'port': 21, 'protocol': 'ftp'}
180
180
  """
181
181
  parsed = urlparse(url)
182
-
183
- result = {
184
- 'host': parsed.hostname or parsed.netloc,
185
- 'protocol': parsed.scheme
186
- }
187
-
182
+
183
+ result = {"host": parsed.hostname or parsed.netloc, "protocol": parsed.scheme}
184
+
188
185
  # Determine port
189
186
  if parsed.port:
190
- result['port'] = parsed.port
187
+ result["port"] = parsed.port
191
188
  else:
192
189
  # Use default port for protocol
193
- if parsed.scheme == 'http':
194
- result['port'] = 80
195
- elif parsed.scheme == 'https':
196
- result['port'] = 443
197
- elif parsed.scheme == 'ftp':
198
- result['port'] = 21
199
- elif parsed.scheme == 'ftps':
200
- result['port'] = 990
201
-
190
+ if parsed.scheme == "http":
191
+ result["port"] = 80
192
+ elif parsed.scheme == "https":
193
+ result["port"] = 443
194
+ elif parsed.scheme == "ftp":
195
+ result["port"] = 21
196
+ elif parsed.scheme == "ftps":
197
+ result["port"] = 990
198
+
202
199
  # Infer service from protocol
203
- if parsed.scheme in ['http', 'https']:
204
- result['service'] = 'http'
205
- elif parsed.scheme in ['ftp', 'ftps']:
206
- result['service'] = 'ftp'
207
-
200
+ if parsed.scheme in ["http", "https"]:
201
+ result["service"] = "http"
202
+ elif parsed.scheme in ["ftp", "ftps"]:
203
+ result["service"] = "ftp"
204
+
208
205
  return result
209
-
206
+
210
207
  def _parse_nmap_args(self, args: Optional[List]) -> Dict:
211
208
  """
212
209
  Parse Nmap arguments to extract port info.
213
-
210
+
214
211
  Examples:
215
212
  ['-p', '22,80,443'] → {'ports': [22, 80, 443]}
216
213
  ['-p', '1-1000'] → {'ports': range(1, 1001)}
217
214
  ['-sV', '-p-'] → {} # Full port scan
218
215
  """
219
216
  result = {}
220
-
217
+
221
218
  if not args:
222
219
  return result
223
-
220
+
224
221
  # Look for -p flag
225
222
  try:
226
- p_idx = args.index('-p')
223
+ p_idx = args.index("-p")
227
224
  if p_idx + 1 < len(args):
228
225
  port_spec = args[p_idx + 1]
229
-
226
+
230
227
  # Handle full port scan
231
- if port_spec == '-':
228
+ if port_spec == "-":
232
229
  return result
233
-
230
+
234
231
  # Handle comma-separated ports
235
- if ',' in port_spec:
232
+ if "," in port_spec:
236
233
  ports = []
237
- for p in port_spec.split(','):
238
- if '-' in p:
234
+ for p in port_spec.split(","):
235
+ if "-" in p:
239
236
  # Range like 20-25
240
- start, end = map(int, p.split('-'))
237
+ start, end = map(int, p.split("-"))
241
238
  ports.extend(range(start, end + 1))
242
239
  else:
243
240
  ports.append(int(p))
244
- result['ports'] = ports
245
-
241
+ result["ports"] = ports
242
+
246
243
  # Handle port range
247
- elif '-' in port_spec:
248
- start, end = map(int, port_spec.split('-'))
249
- result['ports'] = list(range(start, end + 1))
250
-
244
+ elif "-" in port_spec:
245
+ start, end = map(int, port_spec.split("-"))
246
+ result["ports"] = list(range(start, end + 1))
247
+
251
248
  # Single port
252
249
  else:
253
- result['ports'] = [int(port_spec)]
254
-
250
+ result["ports"] = [int(port_spec)]
251
+
255
252
  except (ValueError, IndexError):
256
253
  pass
257
-
254
+
258
255
  return result
259
-
256
+
260
257
  def _parse_web_tool_target(self, target: str) -> Dict:
261
258
  """Parse web tool targets (nuclei, gobuster, wpscan)."""
262
- if target.startswith(('http://', 'https://')):
259
+ if target.startswith(("http://", "https://")):
263
260
  return self.extract_from_url(target)
264
261
  return {}
265
-
262
+
266
263
  def _parse_hydra_args(self, target: str, args: Optional[List]) -> Dict:
267
264
  """
268
265
  Parse Hydra arguments.
269
-
266
+
270
267
  Examples:
271
268
  target='10.0.0.5', args=['ssh'] → {'port': 22, 'service': 'ssh'}
272
269
  target='10.0.0.5', args=['mysql'] → {'port': 3306, 'service': 'mysql'}
273
270
  """
274
271
  result = {}
275
-
272
+
276
273
  if args and len(args) > 0:
277
274
  # First arg is usually the service
278
275
  service = args[0].lower()
279
- result['service'] = service
280
- result['port'] = self.infer_port_from_service(service)
281
-
276
+ result["service"] = service
277
+ result["port"] = self.infer_port_from_service(service)
278
+
282
279
  return result
283
-
280
+
284
281
  def _parse_msf_args(self, args: Optional[List]) -> Dict:
285
282
  """
286
283
  Parse Metasploit auxiliary module args.
287
-
284
+
288
285
  Args can be:
289
286
  - List: ['scanner/mysql/mysql_login']
290
287
  - Dict: {'module': 'scanner/mysql/mysql_login'}
291
-
288
+
292
289
  Examples:
293
290
  {'module': 'scanner/mysql/mysql_login'} → {'service': 'mysql', 'port': 3306}
294
291
  {'module': 'scanner/ssh/ssh_login'} → {'service': 'ssh', 'port': 22}
295
292
  """
296
293
  result = {}
297
-
294
+
298
295
  if not args:
299
296
  return result
300
-
297
+
301
298
  # Extract module name
302
299
  module = None
303
300
  if isinstance(args, dict):
304
- module = args.get('module')
301
+ module = args.get("module")
305
302
  elif isinstance(args, list) and len(args) > 0:
306
303
  module = args[0]
307
-
304
+
308
305
  if module:
309
306
  msf_info = self.parse_msf_module(module)
310
307
  result.update(msf_info)
311
-
308
+
312
309
  return result
313
-
310
+
314
311
  def _parse_sqlmap_target(self, target: str) -> Dict:
315
312
  """
316
313
  Parse SQLMap target (usually a URL).
317
-
314
+
318
315
  Examples:
319
316
  'http://10.0.0.5/page.php?id=1' → {'host': '10.0.0.5', 'port': 80, 'service': 'http'}
320
317
  """
321
- if target.startswith(('http://', 'https://')):
318
+ if target.startswith(("http://", "https://")):
322
319
  return self.extract_from_url(target)
323
320
  return {}
324
-
321
+
325
322
  def parse_msf_module(self, module: str) -> Dict:
326
323
  """
327
324
  Extract service info from MSF module name.
328
-
325
+
329
326
  Examples:
330
327
  'scanner/mysql/mysql_login' → {'service': 'mysql', 'port': 3306}
331
328
  'scanner/ssh/ssh_login' → {'service': 'ssh', 'port': 22}
332
329
  'exploit/unix/ftp/vsftpd_234_backdoor' → {'service': 'ftp', 'port': 21}
333
330
  """
334
331
  result = {}
335
-
332
+
336
333
  # Extract service name from module path
337
- parts = module.split('/')
338
-
334
+ parts = module.split("/")
335
+
339
336
  for part in parts:
340
337
  part_lower = part.lower()
341
338
  if part_lower in self.MSF_PATTERNS:
342
- result['service'] = part_lower
343
- result['port'] = self.MSF_PATTERNS[part_lower]
339
+ result["service"] = part_lower
340
+ result["port"] = self.MSF_PATTERNS[part_lower]
344
341
  break
345
-
342
+
346
343
  return result
347
-
344
+
348
345
  def infer_port_from_service(self, service: str) -> Optional[int]:
349
346
  """
350
347
  Infer default port from service name.
351
-
348
+
352
349
  Examples:
353
350
  'ssh' → 22
354
351
  'mysql' → 3306
@@ -357,11 +354,11 @@ class TargetParser:
357
354
  """
358
355
  service_lower = service.lower()
359
356
  return self.SERVICE_PORTS.get(service_lower)
360
-
357
+
361
358
  def infer_service_from_port(self, port: int) -> Optional[str]:
362
359
  """
363
360
  Infer service from common port.
364
-
361
+
365
362
  Examples:
366
363
  22 → 'ssh'
367
364
  3306 → 'mysql'
@@ -15,10 +15,10 @@ from souleyez.licensing.validator import (
15
15
  )
16
16
 
17
17
  __all__ = [
18
- 'LicenseValidator',
19
- 'LicenseInfo',
20
- 'validate_license',
21
- 'activate_license',
22
- 'get_active_license',
23
- 'deactivate_license',
18
+ "LicenseValidator",
19
+ "LicenseInfo",
20
+ "validate_license",
21
+ "activate_license",
22
+ "get_active_license",
23
+ "deactivate_license",
24
24
  ]
@@ -28,9 +28,10 @@ def _add_base64_padding(data: str) -> str:
28
28
  """Add padding to base64 string if missing."""
29
29
  padding = 4 - len(data) % 4
30
30
  if padding != 4:
31
- data += '=' * padding
31
+ data += "=" * padding
32
32
  return data
33
33
 
34
+
34
35
  # Ed25519 public key for license verification (Base64 encoded)
35
36
  # Private key is kept secure by the license issuer
36
37
  # This public key can only VERIFY signatures, not create them
@@ -42,6 +43,7 @@ MCowBQYDK2VwAyEABS0eqd9OPCtqOvQI1Aw8vGnXiX1qecBjZ0UY7esPk1I=
42
43
  @dataclass
43
44
  class LicenseInfo:
44
45
  """Validated license information."""
46
+
45
47
  email: str
46
48
  tier: str
47
49
  issued_at: datetime
@@ -128,7 +130,7 @@ class LicenseValidator:
128
130
  expires_at=None,
129
131
  machine_id=None,
130
132
  is_valid=False,
131
- error=f"Invalid license format: {e}"
133
+ error=f"Invalid license format: {e}",
132
134
  )
133
135
 
134
136
  # Extract components
@@ -143,7 +145,7 @@ class LicenseValidator:
143
145
  expires_at=None,
144
146
  machine_id=None,
145
147
  is_valid=False,
146
- error="Missing license data or signature"
148
+ error="Missing license data or signature",
147
149
  )
148
150
 
149
151
  # Verify signature
@@ -155,7 +157,7 @@ class LicenseValidator:
155
157
  expires_at=None,
156
158
  machine_id=None,
157
159
  is_valid=False,
158
- error="Invalid license signature"
160
+ error="Invalid license signature",
159
161
  )
160
162
 
161
163
  # Parse dates
@@ -173,7 +175,7 @@ class LicenseValidator:
173
175
  expires_at=expires_at,
174
176
  machine_id=data.get("machine_id"),
175
177
  is_valid=False,
176
- error="License has expired"
178
+ error="License has expired",
177
179
  )
178
180
 
179
181
  # Check machine binding if present
@@ -187,7 +189,7 @@ class LicenseValidator:
187
189
  expires_at=expires_at,
188
190
  machine_id=data.get("machine_id"),
189
191
  is_valid=False,
190
- error="License is bound to a different machine"
192
+ error="License is bound to a different machine",
191
193
  )
192
194
 
193
195
  # License is valid
@@ -198,7 +200,7 @@ class LicenseValidator:
198
200
  expires_at=expires_at,
199
201
  machine_id=data.get("machine_id"),
200
202
  is_valid=True,
201
- error=None
203
+ error=None,
202
204
  )
203
205
 
204
206
  except Exception as e:
@@ -209,7 +211,7 @@ class LicenseValidator:
209
211
  expires_at=None,
210
212
  machine_id=None,
211
213
  is_valid=False,
212
- error=f"License validation error: {e}"
214
+ error=f"License validation error: {e}",
213
215
  )
214
216
 
215
217
  def _verify_signature(self, data: dict, signature_b64: str) -> bool:
@@ -224,7 +226,9 @@ class LicenseValidator:
224
226
  True if signature is valid
225
227
  """
226
228
  try:
227
- from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
229
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import (
230
+ Ed25519PublicKey,
231
+ )
228
232
  from cryptography.hazmat.primitives.serialization import load_pem_public_key
229
233
 
230
234
  # Check if public key is configured
@@ -233,12 +237,10 @@ class LicenseValidator:
233
237
  return self._verify_dev_signature(data, signature_b64)
234
238
 
235
239
  # Load public key
236
- public_key = load_pem_public_key(
237
- LICENSE_PUBLIC_KEY.encode()
238
- )
240
+ public_key = load_pem_public_key(LICENSE_PUBLIC_KEY.encode())
239
241
 
240
242
  # Recreate the signed message
241
- message = json.dumps(data, sort_keys=True, separators=(',', ':')).encode()
243
+ message = json.dumps(data, sort_keys=True, separators=(",", ":")).encode()
242
244
 
243
245
  # Decode signature
244
246
  signature = base64.urlsafe_b64decode(_add_base64_padding(signature_b64))
@@ -259,12 +261,8 @@ class LicenseValidator:
259
261
 
260
262
  DEV_SECRET = "souleyez-dev-license-key-for-testing-only"
261
263
 
262
- message = json.dumps(data, sort_keys=True, separators=(',', ':')).encode()
263
- expected = hmac.new(
264
- DEV_SECRET.encode(),
265
- message,
266
- hashlib.sha256
267
- ).digest()
264
+ message = json.dumps(data, sort_keys=True, separators=(",", ":")).encode()
265
+ expected = hmac.new(DEV_SECRET.encode(), message, hashlib.sha256).digest()
268
266
 
269
267
  try:
270
268
  actual = base64.urlsafe_b64decode(_add_base64_padding(signature_b64))