github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/atexec.py (about) 1 #!/usr/bin/env python 2 # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 # 4 # This software is provided under under a slightly modified version 5 # of the Apache Software License. See the accompanying LICENSE file 6 # for more information. 7 # 8 # ATSVC example for some functions implemented, creates, enums, runs, delete jobs 9 # This example executes a command on the target machine through the Task Scheduler 10 # service. Returns the output of such command 11 # 12 # Author: 13 # Alberto Solino (@agsolino) 14 # 15 # Reference for: 16 # DCE/RPC for TSCH 17 from __future__ import division 18 from __future__ import print_function 19 import string 20 import sys 21 import argparse 22 import time 23 import random 24 import logging 25 26 from impacket.examples import logger 27 from impacket import version 28 from impacket.dcerpc.v5 import tsch, transport 29 from impacket.dcerpc.v5.dtypes import NULL 30 from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE 31 32 33 class TSCH_EXEC: 34 def __init__(self, username='', password='', domain='', hashes=None, aesKey=None, doKerberos=False, kdcHost=None, 35 command=None): 36 self.__username = username 37 self.__password = password 38 self.__domain = domain 39 self.__lmhash = '' 40 self.__nthash = '' 41 self.__aesKey = aesKey 42 self.__doKerberos = doKerberos 43 self.__kdcHost = kdcHost 44 self.__command = command 45 if hashes is not None: 46 self.__lmhash, self.__nthash = hashes.split(':') 47 48 def play(self, addr): 49 stringbinding = r'ncacn_np:%s[\pipe\atsvc]' % addr 50 rpctransport = transport.DCERPCTransportFactory(stringbinding) 51 52 if hasattr(rpctransport, 'set_credentials'): 53 # This method exists only for selected protocol sequences. 54 rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, 55 self.__aesKey) 56 rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) 57 try: 58 self.doStuff(rpctransport) 59 except Exception as e: 60 if logging.getLogger().level == logging.DEBUG: 61 import traceback 62 traceback.print_exc() 63 logging.error(e) 64 if str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >=0: 65 logging.info('When STATUS_OBJECT_NAME_NOT_FOUND is received, try running again. It might work') 66 67 def doStuff(self, rpctransport): 68 def output_callback(data): 69 print(data.decode('utf-8')) 70 71 dce = rpctransport.get_dce_rpc() 72 73 dce.set_credentials(*rpctransport.get_credentials()) 74 if self.__doKerberos is True: 75 dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) 76 dce.connect() 77 #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) 78 dce.bind(tsch.MSRPC_UUID_TSCHS) 79 tmpName = ''.join([random.choice(string.ascii_letters) for _ in range(8)]) 80 tmpFileName = tmpName + '.tmp' 81 82 xml = """<?xml version="1.0" encoding="UTF-16"?> 83 <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> 84 <Triggers> 85 <CalendarTrigger> 86 <StartBoundary>2015-07-15T20:35:13.2757294</StartBoundary> 87 <Enabled>true</Enabled> 88 <ScheduleByDay> 89 <DaysInterval>1</DaysInterval> 90 </ScheduleByDay> 91 </CalendarTrigger> 92 </Triggers> 93 <Principals> 94 <Principal id="LocalSystem"> 95 <UserId>S-1-5-18</UserId> 96 <RunLevel>HighestAvailable</RunLevel> 97 </Principal> 98 </Principals> 99 <Settings> 100 <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> 101 <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> 102 <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> 103 <AllowHardTerminate>true</AllowHardTerminate> 104 <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> 105 <IdleSettings> 106 <StopOnIdleEnd>true</StopOnIdleEnd> 107 <RestartOnIdle>false</RestartOnIdle> 108 </IdleSettings> 109 <AllowStartOnDemand>true</AllowStartOnDemand> 110 <Enabled>true</Enabled> 111 <Hidden>true</Hidden> 112 <RunOnlyIfIdle>false</RunOnlyIfIdle> 113 <WakeToRun>false</WakeToRun> 114 <ExecutionTimeLimit>P3D</ExecutionTimeLimit> 115 <Priority>7</Priority> 116 </Settings> 117 <Actions Context="LocalSystem"> 118 <Exec> 119 <Command>cmd.exe</Command> 120 <Arguments>/C %s > %%windir%%\\Temp\\%s 2>&1</Arguments> 121 </Exec> 122 </Actions> 123 </Task> 124 """ % (self.__command, tmpFileName) 125 taskCreated = False 126 try: 127 logging.info('Creating task \\%s' % tmpName) 128 tsch.hSchRpcRegisterTask(dce, '\\%s' % tmpName, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE) 129 taskCreated = True 130 131 logging.info('Running task \\%s' % tmpName) 132 tsch.hSchRpcRun(dce, '\\%s' % tmpName) 133 134 done = False 135 while not done: 136 logging.debug('Calling SchRpcGetLastRunInfo for \\%s' % tmpName) 137 resp = tsch.hSchRpcGetLastRunInfo(dce, '\\%s' % tmpName) 138 if resp['pLastRuntime']['wYear'] != 0: 139 done = True 140 else: 141 time.sleep(2) 142 143 logging.info('Deleting task \\%s' % tmpName) 144 tsch.hSchRpcDelete(dce, '\\%s' % tmpName) 145 taskCreated = False 146 except tsch.DCERPCSessionError as e: 147 logging.error(e) 148 e.get_packet().dump() 149 finally: 150 if taskCreated is True: 151 tsch.hSchRpcDelete(dce, '\\%s' % tmpName) 152 153 smbConnection = rpctransport.get_smb_connection() 154 waitOnce = True 155 while True: 156 try: 157 logging.info('Attempting to read ADMIN$\\Temp\\%s' % tmpFileName) 158 smbConnection.getFile('ADMIN$', 'Temp\\%s' % tmpFileName, output_callback) 159 break 160 except Exception as e: 161 if str(e).find('SHARING') > 0: 162 time.sleep(3) 163 elif str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0: 164 if waitOnce is True: 165 # We're giving it the chance to flush the file before giving up 166 time.sleep(3) 167 waitOnce = False 168 else: 169 raise 170 else: 171 raise 172 logging.debug('Deleting file ADMIN$\\Temp\\%s' % tmpFileName) 173 smbConnection.deleteFile('ADMIN$', 'Temp\\%s' % tmpFileName) 174 175 dce.disconnect() 176 177 178 # Process command-line arguments. 179 if __name__ == '__main__': 180 print(version.BANNER) 181 # Init the example's logger theme 182 logger.init() 183 184 logging.warning("This will work ONLY on Windows >= Vista") 185 186 parser = argparse.ArgumentParser() 187 188 parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>') 189 parser.add_argument('command', action='store', nargs='*', default = ' ', help='command to execute at the target ') 190 parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 191 192 group = parser.add_argument_group('authentication') 193 194 group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') 195 group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') 196 group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' 197 '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ' 198 'ones specified in the command line') 199 group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' 200 '(128 or 256 bits)') 201 group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. ' 202 'If omitted it will use the domain part (FQDN) specified in the target parameter') 203 204 if len(sys.argv)==1: 205 parser.print_help() 206 sys.exit(1) 207 208 options = parser.parse_args() 209 210 if ''.join(options.command) == ' ': 211 logging.error('You need to specify a command to execute!') 212 sys.exit(1) 213 214 if options.debug is True: 215 logging.getLogger().setLevel(logging.DEBUG) 216 else: 217 logging.getLogger().setLevel(logging.INFO) 218 219 import re 220 221 domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match( 222 options.target).groups('') 223 224 #In case the password contains '@' 225 if '@' in address: 226 password = password + '@' + address.rpartition('@')[0] 227 address = address.rpartition('@')[2] 228 229 if domain is None: 230 domain = '' 231 232 if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: 233 from getpass import getpass 234 235 password = getpass("Password:") 236 237 if options.aesKey is not None: 238 options.k = True 239 240 atsvc_exec = TSCH_EXEC(username, password, domain, options.hashes, options.aesKey, options.k, options.dc_ip, 241 ' '.join(options.command)) 242 atsvc_exec.play(address)