@@ -398,16 +398,18 @@ async def _send_win_r(self):
398398
399399 self .logger .debug ("Win+R sent successfully" )
400400 return True
401+ except (ConnectionResetError , ConnectionError , OSError ) as e :
402+ self .logger .debug (f"Connection error while waiting for clipboard: { e !s} " )
403+ self .logger .fail ("Connection was reset by the remote host" )
404+ return False
401405 except Exception as e :
402406 self .logger .debug (f"Error sending Win+R: { e !s} " )
403-
404407 self .logger .debug ("Using fallback approach for opening command prompt" )
405408 return False
406409
407- async def execute_cmd (self , payload , encoding = None , capture_screenshot = False ):
408- """Execute a command using cmd.exe"""
410+ async def execute_shell (self , payload , get_output , shell_type ):
409411 # Append | clip to send output to clipboard
410- payload_with_clip = f"{ payload } | clip & exit"
412+ payload_with_clip = f"{ payload } | clip & exit" if shell_type == "cmd" else f" { payload } | clip; exit"
411413 self .logger .debug (f"Executing command: { payload_with_clip } " )
412414
413415 # Create a connection
@@ -418,160 +420,98 @@ async def execute_cmd(self, payload, encoding=None, capture_screenshot=False):
418420 self .logger .debug (f"Error connecting to RDP: { e !s} " )
419421 return None
420422
421- self .logger .debug ("Waiting for clipboard to be ready..." )
422- clipboard_ready = False
423- await asyncio .sleep (self .args .cmd_delay )
424-
425- timeout_counter = 0
426- while not clipboard_ready and timeout_counter < 100 : # 10 second timeout
427- try :
428- data = await asyncio .wait_for (self .conn .ext_out_queue .get (), timeout = 0.1 )
429- if hasattr (data , "type" ) and data .type .name == "CLIPBOARD_READY" :
430- clipboard_ready = True
431- self .logger .debug ("Clipboard is ready!" )
432- break
433- except asyncio .TimeoutError :
434- timeout_counter += 1
435- continue
436- except Exception as e :
437- self .logger .debug (f"Error waiting for clipboard: { e !s} " )
438- break
439-
440- if not clipboard_ready :
441- self .logger .fail ("Warning: Clipboard may not be fully initialized, no output can be retrieved" )
442-
443- # Wait for desktop to be available
444- await asyncio .sleep (self .args .cmd_delay )
445-
446423 try :
447- # Try to open Run dialog using Windows+R
448- self .logger .debug ("Attempting to open Run dialog" )
449- win_r_success = await self ._send_win_r ()
450-
451- if win_r_success :
452- # Type cmd.exe in Run dialog
453- self .logger .debug ("Launching cmd.exe via Run dialog" )
454- await self ._send_keystrokes ("cmd.exe" )
455- await self ._send_enter ()
456- await asyncio .sleep (self .args .cmd_delay ) # Wait for cmd window to open
457- else :
458- # Fallback: Try direct command typing (assumes cmd may already be open)
459- self .logger .debug ("Sending cmd.exe command directly" )
460- await self ._send_keystrokes ("cmd.exe" )
461- await self ._send_enter ()
424+ if get_output :
425+ self .logger .debug ("Waiting for clipboard to be ready..." )
426+ clipboard_ready = False
462427 await asyncio .sleep (self .args .cmd_delay )
463-
464- # Type the command with | clip
465- self .logger .debug (f"Typing command: { payload_with_clip } " )
466- await self ._send_keystrokes (payload_with_clip )
467- await self ._send_enter ()
468-
469- # Wait for command to execute
470- await asyncio .sleep (self .args .cmd_delay )
471428
472- # Get the current clipboard text
473- self .logger .debug ("Getting clipboard content..." )
474- clipboard_text = await self .conn .get_current_clipboard_text ()
475-
476- if clipboard_text :
477- self .logger .debug ("Command output retrieved from clipboard:" )
478- for line in clipboard_text .lstrip ().strip ("\n " ).splitlines ():
479- self .logger .highlight (line )
480- else :
481- self .logger .warning ("Clipboard is empty or contains non-text data" )
482-
483- self .logger .debug ("Command execution completed" )
484- return clipboard_text
429+ timeout_counter = 0
430+ while not clipboard_ready and timeout_counter < 100 : # 10 second timeout
431+ try :
432+ data = await asyncio .wait_for (self .conn .ext_out_queue .get (), timeout = 0.1 )
433+ if hasattr (data , "type" ) and data .type .name == "CLIPBOARD_READY" :
434+ clipboard_ready = True
435+ self .logger .debug ("Clipboard is ready!" )
436+ break
437+ except asyncio .TimeoutError :
438+ timeout_counter += 1
439+ continue
440+ except (ConnectionResetError , ConnectionError , OSError ) as e :
441+ self .logger .debug (f"Connection error while waiting for clipboard: { e !s} " )
442+ self .logger .fail ("Connection was reset by the remote host" )
443+ return ""
444+ except Exception as e :
445+ self .logger .debug (f"Error waiting for clipboard: { e !s} " )
446+ self .logger .fail ("Warning: Clipboard may not be fully initialized, no output can be retrieved" )
447+ return ""
448+
449+ # Wait for desktop to be available
450+ await asyncio .sleep (self .args .cmd_delay )
485451
486- finally :
487- # Always clean up the connection
488- if self .conn is not None :
489- self .logger .debug ("Terminating RDP connection" )
490- try :
491- await self .conn .terminate ()
492- except Exception as e :
493- self .logger .debug (f"Error terminating connection: { e !s} " )
494-
495- async def execute_ps (self , payload , capture_screenshot = False ):
496- """Execute a command using PowerShell"""
497- # Append | clip to send output to clipboard
498- payload_with_clip = f"{ payload } | clip & exit"
499- self .logger .debug (f"Executing PowerShell command: { payload_with_clip } " )
500-
501- # Create a connection
502- try :
503- self .conn = RDPConnection (iosettings = self .iosettings , target = self .target , credentials = self .auth )
504- await self .connect_rdp ()
505- except Exception as e :
506- self .logger .debug (f"Error connecting to RDP: { e !s} " )
507- return None
508-
509- self .logger .debug ("Waiting for clipboard to be ready..." )
510- clipboard_ready = False
511- await asyncio .sleep (self .args .cmd_delay )
512-
513- timeout_counter = 0
514- while not clipboard_ready and timeout_counter < 100 : # 10 second timeout
515452 try :
516- data = await asyncio .wait_for (self .conn .ext_out_queue .get (), timeout = 0.1 )
517- if hasattr (data , "type" ) and data .type .name == "CLIPBOARD_READY" :
518- clipboard_ready = True
519- self .logger .debug ("Clipboard is ready!" )
520- break
521- except asyncio .TimeoutError :
522- timeout_counter += 1
523- continue
524- except Exception as e :
525- self .logger .debug (f"Error waiting for clipboard: { e !s} " )
526- break
527-
528- if not clipboard_ready :
529- self .logger .fail ("Warning: Clipboard may not be fully initialized, no output can be retrieved" )
530-
531- # Wait for desktop to be available
532- await asyncio .sleep (self .args .cmd_delay )
533-
534- try :
535- # Try to open Run dialog using Windows+R
536- self .logger .debug ("Attempting to open Run dialog" )
537- win_r_success = await self ._send_win_r ()
453+ # Try to open Run dialog using Windows+R
454+ self .logger .debug ("Attempting to open Run dialog" )
455+ win_r_success = await self ._send_win_r ()
456+
457+ if win_r_success :
458+ self .logger .debug (f"Launching { shell_type } via Run dialog" )
459+ await self ._send_keystrokes (f"{ shell_type } .exe" )
460+ await self ._send_enter ()
461+ await asyncio .sleep (self .args .cmd_delay ) # Wait for cmd window to open
462+ else :
463+ # Fallback: Try direct command typing (assumes cmd may already be open)
464+ self .logger .debug (f"Sending { shell_type } command directly" )
465+ await self ._send_keystrokes (f"{ shell_type } .exe" )
466+ await self ._send_enter ()
467+ await asyncio .sleep (self .args .cmd_delay )
538468
539- if win_r_success :
540- # Type powershell in Run dialog
541- self .logger .debug ("Launching PowerShell via Run dialog" )
542- await self ._send_keystrokes ("powershell" )
543- await self ._send_enter ()
544- await asyncio .sleep (self .args .cmd_delay ) # Wait for PowerShell window to open
545- else :
546- # Fallback: Try direct PowerShell typing (assumes we might be at a prompt)
547- self .logger .debug ("Sending powershell command directly" )
548- await self ._send_keystrokes ("powershell" )
469+ # Type the command with | clip
470+ self .logger .debug (f"Typing command: { payload_with_clip } " )
471+ await self ._send_keystrokes (payload_with_clip )
549472 await self ._send_enter ()
473+
474+ # Wait for command to execute
550475 await asyncio .sleep (self .args .cmd_delay )
551-
552- # Type the PowerShell command with | clip
553- self .logger .debug (f"Typing PowerShell command: { payload_with_clip } " )
554- await self ._send_keystrokes (payload_with_clip )
555- await self ._send_enter ()
556-
557- # Wait for command to execute
558- await asyncio .sleep (self .args .cmd_delay )
559476
560- # Get the current clipboard text
561- self .logger .debug ("Getting clipboard content..." )
562- clipboard_text = await self .conn .get_current_clipboard_text ()
563-
564- if clipboard_text :
565- self .logger .debug ("PowerShell command output retrieved from clipboard:" )
566- for line in clipboard_text .strip ("\n " ):
567- self .logger .highlight (line )
568- else :
569- self .logger .warning ("Clipboard is empty or contains non-text data" )
477+ if get_output :
478+ # Get the current clipboard text
479+ self .logger .debug ("Getting clipboard content..." )
480+ clipboard_text = await self .conn .get_current_clipboard_text ()
481+
482+ if clipboard_text :
483+ self .logger .debug ("Command output retrieved from clipboard:" )
484+ for line in clipboard_text .lstrip ().strip ("\n " ).splitlines ():
485+ self .logger .highlight (line )
486+ else :
487+ self .logger .fail ("Clipboard is empty or contains non-text data" )
488+ return clipboard_text
570489
571- self .logger .debug ("Command execution completed" )
572- return clipboard_text
573-
490+ self .logger .debug ("Command execution completed" )
491+ return None
492+
493+ except (ConnectionResetError , ConnectionError , OSError ) as e :
494+ self .logger .debug (f"Connection error during command execution: { e !s} " )
495+ self .logger .fail ("Connection was reset by the remote host during command execution" )
496+ return None
497+ except Exception as e :
498+ self .logger .debug (f"Error during command execution: { e !s} " )
499+ if "cannot unpack non-iterable NoneType object" in str (e ):
500+ self .logger .fail ("RDP connection was terminated unexpectedly" )
501+ else :
502+ self .logger .fail (f"Command execution failed: { e !s} " )
503+ return None
504+
505+ except (ConnectionResetError , ConnectionError , OSError ) as e :
506+ self .logger .debug (f"Connection error: { e !s} " )
507+ self .logger .fail ("Connection was reset by the remote host" )
508+ return None
509+ except Exception as e :
510+ self .logger .debug (f"Unexpected error: { e !s} " )
511+ self .logger .fail (f"Command execution failed: { e !s} " )
512+ return None
574513 finally :
514+ # Always clean up the connection
575515 if self .conn is not None :
576516 self .logger .debug ("Terminating RDP connection" )
577517 try :
@@ -584,22 +524,12 @@ def execute(self, payload=None, shell_type="cmd"):
584524 if not payload :
585525 payload = self .args .execute
586526
587-
588- # Check if screenshot is requested
589- capture_screenshot = hasattr (self .args , "screenshot" ) and self .args .screenshot
590-
591- # Debug the args object to verify the screenshot flag
592- self .logger .debug (f"Args object has screenshot attribute: { hasattr (self .args , 'screenshot' )} " )
593- if hasattr (self .args , "screenshot" ):
594- self .logger .debug (f"Screenshot flag value: { self .args .screenshot } " )
595-
596- if capture_screenshot :
597- self .logger .info ("Will capture screenshot of command output" )
527+ get_output = bool (not self .args .no_output )
598528
599529 self .logger .success (f"Executing command: { payload } with delay { self .args .cmd_delay } seconds" )
600530
601531 try :
602- result = asyncio .run (self .execute_cmd (payload , capture_screenshot = capture_screenshot )) if shell_type == "cmd" else asyncio . run ( self . execute_ps ( payload , capture_screenshot = capture_screenshot ))
532+ result = asyncio .run (self .execute_shell (payload , get_output , shell_type ))
603533
604534 if result :
605535 self .logger .debug ("Command execution completed" )
0 commit comments