github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/services.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  # [MS-SCMR] services common functions for manipulating services
     9  #
    10  # Author:
    11  #  Alberto Solino (@agsolino)
    12  #
    13  # Reference for:
    14  #  DCE/RPC.
    15  # TODO: 
    16  # [ ] Check errors
    17  from __future__ import division
    18  from __future__ import print_function
    19  import sys
    20  import argparse
    21  import logging
    22  import codecs
    23  
    24  from impacket.examples import logger
    25  from impacket import version
    26  from impacket.dcerpc.v5 import transport, scmr
    27  from impacket.dcerpc.v5.ndr import NULL
    28  from impacket.crypto import encryptSecret
    29  
    30  
    31  class SVCCTL:
    32  
    33      def __init__(self, username, password, domain, options, port=445):
    34          self.__username = username
    35          self.__password = password
    36          self.__options = options
    37          self.__port = port
    38          self.__action = options.action.upper()
    39          self.__domain = domain
    40          self.__lmhash = ''
    41          self.__nthash = ''
    42          self.__aesKey = options.aesKey
    43          self.__doKerberos = options.k
    44          self.__kdcHost = options.dc_ip
    45  
    46          if options.hashes is not None:
    47              self.__lmhash, self.__nthash = options.hashes.split(':')
    48  
    49      def run(self, remoteName, remoteHost):
    50  
    51          stringbinding = r'ncacn_np:%s[\pipe\svcctl]' % remoteName
    52          logging.debug('StringBinding %s'%stringbinding)
    53          rpctransport = transport.DCERPCTransportFactory(stringbinding)
    54          rpctransport.set_dport(self.__port)
    55          rpctransport.setRemoteHost(remoteHost)
    56          if hasattr(rpctransport, 'set_credentials'):
    57              # This method exists only for selected protocol sequences.
    58              rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey)
    59  
    60          rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
    61          self.doStuff(rpctransport)
    62  
    63      def doStuff(self, rpctransport):
    64          dce = rpctransport.get_dce_rpc()
    65          #dce.set_credentials(self.__username, self.__password)
    66          dce.connect()
    67          #dce.set_max_fragment_size(1)
    68          #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)
    69          #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_INTEGRITY)
    70          dce.bind(scmr.MSRPC_UUID_SCMR)
    71          #rpc = svcctl.DCERPCSvcCtl(dce)
    72          rpc = dce
    73          ans = scmr.hROpenSCManagerW(rpc)
    74          scManagerHandle = ans['lpScHandle']
    75          if self.__action != 'LIST' and self.__action != 'CREATE':
    76              ans = scmr.hROpenServiceW(rpc, scManagerHandle, self.__options.name+'\x00')
    77              serviceHandle = ans['lpServiceHandle']
    78  
    79          if self.__action == 'START':
    80              logging.info("Starting service %s" % self.__options.name)
    81              scmr.hRStartServiceW(rpc, serviceHandle)
    82              scmr.hRCloseServiceHandle(rpc, serviceHandle)
    83          elif self.__action == 'STOP':
    84              logging.info("Stopping service %s" % self.__options.name)
    85              scmr.hRControlService(rpc, serviceHandle, scmr.SERVICE_CONTROL_STOP)
    86              scmr.hRCloseServiceHandle(rpc, serviceHandle)
    87          elif self.__action == 'DELETE':
    88              logging.info("Deleting service %s" % self.__options.name)
    89              scmr.hRDeleteService(rpc, serviceHandle)
    90              scmr.hRCloseServiceHandle(rpc, serviceHandle)
    91          elif self.__action == 'CONFIG':
    92              logging.info("Querying service config for %s" % self.__options.name)
    93              resp = scmr.hRQueryServiceConfigW(rpc, serviceHandle)
    94              print("TYPE              : %2d - " % resp['lpServiceConfig']['dwServiceType'], end=' ')
    95              if resp['lpServiceConfig']['dwServiceType'] & 0x1:
    96                  print("SERVICE_KERNEL_DRIVER ", end=' ')
    97              if resp['lpServiceConfig']['dwServiceType'] & 0x2:
    98                  print("SERVICE_FILE_SYSTEM_DRIVER ", end=' ')
    99              if resp['lpServiceConfig']['dwServiceType'] & 0x10:
   100                  print("SERVICE_WIN32_OWN_PROCESS ", end=' ')
   101              if resp['lpServiceConfig']['dwServiceType'] & 0x20:
   102                  print("SERVICE_WIN32_SHARE_PROCESS ", end=' ')
   103              if resp['lpServiceConfig']['dwServiceType'] & 0x100:
   104                  print("SERVICE_INTERACTIVE_PROCESS ", end=' ')
   105              print("")
   106              print("START_TYPE        : %2d - " % resp['lpServiceConfig']['dwStartType'], end=' ')
   107              if resp['lpServiceConfig']['dwStartType'] == 0x0:
   108                  print("BOOT START")
   109              elif resp['lpServiceConfig']['dwStartType'] == 0x1:
   110                  print("SYSTEM START")
   111              elif resp['lpServiceConfig']['dwStartType'] == 0x2:
   112                  print("AUTO START")
   113              elif resp['lpServiceConfig']['dwStartType'] == 0x3:
   114                  print("DEMAND START")
   115              elif resp['lpServiceConfig']['dwStartType'] == 0x4:
   116                  print("DISABLED")
   117              else:
   118                  print("UNKNOWN")
   119  
   120              print("ERROR_CONTROL     : %2d - " % resp['lpServiceConfig']['dwErrorControl'], end=' ')
   121              if resp['lpServiceConfig']['dwErrorControl'] == 0x0:
   122                  print("IGNORE")
   123              elif resp['lpServiceConfig']['dwErrorControl'] == 0x1:
   124                  print("NORMAL")
   125              elif resp['lpServiceConfig']['dwErrorControl'] == 0x2:
   126                  print("SEVERE")
   127              elif resp['lpServiceConfig']['dwErrorControl'] == 0x3:
   128                  print("CRITICAL")
   129              else:
   130                  print("UNKNOWN")
   131              print("BINARY_PATH_NAME  : %s" % resp['lpServiceConfig']['lpBinaryPathName'][:-1])
   132              print("LOAD_ORDER_GROUP  : %s" % resp['lpServiceConfig']['lpLoadOrderGroup'][:-1])
   133              print("TAG               : %d" % resp['lpServiceConfig']['dwTagId'])
   134              print("DISPLAY_NAME      : %s" % resp['lpServiceConfig']['lpDisplayName'][:-1])
   135              print("DEPENDENCIES      : %s" % resp['lpServiceConfig']['lpDependencies'][:-1])
   136              print("SERVICE_START_NAME: %s" % resp['lpServiceConfig']['lpServiceStartName'][:-1])
   137          elif self.__action == 'STATUS':
   138              print("Querying status for %s" % self.__options.name)
   139              resp = scmr.hRQueryServiceStatus(rpc, serviceHandle)
   140              print("%30s - " % self.__options.name, end=' ')
   141              state = resp['lpServiceStatus']['dwCurrentState']
   142              if state == scmr.SERVICE_CONTINUE_PENDING:
   143                 print("CONTINUE PENDING")
   144              elif state == scmr.SERVICE_PAUSE_PENDING:
   145                 print("PAUSE PENDING")
   146              elif state == scmr.SERVICE_PAUSED:
   147                 print("PAUSED")
   148              elif state == scmr.SERVICE_RUNNING:
   149                 print("RUNNING")
   150              elif state == scmr.SERVICE_START_PENDING:
   151                 print("START PENDING")
   152              elif state == scmr.SERVICE_STOP_PENDING:
   153                 print("STOP PENDING")
   154              elif state == scmr.SERVICE_STOPPED:
   155                 print("STOPPED")
   156              else:
   157                 print("UNKNOWN")
   158          elif self.__action == 'LIST':
   159              logging.info("Listing services available on target")
   160              #resp = rpc.EnumServicesStatusW(scManagerHandle, svcctl.SERVICE_WIN32_SHARE_PROCESS )
   161              #resp = rpc.EnumServicesStatusW(scManagerHandle, svcctl.SERVICE_WIN32_OWN_PROCESS )
   162              #resp = rpc.EnumServicesStatusW(scManagerHandle, serviceType = svcctl.SERVICE_FILE_SYSTEM_DRIVER, serviceState = svcctl.SERVICE_STATE_ALL )
   163              resp = scmr.hREnumServicesStatusW(rpc, scManagerHandle)
   164              for i in range(len(resp)):
   165                  print("%30s - %70s - " % (resp[i]['lpServiceName'][:-1], resp[i]['lpDisplayName'][:-1]), end=' ')
   166                  state = resp[i]['ServiceStatus']['dwCurrentState']
   167                  if state == scmr.SERVICE_CONTINUE_PENDING:
   168                     print("CONTINUE PENDING")
   169                  elif state == scmr.SERVICE_PAUSE_PENDING:
   170                     print("PAUSE PENDING")
   171                  elif state == scmr.SERVICE_PAUSED:
   172                     print("PAUSED")
   173                  elif state == scmr.SERVICE_RUNNING:
   174                     print("RUNNING")
   175                  elif state == scmr.SERVICE_START_PENDING:
   176                     print("START PENDING")
   177                  elif state == scmr.SERVICE_STOP_PENDING:
   178                     print("STOP PENDING")
   179                  elif state == scmr.SERVICE_STOPPED:
   180                     print("STOPPED")
   181                  else:
   182                     print("UNKNOWN")
   183              print("Total Services: %d" % len(resp))
   184          elif self.__action == 'CREATE':
   185              logging.info("Creating service %s" % self.__options.name)
   186              scmr.hRCreateServiceW(rpc, scManagerHandle, self.__options.name + '\x00', self.__options.display + '\x00',
   187                                    lpBinaryPathName=self.__options.path + '\x00')
   188          elif self.__action == 'CHANGE':
   189              logging.info("Changing service config for %s" % self.__options.name)
   190              if self.__options.start_type is not None:
   191                  start_type = int(self.__options.start_type)
   192              else:
   193                  start_type = scmr.SERVICE_NO_CHANGE
   194              if self.__options.service_type is not None:
   195                  service_type = int(self.__options.service_type)
   196              else:
   197                  service_type = scmr.SERVICE_NO_CHANGE
   198  
   199              if self.__options.display is not None:
   200                  display = self.__options.display + '\x00'
   201              else:
   202                  display = NULL
   203   
   204              if self.__options.path is not None:
   205                  path = self.__options.path + '\x00'
   206              else:
   207                  path = NULL
   208   
   209              if self.__options.start_name is not None:
   210                  start_name = self.__options.start_name + '\x00'
   211              else:
   212                  start_name = NULL 
   213  
   214              if self.__options.password is not None:
   215                  s = rpctransport.get_smb_connection()
   216                  key = s.getSessionKey()
   217                  try:
   218                      password = (self.__options.password+'\x00').encode('utf-16le')
   219                  except UnicodeDecodeError:
   220                      import sys
   221                      password = (self.__options.password+'\x00').decode(sys.getfilesystemencoding()).encode('utf-16le')
   222                  password = encryptSecret(key, password)
   223              else:
   224                  password = NULL
   225   
   226  
   227              #resp = scmr.hRChangeServiceConfigW(rpc, serviceHandle,  display, path, service_type, start_type, start_name, password)
   228              scmr.hRChangeServiceConfigW(rpc, serviceHandle, service_type, start_type, scmr.SERVICE_ERROR_IGNORE, path,
   229                                          NULL, NULL, NULL, 0, start_name, password, 0, display)
   230              scmr.hRCloseServiceHandle(rpc, serviceHandle)
   231          else:
   232              logging.error("Unknown action %s" % self.__action)
   233  
   234          scmr.hRCloseServiceHandle(rpc, scManagerHandle)
   235  
   236          dce.disconnect()
   237  
   238          return 
   239  
   240  
   241  # Process command-line arguments.
   242  if __name__ == '__main__':
   243  
   244      # Init the example's logger theme
   245      logger.init()
   246      # Explicitly changing the stdout encoding format
   247      if sys.stdout.encoding is None:
   248          # Output is redirected to a file
   249          sys.stdout = codecs.getwriter('utf8')(sys.stdout)
   250      print(version.BANNER)
   251  
   252      parser = argparse.ArgumentParser(add_help = True, description = "Windows Service manipulation script.")
   253  
   254      parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
   255      parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
   256      subparsers = parser.add_subparsers(help='actions', dest='action')
   257   
   258      # A start command
   259      start_parser = subparsers.add_parser('start', help='starts the service')
   260      start_parser.add_argument('-name', action='store', required=True, help='service name')
   261  
   262      # A stop command
   263      stop_parser = subparsers.add_parser('stop', help='stops the service')
   264      stop_parser.add_argument('-name', action='store', required=True, help='service name')
   265  
   266      # A delete command
   267      delete_parser = subparsers.add_parser('delete', help='deletes the service')
   268      delete_parser.add_argument('-name', action='store', required=True, help='service name')
   269  
   270      # A status command
   271      status_parser = subparsers.add_parser('status', help='returns service status')
   272      status_parser.add_argument('-name', action='store', required=True, help='service name')
   273  
   274      # A config command
   275      config_parser = subparsers.add_parser('config', help='returns service configuration')
   276      config_parser.add_argument('-name', action='store', required=True, help='service name')
   277  
   278      # A list command
   279      list_parser = subparsers.add_parser('list', help='list available services')
   280  
   281      # A create command
   282      create_parser = subparsers.add_parser('create', help='create a service')
   283      create_parser.add_argument('-name', action='store', required=True, help='service name')
   284      create_parser.add_argument('-display', action='store', required=True, help='display name')
   285      create_parser.add_argument('-path', action='store', required=True, help='binary path')
   286  
   287      # A change command
   288      create_parser = subparsers.add_parser('change', help='change a service configuration')
   289      create_parser.add_argument('-name', action='store', required=True, help='service name')
   290      create_parser.add_argument('-display', action='store', required=False, help='display name')
   291      create_parser.add_argument('-path', action='store', required=False, help='binary path')
   292      create_parser.add_argument('-service_type', action='store', required=False, help='service type')
   293      create_parser.add_argument('-start_type', action='store', required=False, help='service start type')
   294      create_parser.add_argument('-start_name', action='store', required=False, help='string that specifies the name of '
   295                                 'the account under which the service should run')
   296      create_parser.add_argument('-password', action='store', required=False, help='string that contains the password of '
   297                                 'the account whose name was specified by the start_name parameter')
   298  
   299      group = parser.add_argument_group('authentication')
   300  
   301      group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
   302      group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
   303      group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
   304                         '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the '
   305                         'ones specified in the command line')
   306      group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication '
   307                                                                              '(128 or 256 bits)')
   308  
   309      group = parser.add_argument_group('connection')
   310  
   311      group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If '
   312                         'ommited it use the domain part (FQDN) specified in the target parameter')
   313      group.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If '
   314                         'ommited it will use whatever was specified as target. This is useful when target is the NetBIOS '
   315                         'name and you cannot resolve it')
   316      group.add_argument('-port', choices=['139', '445'], nargs='?', default='445', metavar="destination port",
   317                         help='Destination port to connect to SMB Server')
   318   
   319      if len(sys.argv)==1:
   320          parser.print_help()
   321          sys.exit(1)
   322  
   323      options = parser.parse_args()
   324  
   325      if options.debug is True:
   326          logging.getLogger().setLevel(logging.DEBUG)
   327      else:
   328          logging.getLogger().setLevel(logging.INFO)
   329  
   330      import re
   331  
   332      domain, username, password, remoteName = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
   333          options.target).groups('')
   334  
   335      #In case the password contains '@'
   336      if '@' in remoteName:
   337          password = password + '@' + remoteName.rpartition('@')[0]
   338          remoteName = remoteName.rpartition('@')[2]
   339  
   340      if domain is None:
   341          domain = ''
   342  
   343      if options.target_ip is None:
   344          options.target_ip = remoteName
   345  
   346      if options.aesKey is not None:
   347          options.k = True
   348  
   349      if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
   350          from getpass import getpass
   351          password = getpass("Password:")
   352  
   353      services = SVCCTL(username, password, domain, options, int(options.port))
   354      try:
   355          services.run(remoteName, options.target_ip)
   356      except Exception as e:
   357          if logging.getLogger().level == logging.DEBUG:
   358              import traceback
   359              traceback.print_exc()
   360          logging.error(str(e))