@@ -32,7 +32,6 @@ def __init__(self, args, db, host):
3232 self .domain = None
3333 self .server_os = None
3434 self .iosettings = RDPIOSettings ()
35- self .iosettings .channels = []
3635 self .iosettings .video_out_format = VIDEO_FORMAT .RAW
3736 self .iosettings .clipboard_use_pyperclip = False
3837 self .protoflags_nla = [
@@ -407,7 +406,9 @@ async def _send_win_r(self):
407406
408407 async def execute_cmd (self , payload , encoding = None , capture_screenshot = False ):
409408 """Execute a command using cmd.exe"""
410- self .logger .debug (f"Executing command: { payload } " )
409+ # Append | clip to send output to clipboard
410+ payload_with_clip = f"{ payload } | clip & exit"
411+ self .logger .debug (f"Executing command: { payload_with_clip } " )
411412
412413 # Create a connection
413414 try :
@@ -416,6 +417,28 @@ async def execute_cmd(self, payload, encoding=None, capture_screenshot=False):
416417 except Exception as e :
417418 self .logger .debug (f"Error connecting to RDP: { e !s} " )
418419 return None
420+
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" )
419442
420443 # Wait for desktop to be available
421444 await asyncio .sleep (self .args .cmd_delay )
@@ -438,41 +461,27 @@ async def execute_cmd(self, payload, encoding=None, capture_screenshot=False):
438461 await self ._send_enter ()
439462 await asyncio .sleep (self .args .cmd_delay )
440463
441- # Type the command
442- self .logger .debug (f"Typing command: { payload } " )
443- await self ._send_keystrokes (payload )
464+ # Type the command with | clip
465+ self .logger .debug (f"Typing command: { payload_with_clip } " )
466+ await self ._send_keystrokes (payload_with_clip )
444467 await self ._send_enter ()
445468
469+ # Wait for command to execute
446470 await asyncio .sleep (self .args .cmd_delay )
471+
472+ # Get the current clipboard text
473+ self .logger .debug ("Getting clipboard content..." )
474+ clipboard_text = await self .conn .get_current_clipboard_text ()
447475
448- # Take a screenshot if requested
449- if capture_screenshot and self .conn is not None :
450- self .logger .highlight ("Waiting for screen to update..." )
451- await asyncio .sleep (self .args .screentime ) # Additional wait to ensure screen is updated
452-
453- self .logger .debug (f"Desktop buffer has data: { self .conn .desktop_buffer_has_data } " )
454- if self .conn .desktop_buffer_has_data :
455- try :
456- self .logger .debug ("Capturing command output screenshot" )
457- buffer = self .conn .get_desktop_buffer (VIDEO_FORMAT .PIL )
458- screenshots_dir = os .path .expanduser ("~/.nxc/screenshots" )
459- os .makedirs (screenshots_dir , exist_ok = True ) # Ensure the directory exists
460- filename = os .path .join (screenshots_dir , f"{ self .hostname } _{ self .host } _{ datetime .now ().strftime ('%Y-%m-%d_%H%M%S' )} .png" )
461- buffer .save (filename , "png" )
462- self .logger .highlight (f"Command output screenshot saved: { filename } " )
463- except Exception as e :
464- self .logger .debug (f"Error taking screenshot: { e !s} " )
465- else :
466- self .logger .debug ("No desktop buffer data available for screenshot" )
467-
468- # Exit CMD
469- self .logger .debug ("Exiting CMD" )
470- await self ._send_keystrokes ("exit" )
471- await self ._send_enter ()
472- await asyncio .sleep (0.5 )
473-
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+
474483 self .logger .debug ("Command execution completed" )
475- return True
484+ return clipboard_text
476485
477486 finally :
478487 # Always clean up the connection
@@ -485,7 +494,9 @@ async def execute_cmd(self, payload, encoding=None, capture_screenshot=False):
485494
486495 async def execute_ps (self , payload , capture_screenshot = False ):
487496 """Execute a command using PowerShell"""
488- self .logger .debug (f"Executing PowerShell command: { payload } " )
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 } " )
489500
490501 # Create a connection
491502 try :
@@ -494,6 +505,28 @@ async def execute_ps(self, payload, capture_screenshot=False):
494505 except Exception as e :
495506 self .logger .debug (f"Error connecting to RDP: { e !s} " )
496507 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
515+ 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" )
497530
498531 # Wait for desktop to be available
499532 await asyncio .sleep (self .args .cmd_delay )
@@ -516,42 +549,27 @@ async def execute_ps(self, payload, capture_screenshot=False):
516549 await self ._send_enter ()
517550 await asyncio .sleep (self .args .cmd_delay )
518551
519- # Type the PowerShell command
520- self .logger .debug (f"Typing PowerShell command: { payload } " )
521- await self ._send_keystrokes (payload )
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 )
522555 await self ._send_enter ()
523556
524- # Wait longer for command to complete execution
525- await asyncio .sleep (self .args .cmd_delay ) # Increased wait time to ensure command completes
526-
527- # Take a screenshot if requested
528- if capture_screenshot and self .conn is not None :
529- self .logger .highlight ("Waiting for screen to update..." )
530- await asyncio .sleep (self .args .screentime ) # Additional wait to ensure screen is updated
531-
532- self .logger .debug (f"Desktop buffer has data: { self .conn .desktop_buffer_has_data } " )
533- if self .conn .desktop_buffer_has_data :
534- try :
535- self .logger .debug ("Capturing PowerShell command output screenshot" )
536- buffer = self .conn .get_desktop_buffer (VIDEO_FORMAT .PIL )
537- screenshots_dir = os .path .expanduser ("~/.nxc/screenshots" )
538- os .makedirs (screenshots_dir , exist_ok = True ) # Ensure the directory exists
539- filename = os .path .join (screenshots_dir , f"{ self .hostname } _{ self .host } _{ datetime .now ().strftime ('%Y-%m-%d_%H%M%S' )} .png" )
540- buffer .save (filename , "png" )
541- self .logger .highlight (f"PowerShell command output screenshot saved: { filename } " )
542- except Exception as e :
543- self .logger .debug (f"Error taking screenshot: { e !s} " )
544- else :
545- self .logger .debug ("No desktop buffer data available for screenshot" )
546-
547- # Exit PowerShell
548- self .logger .debug ("Exiting PowerShell" )
549- await self ._send_keystrokes ("exit" )
550- await self ._send_enter ()
551- await asyncio .sleep (0.5 )
557+ # Wait for command to execute
558+ await asyncio .sleep (self .args .cmd_delay )
559+
560+ # Get the current clipboard text
561+ self .logger .debug ("Getting clipboard content..." )
562+ clipboard_text = await self .conn .get_current_clipboard_text ()
552563
553- self .logger .debug ("PowerShell command execution completed" )
554- return True
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" )
570+
571+ self .logger .debug ("Command execution completed" )
572+ return clipboard_text
555573
556574 finally :
557575 if self .conn is not None :
@@ -578,16 +596,16 @@ def execute(self, payload=None, shell_type="cmd"):
578596 if capture_screenshot :
579597 self .logger .info ("Will capture screenshot of command output" )
580598
581- self .logger .success (f"Executing { shell_type } command: { payload } with delay { self .args .cmd_delay } seconds" )
599+ self .logger .success (f"Executing command: { payload } with delay { self .args .cmd_delay } seconds" )
582600
583601 try :
584602 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 ))
585603
586604 if result :
587- self .logger .success ("Command execution completed" )
605+ self .logger .debug ("Command execution completed" )
588606 return result
589607 except Exception as e :
590- self .logger .debug (f"Command execution error: { e !s} " )
608+ self .logger .error (f"Command execution error: { e !s} " )
591609 if shell_type == "cmd" :
592610 self .logger .info ("Cannot execute command via cmd - now switching to PowerShell to attempt execution" )
593611 try :
0 commit comments