def negotiateSession(self, preferredDialect=None, negSessionResponse=None):
        # Let's store some data for later use
        self._Connection['ClientSecurityMode'] = SMB2_NEGOTIATE_SIGNING_ENABLED
        if self.RequireMessageSigning is True:
            self._Connection[
                'ClientSecurityMode'] |= SMB2_NEGOTIATE_SIGNING_REQUIRED
        self._Connection['Capabilities'] = SMB2_GLOBAL_CAP_ENCRYPTION
        currentDialect = SMB2_DIALECT_WILDCARD

        # Do we have a negSessionPacket already?
        if negSessionResponse is not None:
            # Yes, let's store the dialect answered back
            negResp = SMB2Negotiate_Response(negSessionResponse['Data'])
            currentDialect = negResp['DialectRevision']

        if currentDialect == SMB2_DIALECT_WILDCARD:
            # Still don't know the chosen dialect, let's send our options

            packet = self.SMB_PACKET()
            packet['Command'] = SMB2_NEGOTIATE
            negSession = SMB2Negotiate()

            negSession['SecurityMode'] = self._Connection['ClientSecurityMode']
            negSession['Capabilities'] = self._Connection['Capabilities']
            negSession['ClientGuid'] = self.ClientGuid
            if preferredDialect is not None:
                negSession['Dialects'] = [preferredDialect]
                if preferredDialect == SMB2_DIALECT_311:
                    # Build the Contexts
                    contextData = SMB311ContextData()
                    contextData['NegotiateContextOffset'] = 64 + 38 + 2
                    contextData['NegotiateContextCount'] = 0
                    # Add an SMB2_NEGOTIATE_CONTEXT with ContextType as SMB2_PREAUTH_INTEGRITY_CAPABILITIES
                    # to the negotiate request as specified in section 2.2.3.1:
                    negotiateContext = SMB2NegotiateContext()
                    negotiateContext[
                        'ContextType'] = SMB2_PREAUTH_INTEGRITY_CAPABILITIES

                    preAuthIntegrityCapabilities = SMB2PreAuthIntegrityCapabilities(
                    )
                    preAuthIntegrityCapabilities['HashAlgorithmCount'] = 1
                    preAuthIntegrityCapabilities['SaltLength'] = 32
                    preAuthIntegrityCapabilities[
                        'HashAlgorithms'] = b'\x01\x00'
                    preAuthIntegrityCapabilities['Salt'] = ''.join([
                        rand.choice(string.ascii_letters) for _ in range(
                            preAuthIntegrityCapabilities['SaltLength'])
                    ])

                    negotiateContext[
                        'Data'] = preAuthIntegrityCapabilities.getData()
                    negotiateContext['DataLength'] = len(
                        negotiateContext['Data'])
                    contextData['NegotiateContextCount'] += 1
                    pad = b'\xFF' * (8 - (negotiateContext['DataLength'] % 8))

                    negotiateContext2 = SMB2NegotiateContext()
                    negotiateContext2[
                        'ContextType'] = SMB2_COMPRESSION_CAPABILITIES

                    compressionCapabilities = SMB2CompressionCapabilities()
                    compressionCapabilities['CompressionAlgorithmCount'] = 1
                    compressionCapabilities['Padding'] = 0
                    compressionCapabilities['Flags'] = 0
                    compressionCapabilities[
                        'CompressionAlgorithms'] = b'\x01\x00'

                    negotiateContext2[
                        'Data'] = compressionCapabilities.getData()
                    negotiateContext2['DataLength'] = len(
                        negotiateContext2['Data'])
                    contextData['NegotiateContextCount'] += 1

                    negSession['ClientStartTime'] = contextData.getData()
                    negSession['Padding'] = b'\xFF\xFF'
                    # Subsequent negotiate contexts MUST appear at the first 8-byte aligned offset following the
                    # previous negotiate context.
                    negSession[
                        'NegotiateContextList'] = negotiateContext.getData(
                        ) + pad + negotiateContext2.getData()

            else:
                negSession['Dialects'] = [
                    SMB2_DIALECT_002, SMB2_DIALECT_21, SMB2_DIALECT_30
                ]
            negSession['DialectCount'] = len(negSession['Dialects'])
            packet['Data'] = negSession

            packetID = self.sendSMB(packet)
            ans = self.recvSMB(packetID)
            if ans.isValidAnswer(STATUS_SUCCESS):
                negResp = SMB2Negotiate_Response(ans['Data'])

        self._Connection['MaxTransactSize'] = min(0x100000,
                                                  negResp['MaxTransactSize'])
        self._Connection['MaxReadSize'] = min(0x100000, negResp['MaxReadSize'])
        self._Connection['MaxWriteSize'] = min(0x100000,
                                               negResp['MaxWriteSize'])
        self._Connection['ServerGuid'] = negResp['ServerGuid']
        self._Connection['GSSNegotiateToken'] = negResp['Buffer']
        self._Connection['Dialect'] = negResp['DialectRevision']
        if (negResp['SecurityMode'] & SMB2_NEGOTIATE_SIGNING_REQUIRED) == SMB2_NEGOTIATE_SIGNING_REQUIRED or \
                self._Connection['Dialect'] == SMB2_DIALECT_311:
            self._Connection['RequireSigning'] = True
        if self._Connection['Dialect'] == SMB2_DIALECT_311:
            # Always Sign
            self._Connection['RequireSigning'] = True

        if (negResp['Capabilities']
                & SMB2_GLOBAL_CAP_LEASING) == SMB2_GLOBAL_CAP_LEASING:
            self._Connection['SupportsFileLeasing'] = True
        if (negResp['Capabilities']
                & SMB2_GLOBAL_CAP_LARGE_MTU) == SMB2_GLOBAL_CAP_LARGE_MTU:
            self._Connection['SupportsMultiCredit'] = True

        if self._Connection['Dialect'] >= SMB2_DIALECT_30:
            # Switching to the right packet format
            self.SMB_PACKET = SMB3Packet
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_DIRECTORY_LEASING
                ) == SMB2_GLOBAL_CAP_DIRECTORY_LEASING:
                self._Connection['SupportsDirectoryLeasing'] = True
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_MULTI_CHANNEL
                ) == SMB2_GLOBAL_CAP_MULTI_CHANNEL:
                self._Connection['SupportsMultiChannel'] = True
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES
                ) == SMB2_GLOBAL_CAP_PERSISTENT_HANDLES:
                self._Connection['SupportsPersistentHandles'] = True
            if (negResp['Capabilities'] &
                    SMB2_GLOBAL_CAP_ENCRYPTION) == SMB2_GLOBAL_CAP_ENCRYPTION:
                self._Connection['SupportsEncryption'] = True

            self._Connection['ServerCapabilities'] = negResp['Capabilities']
            self._Connection['ServerSecurityMode'] = negResp['SecurityMode']
Beispiel #2
0
    def negotiateSession(self, preferredDialect=None, negSessionResponse=None):
        # We DON'T want to sign
        self._Connection['ClientSecurityMode'] = 0

        if self.RequireMessageSigning is True:
            LOG.error('Signing is required, attack won\'t work!')
            return

        self._Connection['Capabilities'] = SMB2_GLOBAL_CAP_ENCRYPTION
        currentDialect = SMB2_DIALECT_WILDCARD

        # Do we have a negSessionPacket already?
        if negSessionResponse is not None:
            # Yes, let's store the dialect answered back
            negResp = SMB2Negotiate_Response(negSessionResponse['Data'])
            currentDialect = negResp['DialectRevision']

        if currentDialect == SMB2_DIALECT_WILDCARD:
            # Still don't know the chosen dialect, let's send our options

            packet = self.SMB_PACKET()
            packet['Command'] = SMB2_NEGOTIATE
            negSession = SMB2Negotiate()

            negSession['SecurityMode'] = self._Connection['ClientSecurityMode']
            negSession['Capabilities'] = self._Connection['Capabilities']
            negSession['ClientGuid'] = self.ClientGuid
            if preferredDialect is not None:
                negSession['Dialects'] = [preferredDialect]
            else:
                negSession['Dialects'] = [
                    SMB2_DIALECT_002, SMB2_DIALECT_21, SMB2_DIALECT_30
                ]
            negSession['DialectCount'] = len(negSession['Dialects'])
            packet['Data'] = negSession

            packetID = self.sendSMB(packet)
            ans = self.recvSMB(packetID)
            if ans.isValidAnswer(STATUS_SUCCESS):
                negResp = SMB2Negotiate_Response(ans['Data'])

        self._Connection['MaxTransactSize'] = min(0x100000,
                                                  negResp['MaxTransactSize'])
        self._Connection['MaxReadSize'] = min(0x100000, negResp['MaxReadSize'])
        self._Connection['MaxWriteSize'] = min(0x100000,
                                               negResp['MaxWriteSize'])
        self._Connection['ServerGuid'] = negResp['ServerGuid']
        self._Connection['GSSNegotiateToken'] = negResp['Buffer']
        self._Connection['Dialect'] = negResp['DialectRevision']
        if (negResp['SecurityMode'] & SMB2_NEGOTIATE_SIGNING_REQUIRED
            ) == SMB2_NEGOTIATE_SIGNING_REQUIRED:
            LOG.error('Signing is required, attack won\'t work!')
            return
        if (negResp['Capabilities']
                & SMB2_GLOBAL_CAP_LEASING) == SMB2_GLOBAL_CAP_LEASING:
            self._Connection['SupportsFileLeasing'] = True
        if (negResp['Capabilities']
                & SMB2_GLOBAL_CAP_LARGE_MTU) == SMB2_GLOBAL_CAP_LARGE_MTU:
            self._Connection['SupportsMultiCredit'] = True

        if self._Connection['Dialect'] == SMB2_DIALECT_30:
            # Switching to the right packet format
            self.SMB_PACKET = SMB3Packet
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_DIRECTORY_LEASING
                ) == SMB2_GLOBAL_CAP_DIRECTORY_LEASING:
                self._Connection['SupportsDirectoryLeasing'] = True
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_MULTI_CHANNEL
                ) == SMB2_GLOBAL_CAP_MULTI_CHANNEL:
                self._Connection['SupportsMultiChannel'] = True
            if (negResp['Capabilities'] & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES
                ) == SMB2_GLOBAL_CAP_PERSISTENT_HANDLES:
                self._Connection['SupportsPersistentHandles'] = True
            if (negResp['Capabilities'] &
                    SMB2_GLOBAL_CAP_ENCRYPTION) == SMB2_GLOBAL_CAP_ENCRYPTION:
                self._Connection['SupportsEncryption'] = True

            self._Connection['ServerCapabilities'] = negResp['Capabilities']
            self._Connection['ServerSecurityMode'] = negResp['SecurityMode']
Beispiel #3
0
    def getNegoAnswer(self, recvPacket):

        if self.isSMB2 is False:
            smbCommand = SMBCommand(recvPacket['Data'][0])
            respSMBCommand = SMBCommand(SMB.SMB_COM_NEGOTIATE)

            resp = NewSMBPacket()
            resp['Flags1'] = SMB.FLAGS1_REPLY
            resp['Pid'] = recvPacket['Pid']
            resp['Tid'] = recvPacket['Tid']
            resp['Mid'] = recvPacket['Mid']

            dialects = smbCommand['Data'].split('\x02')
            index = dialects.index('NT LM 0.12\x00') - 1
            # Let's fill the data for NTLM
            if recvPacket['Flags2'] & SMB.FLAGS2_EXTENDED_SECURITY:
                resp[
                    'Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE
                _dialects_data = SMBExtended_Security_Data()
                _dialects_data['ServerGUID'] = 'A' * 16
                blob = SPNEGO_NegTokenInit()
                blob['MechTypes'] = [
                    TypesMech[
                        'NTLMSSP - Microsoft NTLM Security Support Provider']
                ]
                _dialects_data['SecurityBlob'] = blob.getData()

                _dialects_parameters = SMBExtended_Security_Parameters()
                _dialects_parameters[
                    'Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS | SMB.CAP_UNICODE
                _dialects_parameters['ChallengeLength'] = 0

            else:
                resp['Flags2'] = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE
                _dialects_parameters = SMBNTLMDialect_Parameters()
                _dialects_data = SMBNTLMDialect_Data()
                _dialects_data['Payload'] = ''
                _dialects_data[
                    'Challenge'] = '\x11\x22\x33\x44\x55\x66\x77\x88'
                _dialects_parameters['ChallengeLength'] = 8
                _dialects_parameters[
                    'Capabilities'] = SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS

            _dialects_parameters['Capabilities'] |= SMB.CAP_RPC_REMOTE_APIS
            _dialects_parameters['DialectIndex'] = index
            _dialects_parameters[
                'SecurityMode'] = SMB.SECURITY_AUTH_ENCRYPTED | SMB.SECURITY_SHARE_USER
            _dialects_parameters['MaxMpxCount'] = 1
            _dialects_parameters['MaxNumberVcs'] = 1
            _dialects_parameters['MaxBufferSize'] = 64000
            _dialects_parameters['MaxRawSize'] = 65536
            _dialects_parameters['SessionKey'] = 0
            _dialects_parameters['LowDateTime'] = 0
            _dialects_parameters['HighDateTime'] = 0
            _dialects_parameters['ServerTimeZone'] = 0

            respSMBCommand['Data'] = _dialects_data
            respSMBCommand['Parameters'] = _dialects_parameters

            resp.addCommand(respSMBCommand)
        else:
            resp = SMB2Packet()
            resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
            resp['Status'] = STATUS_SUCCESS
            resp['CreditRequestResponse'] = 1
            resp['CreditCharge'] = 1
            resp['Command'] = SMB2_NEGOTIATE
            resp['SessionID'] = 0
            resp['MessageID'] = 0
            resp['TreeID'] = 0

            respSMBCommand = SMB2Negotiate_Response()

            respSMBCommand['SecurityMode'] = 1
            if isinstance(recvPacket, NewSMBPacket):
                respSMBCommand['DialectRevision'] = SMB2_DIALECT_WILDCARD
            else:
                respSMBCommand['DialectRevision'] = self.serverDialect
                resp['MessageID'] = 1
            respSMBCommand['ServerGuid'] = ''.join(
                [random.choice(string.letters) for _ in range(16)])
            respSMBCommand['Capabilities'] = 0x7
            respSMBCommand['MaxTransactSize'] = 65536
            respSMBCommand['MaxReadSize'] = 65536
            respSMBCommand['MaxWriteSize'] = 65536
            respSMBCommand['SystemTime'] = getFileTime(
                calendar.timegm(time.gmtime()))
            respSMBCommand['ServerStartTime'] = getFileTime(
                calendar.timegm(time.gmtime()))
            respSMBCommand['SecurityBufferOffset'] = 0x80

            blob = SPNEGO_NegTokenInit()
            blob['MechTypes'] = [
                TypesMech[
                    'NEGOEX - SPNEGO Extended Negotiation Security Mechanism'],
                TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']
            ]

            respSMBCommand['Buffer'] = blob.getData()
            respSMBCommand['SecurityBufferLength'] = len(
                respSMBCommand['Buffer'])

            resp['Data'] = respSMBCommand

        return resp