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,31 @@ 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\')
2528 """
26- self .cmd = self .user = self .task = self .file = self .location = self .time = None
29+
30+ self .cmd = self .binary = self .user = self .task = self .file = self .location = self .time = None
31+ self .share = "C$"
32+ self .tmp_dir = "C:\\ Windows\\ Temp\\ "
33+ self .tmp_share = self .tmp_dir .split (":" )[1 ]
34+
2735 if "CMD" in module_options :
2836 self .cmd = module_options ["CMD" ]
2937
38+ if "BINARY" in module_options :
39+ self .binary = module_options ["BINARY" ]
40+
3041 if "USER" in module_options :
3142 self .user = module_options ["USER" ]
3243
@@ -47,13 +58,32 @@ def options(self, context, module_options):
4758
4859 def on_admin_login (self , context , connection ):
4960 self .logger = context .log
61+
5062 if self .cmd is None :
5163 self .logger .fail ("You need to specify a CMD to run" )
5264 return 1
65+
5366 if self .user is None :
5467 self .logger .fail ("You need to specify a USER to run the command as" )
5568 return 1
56-
69+
70+ if self .binary :
71+ if not os .path .isfile (self .binary ):
72+ self .logger .fail (f"Cannot find { self .binary } " )
73+ return 1
74+ else :
75+ self .logger .display (f"Uploading { self .binary } " )
76+ with open (self .binary , "rb" ) as binary_to_upload :
77+ try :
78+ self .binary_name = os .path .basename (self .binary )
79+ connection .conn .putFile (self .share , f"{ self .tmp_share } { self .binary_name } " , binary_to_upload .read )
80+ self .logger .success (f"Binary { self .binary_name } successfully uploaded in { self .tmp_share } { self .binary_name } " )
81+ except Exception as e :
82+ self .logger .fail (f"Error writing file to share { self .tmp_share } : { e } " )
83+ return 1
84+
85+ # Returnes self.cmd or \Windows\temp\BinToExecute.exe depending if BINARY=BinToExecute.exe
86+ self .cmd = self .cmd if not self .binary else f"{ self .tmp_share } { self .cmd } "
5787 self .logger .display ("Connecting to the remote Service control endpoint" )
5888 try :
5989 exec_method = TSCH_EXEC (
@@ -87,7 +117,8 @@ def on_admin_login(self, context, connection):
87117 # Required to decode specific French characters otherwise it'll print b"<result>"
88118 output = output .decode ("cp437" )
89119 if output :
90- self .logger .highlight (output )
120+ for line in output .splitlines ():
121+ self .logger .highlight (line .strip ())
91122
92123 except Exception as e :
93124 if "SCHED_S_TASK_HAS_NOT_RUN" in str (e ):
@@ -96,6 +127,13 @@ def on_admin_login(self, context, connection):
96127 exec_method .deleteartifact ()
97128 else :
98129 self .logger .fail (f"Failed to execute command: { e } " )
130+ finally :
131+ if self .binary :
132+ try :
133+ connection .conn .deleteFile (self .share , f"{ self .tmp_share } { self .binary_name } " )
134+ context .log .success (f"Binary { self .binary_name } successfully deleted" )
135+ except Exception as e :
136+ context .log .fail (f"Error deleting { self .binary_name } on { self .share } : { e } " )
99137
100138
101139class TSCH_EXEC :
0 commit comments