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()