1+ import contextlib
12import os
23from time import sleep
3- from datetime import datetime
4+ from datetime import datetime , timedelta
45from impacket .dcerpc .v5 .dtypes import NULL
56from impacket .dcerpc .v5 import tsch , transport
67from nxc .helpers .misc import gen_random_string
@@ -91,6 +92,10 @@ def on_admin_login(self, context, connection):
9192 except Exception as e :
9293 if "SCHED_S_TASK_HAS_NOT_RUN" in str (e ):
9394 self .logger .fail ("Task was not run, seems like the specified user has no active session on the target" )
95+ with contextlib .suppress (Exception ):
96+ exec_method .deleteartifact ()
97+ else :
98+ self .logger .fail (f"Failed to execute command: { e } " )
9499
95100
96101class TSCH_EXEC :
@@ -143,6 +148,18 @@ def __init__(self, target, share_name, username, password, domain, user, cmd, fi
143148 )
144149 self .__rpctransport .set_kerberos (self .__doKerberos , self .__kdcHost )
145150
151+ def deleteartifact (self ):
152+ dce = self .__rpctransport .get_dce_rpc ()
153+ if self .__doKerberos :
154+ dce .set_auth_type (RPC_C_AUTHN_GSS_NEGOTIATE )
155+ dce .set_credentials (* self .__rpctransport .get_credentials ())
156+ dce .connect ()
157+ dce .set_auth_level (RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
158+ dce .bind (tsch .MSRPC_UUID_TSCHS )
159+ self .logger .display (f"Deleting task \\ { self .task } " )
160+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
161+ dce .disconnect ()
162+
146163 def execute (self , command , output = False ):
147164 self .__retOutput = output
148165 self .execute_handler (command )
@@ -151,24 +168,20 @@ def execute(self, command, output=False):
151168 def output_callback (self , data ):
152169 self .__outputBuffer = data
153170
154- def get_current_date (self ):
155- # Get current date and time
156- now = datetime .now ()
171+ def get_end_boundary (self ):
172+ # Get current date and time + 5 minutes
173+ end_boundary = datetime .now () + timedelta ( minutes = 5 )
157174
158175 # Format it to match the format in the XML: "YYYY-MM-DDTHH:MM:SS.ssssss"
159- return now .strftime ("%Y-%m-%dT%H:%M:%S.%f" )[:- 3 ]
176+ return end_boundary .strftime ("%Y-%m-%dT%H:%M:%S.%f" )[:- 3 ]
160177
161178 def gen_xml (self , command , fileless = False ):
162179 xml = f"""<?xml version="1.0" encoding="UTF-16"?>
163180<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
164181 <Triggers>
165- <CalendarTrigger>
166- <StartBoundary>{ self .get_current_date ()} </StartBoundary>
167- <Enabled>true</Enabled>
168- <ScheduleByDay>
169- <DaysInterval>1</DaysInterval>
170- </ScheduleByDay>
171- </CalendarTrigger>
182+ <RegistrationTrigger>
183+ <EndBoundary>{ self .get_end_boundary ()} </EndBoundary>
184+ </RegistrationTrigger>
172185 </Triggers>
173186 <Principals>
174187 <Principal id="LocalSystem">
@@ -224,53 +237,58 @@ def gen_xml(self, command, fileless=False):
224237
225238 def execute_handler (self , command , fileless = False ):
226239 dce = self .__rpctransport .get_dce_rpc ()
240+
227241 if self .__doKerberos :
228242 dce .set_auth_type (RPC_C_AUTHN_GSS_NEGOTIATE )
229243
230244 dce .set_credentials (* self .__rpctransport .get_credentials ())
231245 dce .connect ()
232- tmpName = gen_random_string (8 ) if self .task is None else self .task
246+ # Give self.task a random string as name if not already specified
247+ self .task = gen_random_string (8 ) if self .task is None else self .task
233248 xml = self .gen_xml (command , fileless )
234249
235250 self .logger .info (f"Task XML: { xml } " )
236- taskCreated = False
237- self .logger .info (f"Creating task \\ { tmpName } " )
251+ self .logger .info (f"Creating task \\ { self .task } " )
238252 try :
239253 # windows server 2003 has no MSRPC_UUID_TSCHS, if it bind, it will return abstract_syntax_not_supported
240254 dce .set_auth_level (RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
241255 dce .bind (tsch .MSRPC_UUID_TSCHS )
242- tsch .hSchRpcRegisterTask (dce , f"\\ { tmpName } " , xml , tsch .TASK_CREATE , NULL , tsch .TASK_LOGON_NONE )
256+ tsch .hSchRpcRegisterTask (dce , f"\\ { self . task } " , xml , tsch .TASK_CREATE , NULL , tsch .TASK_LOGON_NONE )
243257 except Exception as e :
244258 if "ERROR_NONE_MAPPED" in str (e ):
245259 self .logger .fail (f"User { self .user } is not connected on the target, cannot run the task" )
246- if e .error_code and hex (e .error_code ) == "0x80070005" :
247- self .logger .fail ("Schtask_as: Create schedule task got blocked." )
248- if "ERROR_TRUSTED_DOMAIN_FAILURE" in str (e ):
260+ with contextlib .suppress (Exception ):
261+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
262+ elif e .error_code and hex (e .error_code ) == "0x80070005" :
263+ self .logger .fail ("Create schedule task got blocked." )
264+ with contextlib .suppress (Exception ):
265+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
266+ elif "ERROR_TRUSTED_DOMAIN_FAILURE" in str (e ):
249267 self .logger .fail (f"User { self .user } does not exist in the domain." )
268+ with contextlib .suppress (Exception ):
269+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
270+ elif "SCHED_S_TASK_HAS_NOT_RUN" in str (e ):
271+ with contextlib .suppress (Exception ):
272+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
273+ elif "ERROR_ALREADY_EXISTS" in str (e ):
274+ self .logger .fail (f"Create schedule task failed: { e } " )
250275 else :
251- self .logger .fail (f"Schtask_as: Create schedule task failed: { e } " )
276+ self .logger .fail (f"Create schedule task failed: { e } " )
277+ with contextlib .suppress (Exception ):
278+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
252279 return
253- else :
254- taskCreated = True
255-
256- self .logger .info (f"Running task \\ { tmpName } " )
257- tsch .hSchRpcRun (dce , f"\\ { tmpName } " )
258280
259281 done = False
260282 while not done :
261- self .logger .debug (f"Calling SchRpcGetLastRunInfo for \\ { tmpName } " )
262- resp = tsch .hSchRpcGetLastRunInfo (dce , f"\\ { tmpName } " )
283+ self .logger .debug (f"Calling SchRpcGetLastRunInfo for \\ { self . task } " )
284+ resp = tsch .hSchRpcGetLastRunInfo (dce , f"\\ { self . task } " )
263285 if resp ["pLastRuntime" ]["wYear" ] != 0 :
264286 done = True
265287 else :
266288 sleep (2 )
267289
268- self .logger .info (f"Deleting task \\ { tmpName } " )
269- tsch .hSchRpcDelete (dce , f"\\ { tmpName } " )
270- taskCreated = False
271-
272- if taskCreated is True :
273- tsch .hSchRpcDelete (dce , f"\\ { tmpName } " )
290+ self .logger .info (f"Deleting task \\ { self .task } " )
291+ tsch .hSchRpcDelete (dce , f"\\ { self .task } " )
274292
275293 if self .__retOutput :
276294 if fileless :
0 commit comments