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']
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']