1- import contextlib
21import os
2+ import contextlib
33from time import sleep
44from datetime import datetime , timedelta
55from impacket .dcerpc .v5 .dtypes import NULL
@@ -13,20 +13,35 @@ class NXCModule:
1313 """
1414 Execute a scheduled task remotely as a already connected user by @Defte_
1515 Thanks @Shad0wC0ntr0ller for the idea of removing the hardcoded date that could be used as an IOC
16+ Modified by @Defte_ so that output on multiples lines are printed correctly (28/04/2025)
17+ Modified by @Defte_ so that we can upload a custom binary to execute using the BINARY option (28/04/2025)
1618 """
1719
1820 def options (self , context , module_options ):
1921 r"""
22+ BINARY Upload the binary to be executed by CMD
2023 CMD Command to execute
2124 USER User to execute command as
2225 TASK OPTIONAL: Set a name for the scheduled task name
2326 FILE OPTIONAL: Set a name for the command output file
2427 LOCATION OPTIONAL: Set a location for the command output file (e.g. '\tmp\')
28+
29+ Example:
30+ -------
31+ nxc smb <ip> -u <user> -p <password> -M schtask_as -o USER=Administrator CMD=whoami
32+ nxc smb <ip> -u <user> -p <password> -M schtask_as -o USER=Administrator CMD='bin.exe --option' BINARY=bin.exe
2533 """
26- self .cmd = self .user = self .task = self .file = self .location = self .time = None
34+ self .cmd = self .binary = self .user = self .task = self .file = self .location = self .time = None
35+ self .share = "C$"
36+ self .tmp_dir = "C:\\ Windows\\ Temp\\ "
37+ self .tmp_share = self .tmp_dir .split (":" )[1 ]
38+
2739 if "CMD" in module_options :
2840 self .cmd = module_options ["CMD" ]
2941
42+ if "BINARY" in module_options :
43+ self .binary = module_options ["BINARY" ]
44+
3045 if "USER" in module_options :
3146 self .user = module_options ["USER" ]
3247
@@ -47,13 +62,32 @@ def options(self, context, module_options):
4762
4863 def on_admin_login (self , context , connection ):
4964 self .logger = context .log
65+
5066 if self .cmd is None :
5167 self .logger .fail ("You need to specify a CMD to run" )
5268 return 1
69+
5370 if self .user is None :
5471 self .logger .fail ("You need to specify a USER to run the command as" )
5572 return 1
5673
74+ if self .binary :
75+ if not os .path .isfile (self .binary ):
76+ self .logger .fail (f"Cannot find { self .binary } " )
77+ return 1
78+ else :
79+ self .logger .display (f"Uploading { self .binary } " )
80+ with open (self .binary , "rb" ) as binary_to_upload :
81+ try :
82+ self .binary_name = os .path .basename (self .binary )
83+ connection .conn .putFile (self .share , f"{ self .tmp_share } { self .binary_name } " , binary_to_upload .read )
84+ self .logger .success (f"Binary { self .binary_name } successfully uploaded in { self .tmp_share } { self .binary_name } " )
85+ except Exception as e :
86+ self .logger .fail (f"Error writing file to share { self .tmp_share } : { e } " )
87+ return 1
88+
89+ # Returnes self.cmd or \Windows\temp\BinToExecute.exe depending if BINARY=BinToExecute.exe
90+ self .cmd = self .cmd if not self .binary else f"{ self .tmp_share } { self .cmd } "
5791 self .logger .display ("Connecting to the remote Service control endpoint" )
5892 try :
5993 exec_method = TSCH_EXEC (
@@ -87,7 +121,8 @@ def on_admin_login(self, context, connection):
87121 # Required to decode specific French characters otherwise it'll print b"<result>"
88122 output = output .decode ("cp437" )
89123 if output :
90- self .logger .highlight (output )
124+ for line in output .splitlines ():
125+ self .logger .highlight (line .rstrip ())
91126
92127 except Exception as e :
93128 if "SCHED_S_TASK_HAS_NOT_RUN" in str (e ):
@@ -96,6 +131,13 @@ def on_admin_login(self, context, connection):
96131 exec_method .deleteartifact ()
97132 else :
98133 self .logger .fail (f"Failed to execute command: { e } " )
134+ finally :
135+ if self .binary :
136+ try :
137+ connection .conn .deleteFile (self .share , f"{ self .tmp_share } { self .binary_name } " )
138+ context .log .success (f"Binary { self .binary_name } successfully deleted" )
139+ except Exception as e :
140+ context .log .fail (f"Error deleting { self .binary_name } on { self .share } : { e } " )
99141
100142
101143class TSCH_EXEC :
0 commit comments