import traceback from impacket.dcerpc.v5 import tsch, transport from impacket.dcerpc.v5.dtypes import NULL from core.helpers import gen_random_string from gevent import sleep class TSCH_EXEC: def __init__(self, target, username, password, domain, hashes=None): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__outputBuffer = '' self.__retOutput = False #self.__aesKey = aesKey #self.__doKerberos = doKerberos if hashes is not None: self.__lmhash, self.__nthash = hashes.split(':') if self.__password is None: self.__password = '' stringbinding = r'ncacn_np:%s[\pipe\atsvc]' % self.__target 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) #rpctransport.set_kerberos(self.__doKerberos) def execute(self, command, output=False): self.__retOutput = output try: self.doStuff(command) return self.__outputBuffer except Exception as e: traceback.print_exc() def doStuff(self, command): def output_callback(data): self.__outputBuffer = data dce = self.__rpctransport.get_dce_rpc() dce.set_credentials(*self.__rpctransport.get_credentials()) dce.connect() #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) dce.bind(tsch.MSRPC_UUID_TSCHS) tmpName = gen_random_string(8) xml = """ 2015-07-15T20:35:13.2757294 true 1 S-1-5-18 HighestAvailable IgnoreNew false false true false true false true true true false false P3D 7 cmd.exe """ if self.__retOutput: tmpFileName = tmpName + '.tmp' xml+= """ /C {} > %windir%\\Temp\\{} 2>&1 """.format(command, tmpFileName) elif self.__retOutput is False: xml+= """ /C {} """.format(command) #logging.info("Task XML: {}".format(xml)) taskCreated = False try: #logging.info('Creating task \\%s' % tmpName) tsch.hSchRpcRegisterTask(dce, '\\%s' % tmpName, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE) taskCreated = True #logging.info('Running task \\%s' % tmpName) tsch.hSchRpcRun(dce, '\\%s' % tmpName) done = False while not done: #logging.debug('Calling SchRpcGetLastRunInfo for \\%s' % tmpName) resp = tsch.hSchRpcGetLastRunInfo(dce, '\\%s' % tmpName) if resp['pLastRuntime']['wYear'] != 0: done = True else: sleep(2) #logging.info('Deleting task \\%s' % tmpName) tsch.hSchRpcDelete(dce, '\\%s' % tmpName) taskCreated = False except tsch.DCERPCSessionError, e: traceback.print_exc() e.get_packet().dump() finally: if taskCreated is True: tsch.hSchRpcDelete(dce, '\\%s' % tmpName) peer = ':'.join(map(str, self.__rpctransport.get_socket().getpeername())) #self.__logger.success('Executed command via ATEXEC') if self.__retOutput: smbConnection = self.__rpctransport.get_smb_connection() while True: try: #logging.info('Attempting to read ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.getFile('ADMIN$', 'Temp\\%s' % tmpFileName, output_callback) break except Exception as e: if str(e).find('SHARING') > 0: sleep(3) elif str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0: sleep(3) else: raise #logging.debug('Deleting file ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.deleteFile('ADMIN$', 'Temp\\%s' % tmpFileName) else: pass #logging.info('Output retrieval disabled') dce.disconnect()