Exemplo n.º 1
0
 def getPage(self, pageNum):
     LOG.debug("Trying to fetch page %d (0x%x)" % (pageNum, (pageNum+1)*self.__pageSize))
     self.__DB.seek((pageNum+1)*self.__pageSize, 0)
     data = self.__DB.read(self.__pageSize)
     while len(data) < self.__pageSize:
         remaining = self.__pageSize - len(data)
         data += self.__DB.read(remaining)
     # Special case for the first page
     if pageNum <= 0:
         return data
     else:
         return ESENT_PAGE(self.__DBHeader, data)
Exemplo n.º 2
0
 def getPage(self, pageNum):
     LOG.debug("Trying to fetch page %d (0x%x)" %
               (pageNum, (pageNum + 1) * self.__pageSize))
     self.__DB.seek((pageNum + 1) * self.__pageSize, 0)
     data = self.__DB.read(self.__pageSize)
     while len(data) < self.__pageSize:
         remaining = self.__pageSize - len(data)
         data += self.__DB.read(remaining)
     # Special case for the first page
     if pageNum <= 0:
         return data
     else:
         return ESENT_PAGE(self.__DBHeader, data)
Exemplo n.º 3
0
 def __getBlock(self, offset):
     self.fd.seek(4096 + offset, 0)
     sizeBytes = self.fd.read(4)
     data = sizeBytes + self.fd.read(unpack("<l", sizeBytes)[0] * -1 - 4)
     if len(data) == 0:
         return None
     else:
         block = REG_HBINBLOCK(data)
         if StructMappings.has_key(block["Data"][:2]):
             return StructMappings[block["Data"][:2]](block["Data"])
         else:
             LOG.debug("Unknown type 0x%s" % block["Data"][:2])
             return block
         return None
Exemplo n.º 4
0
 def __getBlock(self, offset):
     self.fd.seek(4096 + offset, 0)
     sizeBytes = self.fd.read(4)
     data = sizeBytes + self.fd.read(unpack('<l', sizeBytes)[0] * -1 - 4)
     if len(data) == 0:
         return None
     else:
         block = REG_HBINBLOCK(data)
         if StructMappings.has_key(block['Data'][:2]):
             return StructMappings[block['Data'][:2]](block['Data'])
         else:
             LOG.debug("Unknown type 0x%s" % block['Data'][:2])
             return block
         return None
Exemplo n.º 5
0
def getKerberosType1(username,
                     password,
                     domain,
                     lmhash,
                     nthash,
                     aesKey='',
                     TGT=None,
                     TGS=None,
                     targetName='',
                     kdcHost=None,
                     useCache=True):
    if TGT is None and TGS is None:
        if useCache is True:
            try:
                ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
            except Exception, e:
                # No cache present
                pass
            else:
                LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME'))
                principal = 'host/%s@%s' % (targetName.upper(), domain.upper())
                creds = ccache.getCredential(principal)
                if creds is None:
                    # Let's try for the TGT and go from there
                    principal = 'krbtgt/%s@%s' % (domain.upper(),
                                                  domain.upper())
                    creds = ccache.getCredential(principal)
                    if creds is not None:
                        TGT = creds.toTGT()
                        LOG.debug('Using TGT from cache')
                    else:
                        LOG.debug("No valid credentials found in cache. ")
                else:
                    TGS = creds.toTGS()
Exemplo n.º 6
0
 def mountDB(self):
     LOG.debug("Mounting DB...")
     if self.__isRemote is True:
         self.__DB = self.__fileName
         self.__DB.open()
     else:
         self.__DB = open(self.__fileName,"rb")
     mainHeader = self.getPage(-1)
     self.__DBHeader = ESENT_DB_HEADER(mainHeader)
     self.__pageSize = self.__DBHeader['PageSize']
     self.__DB.seek(0,2)
     self.__totalPages = (self.__DB.tell() / self.__pageSize) -2
     LOG.debug("Database Version:0x%x, Revision:0x%x"% (self.__DBHeader['Version'], self.__DBHeader['FileFormatRevision']))
     LOG.debug("Page Size: %d" % self.__pageSize)
     LOG.debug("Total Pages in file: %d" % self.__totalPages)
     self.parseCatalog(CATALOG_PAGE_NUMBER)
Exemplo n.º 7
0
 def mountDB(self):
     LOG.debug("Mounting DB...")
     if self.__isRemote is True:
         self.__DB = self.__fileName
         self.__DB.open()
     else:
         self.__DB = open(self.__fileName, "rb")
     mainHeader = self.getPage(-1)
     self.__DBHeader = ESENT_DB_HEADER(mainHeader)
     self.__pageSize = self.__DBHeader['PageSize']
     self.__DB.seek(0, 2)
     self.__totalPages = (self.__DB.tell() / self.__pageSize) - 2
     LOG.debug("Database Version:0x%x, Revision:0x%x" %
               (self.__DBHeader['Version'],
                self.__DBHeader['FileFormatRevision']))
     LOG.debug("Page Size: %d" % self.__pageSize)
     LOG.debug("Total Pages in file: %d" % self.__totalPages)
     self.parseCatalog(CATALOG_PAGE_NUMBER)
Exemplo n.º 8
0
def getKerberosType1(username, password, domain, lmhash, nthash, aesKey='', TGT = None, TGS = None, targetName='', kdcHost = None, useCache = True):
    if TGT is None and TGS is None:
        if useCache is True:
            try:
                ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
            except Exception, e:
                # No cache present
                pass
            else:
                LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME'))
                principal = 'host/%s@%s' % (targetName.upper(), domain.upper())
                creds = ccache.getCredential(principal)
                if creds is None:
                    # Let's try for the TGT and go from there
                    principal = 'krbtgt/%s@%s' % (domain.upper(),domain.upper())
                    creds =  ccache.getCredential(principal)
                    if creds is not None:
                        TGT = creds.toTGT()
                        LOG.debug('Using TGT from cache')
                    else:
                        LOG.debug("No valid credentials found in cache. ")
                else:
                    TGS = creds.toTGS()
Exemplo n.º 9
0
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(
                        userName, password, domain, lmhash, nthash, aesKey,
                        kdcHost)
                except KerberosError, e:
                    if e.getErrorCode(
                    ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES
                        # So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if lmhash is '' and nthash is '' and (
                                aesKey is '' or aesKey is None
                        ) and TGT is None and TGS is None:
                            from mitmflib.impacket.ntlm import compute_lmhash, compute_nthash
                            LOG.debug(
                                'Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                            lmhash = compute_lmhash(password)
                            nthash = compute_nthash(password)
                            continue
                        else:
                            raise
                    else:
                        raise

        else:
            tgt = TGT['KDC_REP']
            cipher = TGT['cipher']
            sessionKey = TGT['sessionKey']

        # Now that we have the TGT, we should ask for a TGS for cifs
Exemplo n.º 10
0
    # First of all, we need to get a TGT for the user
    userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
    while True:
        if TGT is None:
            if TGS is None:
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)
                except KerberosError, e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES 
                        # So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None:
                            from mitmflib.impacket.ntlm import compute_lmhash, compute_nthash
                            LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4')
                            lmhash = compute_lmhash(password)
                            nthash = compute_nthash(password) 
                            continue
                        else:
                            raise 
                    else:
                        raise

        else:
            tgt = TGT['KDC_REP']
            cipher = TGT['cipher']
            sessionKey = TGT['sessionKey'] 

        # Now that we have the TGT, we should ask for a TGS for cifs
Exemplo n.º 11
0
    def __tagToRecord(self, cursor, tag):
        # So my brain doesn't forget, the data record is composed of:
        # Header
        # Fixed Size Data (ID < 127)
        #     The easiest to parse. Their size is fixed in the record. You can get its size
        #     from the Column Record, field SpaceUsage
        # Variable Size Data (127 < ID < 255)
        #     At VariableSizeOffset you get an array of two bytes per variable entry, pointing
        #     to the length of the value. Values start at:
        #                numEntries = LastVariableDataType - 127
        #                VariableSizeOffset + numEntries * 2 (bytes)
        # Tagged Data ( > 255 )
        #     After the Variable Size Value, there's more data for the tagged values.
        #     Right at the beggining there's another array (taggedItems), pointing to the
        #     values, size.
        #
        # The interesting thing about this DB records is there's no need for all the columns to be there, hence
        # saving space. That's why I got over all the columns, and if I find data (of any type), i assign it. If 
        # not, the column's empty.
        #
        # There are a lot of caveats in the code, so take your time to explore it. 
        #
        # ToDo: Better complete this description
        #

        record = OrderedDict()
        taggedItems = OrderedDict()
        taggedItemsParsed = False

        dataDefinitionHeader = ESENT_DATA_DEFINITION_HEADER(tag)
        #dataDefinitionHeader.dump()
        variableDataBytesProcessed = (dataDefinitionHeader['LastVariableDataType'] - 127) * 2
        prevItemLen = 0
        tagLen = len(tag)
        fixedSizeOffset = len(dataDefinitionHeader)
        variableSizeOffset = dataDefinitionHeader['VariableSizeOffset'] 
 
        columns = cursor['TableData']['Columns'] 
        
        for column in columns.keys():
            columnRecord = columns[column]['Record']
            #columnRecord.dump()
            if columnRecord['Identifier'] <= dataDefinitionHeader['LastFixedSize']:
                # Fixed Size column data type, still available data
                record[column] = tag[fixedSizeOffset:][:columnRecord['SpaceUsage']]
                fixedSizeOffset += columnRecord['SpaceUsage']

            elif 127 < columnRecord['Identifier'] <= dataDefinitionHeader['LastVariableDataType']:
                # Variable data type
                index = columnRecord['Identifier'] - 127 - 1
                itemLen = unpack('<H',tag[variableSizeOffset+index*2:][:2])[0]

                if itemLen & 0x8000:
                    # Empty item
                    itemLen = prevItemLen
                    record[column] = None
                else:
                    itemValue = tag[variableSizeOffset+variableDataBytesProcessed:][:itemLen-prevItemLen]
                    record[column] = itemValue

                #if columnRecord['Identifier'] <= dataDefinitionHeader['LastVariableDataType']:
                variableDataBytesProcessed +=itemLen-prevItemLen

                prevItemLen = itemLen

            elif columnRecord['Identifier'] > 255:
                # Have we parsed the tagged items already?
                if taggedItemsParsed is False and (variableDataBytesProcessed+variableSizeOffset) < tagLen:
                    index = variableDataBytesProcessed+variableSizeOffset
                    #hexdump(tag[index:])
                    endOfVS = self.__pageSize
                    firstOffsetTag = (unpack('<H', tag[index+2:][:2])[0] & 0x3fff) + variableDataBytesProcessed+variableSizeOffset
                    while True:
                        taggedIdentifier = unpack('<H', tag[index:][:2])[0]
                        index += 2
                        taggedOffset = (unpack('<H', tag[index:][:2])[0] & 0x3fff) 
                        # As of Windows 7 and later ( version 0x620 revision 0x11) the 
                        # tagged data type flags are always present
                        if self.__DBHeader['Version'] == 0x620 and self.__DBHeader['FileFormatRevision'] >= 17 and self.__DBHeader['PageSize'] > 8192: 
                            flagsPresent = 1
                        else:
                            flagsPresent = (unpack('<H', tag[index:][:2])[0] & 0x4000)
                        index += 2
                        if taggedOffset < endOfVS:
                            endOfVS = taggedOffset
                        taggedItems[taggedIdentifier] = (taggedOffset, tagLen, flagsPresent)
                        #print "ID: %d, Offset:%d, firstOffset:%d, index:%d, flag: 0x%x" % (taggedIdentifier, taggedOffset,firstOffsetTag,index, flagsPresent)
                        if index >= firstOffsetTag:
                            # We reached the end of the variable size array
                            break
                
                    # Calculate length of variable items
                    # Ugly.. should be redone
                    prevKey = taggedItems.keys()[0]
                    for i in range(1,len(taggedItems)):
                        offset0, length, flags = taggedItems[prevKey]
                        offset, _, _ = taggedItems.items()[i][1]
                        taggedItems[prevKey] = (offset0, offset-offset0, flags)
                        #print "ID: %d, Offset: %d, Len: %d, flags: %d" % (prevKey, offset0, offset-offset0, flags)
                        prevKey = taggedItems.keys()[i]
                    taggedItemsParsed = True
 
                # Tagged data type
                if taggedItems.has_key(columnRecord['Identifier']):
                    offsetItem = variableDataBytesProcessed + variableSizeOffset + taggedItems[columnRecord['Identifier']][0] 
                    itemSize = taggedItems[columnRecord['Identifier']][1]
                    # If item have flags, we should skip them
                    if taggedItems[columnRecord['Identifier']][2] > 0:
                        itemFlag = ord(tag[offsetItem:offsetItem+1])
                        offsetItem += 1
                        itemSize -= 1
                    else:
                        itemFlag = 0

                    #print "ID: %d, itemFlag: 0x%x" %( columnRecord['Identifier'], itemFlag)
                    if itemFlag & (TAGGED_DATA_TYPE_COMPRESSED ):
                        LOG.error('Unsupported tag column: %s, flag:0x%x' % (column, itemFlag))
                        record[column] = None
                    elif itemFlag & TAGGED_DATA_TYPE_MULTI_VALUE:
                        # ToDo: Parse multi-values properly
                        LOG.debug('Multivalue detected in column %s, returning raw results' % (column))
                        record[column] = (hexlify(tag[offsetItem:][:itemSize]),)
                    else:
                        record[column] = tag[offsetItem:][:itemSize]

                else:
                    record[column] = None
            else:
                record[column] = None

            # If we understand the data type, we unpack it and cast it accordingly
            # otherwise, we just encode it in hex
            if type(record[column]) is tuple:
                # A multi value data, we won't decode it, just leave it this way
                record[column] = record[column][0]
            elif columnRecord['ColumnType'] == JET_coltypText or columnRecord['ColumnType'] == JET_coltypLongText: 
                # Let's handle strings
                if record[column] is not None:
                    if columnRecord['CodePage'] not in StringCodePages:
                        LOG.error('Unknown codepage 0x%x'% columnRecord['CodePage'])
                        raise
                    stringDecoder = StringCodePages[columnRecord['CodePage']]

                    record[column] = record[column].decode(stringDecoder)
                
            else:
                unpackData = ColumnTypeSize[columnRecord['ColumnType']]
                if record[column] is not None:
                    if unpackData is None:
                        record[column] = hexlify(record[column])
                    else:
                        unpackStr = unpackData[1]
                        unpackSize = unpackData[0]
                        record[column] = unpack(unpackStr, record[column])[0]

        return record
Exemplo n.º 12
0
 def readHeader(self):
     LOG.debug("Reading Boot Sector for %s" % self.__volumeName)
Exemplo n.º 13
0
    def __tagToRecord(self, cursor, tag):
        # So my brain doesn't forget, the data record is composed of:
        # Header
        # Fixed Size Data (ID < 127)
        #     The easiest to parse. Their size is fixed in the record. You can get its size
        #     from the Column Record, field SpaceUsage
        # Variable Size Data (127 < ID < 255)
        #     At VariableSizeOffset you get an array of two bytes per variable entry, pointing
        #     to the length of the value. Values start at:
        #                numEntries = LastVariableDataType - 127
        #                VariableSizeOffset + numEntries * 2 (bytes)
        # Tagged Data ( > 255 )
        #     After the Variable Size Value, there's more data for the tagged values.
        #     Right at the beggining there's another array (taggedItems), pointing to the
        #     values, size.
        #
        # The interesting thing about this DB records is there's no need for all the columns to be there, hence
        # saving space. That's why I got over all the columns, and if I find data (of any type), i assign it. If
        # not, the column's empty.
        #
        # There are a lot of caveats in the code, so take your time to explore it.
        #
        # ToDo: Better complete this description
        #

        record = OrderedDict()
        taggedItems = OrderedDict()
        taggedItemsParsed = False

        dataDefinitionHeader = ESENT_DATA_DEFINITION_HEADER(tag)
        #dataDefinitionHeader.dump()
        variableDataBytesProcessed = (
            dataDefinitionHeader['LastVariableDataType'] - 127) * 2
        prevItemLen = 0
        tagLen = len(tag)
        fixedSizeOffset = len(dataDefinitionHeader)
        variableSizeOffset = dataDefinitionHeader['VariableSizeOffset']

        columns = cursor['TableData']['Columns']

        for column in columns.keys():
            columnRecord = columns[column]['Record']
            #columnRecord.dump()
            if columnRecord['Identifier'] <= dataDefinitionHeader[
                    'LastFixedSize']:
                # Fixed Size column data type, still available data
                record[column] = tag[
                    fixedSizeOffset:][:columnRecord['SpaceUsage']]
                fixedSizeOffset += columnRecord['SpaceUsage']

            elif 127 < columnRecord['Identifier'] <= dataDefinitionHeader[
                    'LastVariableDataType']:
                # Variable data type
                index = columnRecord['Identifier'] - 127 - 1
                itemLen = unpack('<H',
                                 tag[variableSizeOffset + index * 2:][:2])[0]

                if itemLen & 0x8000:
                    # Empty item
                    itemLen = prevItemLen
                    record[column] = None
                else:
                    itemValue = tag[variableSizeOffset +
                                    variableDataBytesProcessed:][:itemLen -
                                                                 prevItemLen]
                    record[column] = itemValue

                #if columnRecord['Identifier'] <= dataDefinitionHeader['LastVariableDataType']:
                variableDataBytesProcessed += itemLen - prevItemLen

                prevItemLen = itemLen

            elif columnRecord['Identifier'] > 255:
                # Have we parsed the tagged items already?
                if taggedItemsParsed is False and (
                        variableDataBytesProcessed +
                        variableSizeOffset) < tagLen:
                    index = variableDataBytesProcessed + variableSizeOffset
                    #hexdump(tag[index:])
                    endOfVS = self.__pageSize
                    firstOffsetTag = (
                        unpack('<H', tag[index + 2:][:2])[0] & 0x3fff
                    ) + variableDataBytesProcessed + variableSizeOffset
                    while True:
                        taggedIdentifier = unpack('<H', tag[index:][:2])[0]
                        index += 2
                        taggedOffset = (unpack('<H', tag[index:][:2])[0]
                                        & 0x3fff)
                        # As of Windows 7 and later ( version 0x620 revision 0x11) the
                        # tagged data type flags are always present
                        if self.__DBHeader['Version'] == 0x620 and self.__DBHeader[
                                'FileFormatRevision'] >= 17 and self.__DBHeader[
                                    'PageSize'] > 8192:
                            flagsPresent = 1
                        else:
                            flagsPresent = (unpack('<H', tag[index:][:2])[0]
                                            & 0x4000)
                        index += 2
                        if taggedOffset < endOfVS:
                            endOfVS = taggedOffset
                        taggedItems[taggedIdentifier] = (taggedOffset, tagLen,
                                                         flagsPresent)
                        #print "ID: %d, Offset:%d, firstOffset:%d, index:%d, flag: 0x%x" % (taggedIdentifier, taggedOffset,firstOffsetTag,index, flagsPresent)
                        if index >= firstOffsetTag:
                            # We reached the end of the variable size array
                            break

                    # Calculate length of variable items
                    # Ugly.. should be redone
                    prevKey = taggedItems.keys()[0]
                    for i in range(1, len(taggedItems)):
                        offset0, length, flags = taggedItems[prevKey]
                        offset, _, _ = taggedItems.items()[i][1]
                        taggedItems[prevKey] = (offset0, offset - offset0,
                                                flags)
                        #print "ID: %d, Offset: %d, Len: %d, flags: %d" % (prevKey, offset0, offset-offset0, flags)
                        prevKey = taggedItems.keys()[i]
                    taggedItemsParsed = True

                # Tagged data type
                if taggedItems.has_key(columnRecord['Identifier']):
                    offsetItem = variableDataBytesProcessed + variableSizeOffset + taggedItems[
                        columnRecord['Identifier']][0]
                    itemSize = taggedItems[columnRecord['Identifier']][1]
                    # If item have flags, we should skip them
                    if taggedItems[columnRecord['Identifier']][2] > 0:
                        itemFlag = ord(tag[offsetItem:offsetItem + 1])
                        offsetItem += 1
                        itemSize -= 1
                    else:
                        itemFlag = 0

                    #print "ID: %d, itemFlag: 0x%x" %( columnRecord['Identifier'], itemFlag)
                    if itemFlag & (TAGGED_DATA_TYPE_COMPRESSED):
                        LOG.error('Unsupported tag column: %s, flag:0x%x' %
                                  (column, itemFlag))
                        record[column] = None
                    elif itemFlag & TAGGED_DATA_TYPE_MULTI_VALUE:
                        # ToDo: Parse multi-values properly
                        LOG.debug(
                            'Multivalue detected in column %s, returning raw results'
                            % (column))
                        record[column] = (hexlify(
                            tag[offsetItem:][:itemSize]), )
                    else:
                        record[column] = tag[offsetItem:][:itemSize]

                else:
                    record[column] = None
            else:
                record[column] = None

            # If we understand the data type, we unpack it and cast it accordingly
            # otherwise, we just encode it in hex
            if type(record[column]) is tuple:
                # A multi value data, we won't decode it, just leave it this way
                record[column] = record[column][0]
            elif columnRecord['ColumnType'] == JET_coltypText or columnRecord[
                    'ColumnType'] == JET_coltypLongText:
                # Let's handle strings
                if record[column] is not None:
                    if columnRecord['CodePage'] not in StringCodePages:
                        LOG.error('Unknown codepage 0x%x' %
                                  columnRecord['CodePage'])
                        raise
                    stringDecoder = StringCodePages[columnRecord['CodePage']]

                    record[column] = record[column].decode(stringDecoder)

            else:
                unpackData = ColumnTypeSize[columnRecord['ColumnType']]
                if record[column] is not None:
                    if unpackData is None:
                        record[column] = hexlify(record[column])
                    else:
                        unpackStr = unpackData[1]
                        unpackSize = unpackData[0]
                        record[column] = unpack(unpackStr, record[column])[0]

        return record
Exemplo n.º 14
0
 def readHeader(self):
     LOG.debug("Reading Boot Sector for %s" % self.__volumeName)
Exemplo n.º 15
0
    def kerberosLogin(self, user, password, domain = '', lmhash = '', nthash = '', aesKey = '', kdcHost=None, TGT=None, TGS=None, useCache = True):
        """
        logins into the target system explicitly using Kerberos. Hashes are used if RC4_HMAC is supported.

        :param string user: username
        :param string password: password for the user
        :param string domain: domain where the account is valid for (required)
        :param string lmhash: LMHASH used to authenticate using hashes (password is not used)
        :param string nthash: NTHASH used to authenticate using hashes (password is not used)
        :param string aesKey: aes256-cts-hmac-sha1-96 or aes128-cts-hmac-sha1-96 used for Kerberos authentication
        :param string kdcHost: hostname or IP Address for the KDC. If None, the domain will be used (it needs to resolve tho)
        :param struct TGT: If there's a TGT available, send the structure here and it will be used
        :param struct TGS: same for TGS. See smb3.py for the format
        :param bool useCache: whether or not we should use the ccache for credentials lookup. If TGT or TGS are specified this is False

        :return: None, raises a Session Error if error.
        """
        import os
        from mitmflib.impacket.krb5.ccache import CCache
        from mitmflib.impacket.krb5.kerberosv5 import KerberosError
        from mitmflib.impacket.krb5 import constants
        from mitmflib.impacket.ntlm import compute_lmhash, compute_nthash

        if TGT is not None or TGS is not None:
            useCache = False

        if useCache is True:
            try:
                ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
            except:
                # No cache present
                pass
            else:
                LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME'))
                principal = 'cifs/%s@%s' % (self.getRemoteHost().upper(), domain.upper())
                creds = ccache.getCredential(principal)
                if creds is None:
                    # Let's try for the TGT and go from there
                    principal = 'krbtgt/%s@%s' % (domain.upper(),domain.upper())
                    creds =  ccache.getCredential(principal)
                    if creds is not None:
                        TGT = creds.toTGT()
                        LOG.debug('Using TGT from cache')
                    else:
                        LOG.debug("No valid credentials found in cache. ")
                else:
                    TGS = creds.toTGS()
                    LOG.debug('Using TGS from cache')

        while True:
            try:
                if self.getDialect() == smb.SMB_DIALECT:
                    return self._SMBConnection.kerberos_login(user, password, domain, lmhash, nthash, aesKey, kdcHost, TGT, TGS)
                return self._SMBConnection.kerberosLogin(user, password, domain, lmhash, nthash, aesKey, kdcHost, TGT, TGS)
            except (smb.SessionError, smb3.SessionError), e:
                raise SessionError(e.get_error_code())
            except KerberosError, e:
                if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                    # We might face this if the target does not support AES
                    # So, if that's the case we'll force using RC4 by converting
                    # the password to lm/nt hashes and hope for the best. If that's already
                    # done, byebye.
                    if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None:
                        from mitmflib.impacket.ntlm import compute_lmhash, compute_nthash
                        lmhash = compute_lmhash(password) 
                        nthash = compute_nthash(password) 
                    else:
                        raise e
                else:
                    raise e