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 &gt; %%windir%%\\Temp\\%s 2&gt;&amp;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)