github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/wmiquery.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  # Description: [MS-WMI] example. It allows to issue WQL queries and
     9  #              get description of the objects.
    10  #
    11  #              e.g.: select name from win32_account
    12  #              e.g.: describe win32_process
    13  # 
    14  # Author:
    15  #  Alberto Solino (@agsolino)
    16  #
    17  # Reference for:
    18  #  DCOM
    19  #
    20  from __future__ import division
    21  from __future__ import print_function
    22  import argparse
    23  import sys
    24  import os
    25  import logging
    26  
    27  from impacket.examples import logger
    28  from impacket import version
    29  from impacket.dcerpc.v5.dtypes import NULL
    30  from impacket.dcerpc.v5.dcom import wmi
    31  from impacket.dcerpc.v5.dcomrt import DCOMConnection
    32  from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
    33  
    34  if __name__ == '__main__':
    35      import cmd
    36  
    37      class WMIQUERY(cmd.Cmd):
    38          def __init__(self, iWbemServices):
    39              cmd.Cmd.__init__(self)
    40              self.iWbemServices = iWbemServices
    41              self.prompt = 'WQL> '
    42              self.intro = '[!] Press help for extra shell commands'
    43  
    44          def do_help(self, line):
    45              print("""
    46       lcd {path}                 - changes the current local directory to {path}
    47       exit                       - terminates the server process (and this session)
    48       describe {class}           - describes class
    49       ! {cmd}                    - executes a local shell cmd
    50       """) 
    51  
    52          def do_shell(self, s):
    53              os.system(s)
    54  
    55          def do_describe(self, sClass):
    56              sClass = sClass.strip('\n')
    57              if sClass[-1:] == ';':
    58                  sClass = sClass[:-1]
    59              try:
    60                  iObject, _ = self.iWbemServices.GetObject(sClass)
    61                  iObject.printInformation()
    62                  iObject.RemRelease()
    63              except Exception as e:
    64                  if logging.getLogger().level == logging.DEBUG:
    65                      import traceback
    66                      traceback.print_exc()
    67                  logging.error(str(e))
    68  
    69          def do_lcd(self, s):
    70              if s == '':
    71                  print(os.getcwd())
    72              else:
    73                  os.chdir(s)
    74      
    75          def printReply(self, iEnum):
    76              printHeader = True
    77              while True:
    78                  try:
    79                      pEnum = iEnum.Next(0xffffffff,1)[0]
    80                      record = pEnum.getProperties()
    81                      if printHeader is True:
    82                          print('|', end=' ')
    83                          for col in record:
    84                              print('%s |' % col, end=' ')
    85                          print()
    86                          printHeader = False
    87                      print('|', end=' ') 
    88                      for key in record:
    89                          if type(record[key]['value']) is list:
    90                              for item in record[key]['value']:
    91                                  print(item, end=' ')
    92                              print(' |', end=' ')
    93                          else:
    94                              print('%s |' % record[key]['value'], end=' ')
    95                      print() 
    96                  except Exception as e:
    97                      if logging.getLogger().level == logging.DEBUG:
    98                          import traceback
    99                          traceback.print_exc()
   100                      if str(e).find('S_FALSE') < 0:
   101                          raise
   102                      else:
   103                          break
   104              iEnum.RemRelease() 
   105  
   106          def default(self, line):
   107              line = line.strip('\n')
   108              if line[-1:] == ';':
   109                  line = line[:-1]
   110              try:
   111                  iEnumWbemClassObject = self.iWbemServices.ExecQuery(line.strip('\n'))
   112                  self.printReply(iEnumWbemClassObject)
   113                  iEnumWbemClassObject.RemRelease()
   114              except Exception as e:
   115                  logging.error(str(e))
   116           
   117          def emptyline(self):
   118              pass
   119  
   120          def do_exit(self, line):
   121              return True
   122  
   123      # Init the example's logger theme
   124      logger.init()
   125      print(version.BANNER)
   126  
   127      parser = argparse.ArgumentParser(add_help = True, description = "Executes WQL queries and gets object descriptions "
   128                                                                      "using Windows Management Instrumentation.")
   129      parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
   130      parser.add_argument('-namespace', action='store', default='//./root/cimv2', help='namespace name (default //./root/cimv2)')
   131      parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the WQL shell')
   132      parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
   133  
   134      group = parser.add_argument_group('authentication')
   135  
   136      group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
   137      group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
   138      group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
   139                         '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the '
   140                         'ones specified in the command line')
   141      group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication '
   142                                                                              '(128 or 256 bits)')
   143      group.add_argument('-dc-ip', action='store',metavar = "ip address",  help='IP Address of the domain controller. If '
   144                         'ommited it use the domain part (FQDN) specified in the target parameter')
   145      group.add_argument('-rpc-auth-level', choices=['integrity', 'privacy','default'], nargs='?', default='default',
   146                         help='default, integrity (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) or privacy '
   147                              '(RPC_C_AUTHN_LEVEL_PKT_PRIVACY). For example CIM path "root/MSCluster" would require '
   148                              'privacy level by default)')
   149  
   150      if len(sys.argv)==1:
   151          parser.print_help()
   152          sys.exit(1)
   153   
   154      options = parser.parse_args()
   155  
   156      if options.debug is True:
   157          logging.getLogger().setLevel(logging.DEBUG)
   158      else:
   159          logging.getLogger().setLevel(logging.INFO)
   160  
   161      import re
   162  
   163      domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
   164          options.target).groups('')
   165  
   166      #In case the password contains '@'
   167      if '@' in address:
   168          password = password + '@' + address.rpartition('@')[0]
   169          address = address.rpartition('@')[2]
   170  
   171      if domain is None:
   172          domain = ''
   173  
   174      if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
   175          from getpass import getpass
   176          password = getpass("Password:")
   177  
   178      if options.aesKey is not None:
   179          options.k = True
   180  
   181      if options.hashes is not None:
   182          lmhash, nthash = options.hashes.split(':')
   183      else:
   184          lmhash = ''
   185          nthash = ''
   186  
   187      try:
   188          dcom = DCOMConnection(address, username, password, domain, lmhash, nthash, options.aesKey, oxidResolver=True,
   189                                doKerberos=options.k, kdcHost=options.dc_ip)
   190  
   191          iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
   192          iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
   193          iWbemServices= iWbemLevel1Login.NTLMLogin(options.namespace, NULL, NULL)
   194          if options.rpc_auth_level == 'privacy':
   195              iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
   196          elif options.rpc_auth_level == 'integrity':
   197              iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
   198  
   199          iWbemLevel1Login.RemRelease()
   200  
   201          shell = WMIQUERY(iWbemServices)
   202          if options.file is None:
   203              shell.cmdloop()
   204          else:
   205              for line in options.file.readlines():
   206                  print("WQL> %s" % line, end=' ')
   207                  shell.onecmd(line)
   208  
   209          iWbemServices.RemRelease()
   210          dcom.disconnect()
   211      except Exception as e:
   212          logging.error(str(e))
   213          try:
   214              dcom.disconnect()
   215          except:
   216              pass