github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/rpcdump.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  # DCE/RPC endpoint mapper dumper.
     9  #
    10  # Author:
    11  #  Javier Kohen <jkohen@coresecurity.com>
    12  #  Alberto Solino <beto@coresecurity.com>
    13  #
    14  # Reference for:
    15  #  DCE/RPC.
    16  from __future__ import division
    17  from __future__ import print_function
    18  import sys
    19  import logging
    20  import argparse
    21  
    22  from impacket.examples import logger
    23  from impacket import uuid, version
    24  from impacket.dcerpc.v5 import transport, epm
    25  
    26  class RPCDump:
    27      KNOWN_PROTOCOLS = {
    28          135: {'bindstr': r'ncacn_ip_tcp:%s',             'set_host': False},
    29          139: {'bindstr': r'ncacn_np:%s[\pipe\epmapper]', 'set_host': True},
    30          445: {'bindstr': r'ncacn_np:%s[\pipe\epmapper]', 'set_host': True}
    31          }
    32  
    33      def __init__(self, username = '', password = '', domain='', hashes = None, port=135):
    34  
    35          self.__username = username
    36          self.__password = password
    37          self.__domain = domain
    38          self.__lmhash = ''
    39          self.__nthash = ''
    40          self.__port = port
    41          if hashes is not None:
    42              self.__lmhash, self.__nthash = hashes.split(':')
    43  
    44      def dump(self, remoteName, remoteHost):
    45          """Dumps the list of endpoints registered with the mapper
    46          listening at addr. remoteName is a valid host name or IP
    47          address in string format.
    48          """
    49  
    50          logging.info('Retrieving endpoint list from %s' % remoteName)
    51  
    52          entries = []
    53  
    54          stringbinding = self.KNOWN_PROTOCOLS[self.__port]['bindstr'] % remoteName
    55          logging.debug('StringBinding %s'%stringbinding)
    56          rpctransport = transport.DCERPCTransportFactory(stringbinding)
    57          rpctransport.set_dport(self.__port)
    58  
    59          if self.KNOWN_PROTOCOLS[self.__port]['set_host']:
    60              rpctransport.setRemoteHost(remoteHost)
    61  
    62          if hasattr(rpctransport, 'set_credentials'):
    63              # This method exists only for selected protocol sequences.
    64              rpctransport.set_credentials(self.__username, self.__password, self.__domain,
    65                                           self.__lmhash, self.__nthash)
    66  
    67          try:
    68              entries = self.__fetchList(rpctransport)
    69          except Exception as e:
    70              logging.critical('Protocol failed: %s' % e)
    71  
    72          # Display results.
    73  
    74          endpoints = {}
    75          # Let's groups the UUIDS
    76          for entry in entries:
    77              binding = epm.PrintStringBinding(entry['tower']['Floors'], rpctransport.getRemoteHost())
    78              tmpUUID = str(entry['tower']['Floors'][0])
    79              if (tmpUUID in endpoints) is not True:
    80                  endpoints[tmpUUID] = {}
    81                  endpoints[tmpUUID]['Bindings'] = list()
    82              if uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18] in epm.KNOWN_UUIDS:
    83                  endpoints[tmpUUID]['EXE'] = epm.KNOWN_UUIDS[uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18]]
    84              else:
    85                  endpoints[tmpUUID]['EXE'] = 'N/A'
    86              endpoints[tmpUUID]['annotation'] = entry['annotation'][:-1].decode('utf-8')
    87              endpoints[tmpUUID]['Bindings'].append(binding)
    88  
    89              if tmpUUID[:36] in epm.KNOWN_PROTOCOLS:
    90                  endpoints[tmpUUID]['Protocol'] = epm.KNOWN_PROTOCOLS[tmpUUID[:36]]
    91              else:
    92                  endpoints[tmpUUID]['Protocol'] = "N/A"
    93              #print "Transfer Syntax: %s" % entry['Tower']['Floors'][1]
    94       
    95          for endpoint in list(endpoints.keys()):
    96              print("Protocol: %s " % endpoints[endpoint]['Protocol'])
    97              print("Provider: %s " % endpoints[endpoint]['EXE'])
    98              print("UUID    : %s %s" % (endpoint, endpoints[endpoint]['annotation']))
    99              print("Bindings: ")
   100              for binding in endpoints[endpoint]['Bindings']:
   101                  print("          %s" % binding)
   102              print("")
   103  
   104          if entries:
   105              num = len(entries)
   106              if 1 == num:
   107                  logging.info('Received one endpoint.')
   108              else:
   109                  logging.info('Received %d endpoints.' % num)
   110          else:
   111              logging.info('No endpoints found.')
   112  
   113  
   114      def __fetchList(self, rpctransport):
   115          dce = rpctransport.get_dce_rpc()
   116  
   117          dce.connect()
   118          #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_INTEGRITY)
   119          #dce.bind(epm.MSRPC_UUID_PORTMAP)
   120          #rpcepm = epm.DCERPCEpm(dce)
   121  
   122          resp = epm.hept_lookup(None, dce=dce)
   123  
   124          dce.disconnect()
   125  
   126          return resp
   127  
   128  
   129  # Process command-line arguments.
   130  if __name__ == '__main__':
   131      # Init the example's logger theme
   132      logger.init()
   133      print(version.BANNER)
   134  
   135      parser = argparse.ArgumentParser(add_help = True, description = "Dumps the remote RPC enpoints information.")
   136      parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
   137      parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
   138  
   139      group = parser.add_argument_group('connection')
   140  
   141      group.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If '
   142                         'ommited it will use whatever was specified as target. This is useful when target is the NetBIOS '
   143                         'name and you cannot resolve it')
   144      group.add_argument('-port', choices=['135', '139', '445'], nargs='?', default='135', metavar="destination port",
   145                         help='Destination port to connect to SMB Server')
   146  
   147      group = parser.add_argument_group('authentication')
   148  
   149      group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
   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      domain, username, password, remoteName = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(options.target).groups('')
   163  
   164      #In case the password contains '@'
   165      if '@' in remoteName:
   166          password = password + '@' + remoteName.rpartition('@')[0]
   167          remoteName = remoteName.rpartition('@')[2]
   168  
   169      if domain is None:
   170          domain = ''
   171  
   172      if password == '' and username != '' and options.hashes is None:
   173          from getpass import getpass
   174          password = getpass("Password:")
   175  
   176      if options.target_ip is None:
   177          options.target_ip = remoteName
   178  
   179      dumper = RPCDump(username, password, domain, options.hashes, int(options.port))
   180  
   181      dumper.dump(remoteName, options.target_ip)