Beispiel #1
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        #authdata is only for api compatibility reasons
        if is_rpc == True:
            if self.iterations == 0:
                flags = ISC_REQ.CONFIDENTIALITY | \
                  ISC_REQ.INTEGRITY | \
                  ISC_REQ.MUTUAL_AUTH | \
                  ISC_REQ.REPLAY_DETECT | \
                  ISC_REQ.SEQUENCE_DETECT|\
                  ISC_REQ.USE_DCE_STYLE

                token = self.ksspi.get_ticket_for_spn(self.target,
                                                      flags=flags,
                                                      is_rpc=True,
                                                      token_data=authData)
                print(token.hex())
                self.iterations += 1
                return token, True

            elif self.iterations == 1:
                flags = ISC_REQ.USE_DCE_STYLE

                token = self.ksspi.get_ticket_for_spn(self.target,
                                                      flags=flags,
                                                      is_rpc=True,
                                                      token_data=authData)
                print(token.hex())

                aprep = AP_REP.load(token).native

                subkey = Key(aprep['enc-part']['etype'],
                             self.get_session_key())

                cipher_text = aprep['enc-part']['cipher']
                cipher = _enctype_table[aprep['enc-part']['etype']]()

                plaintext = cipher.decrypt(subkey, 12, cipher_text)
                print('plaintext')
                input(plaintext.hex())

                self.gssapi = get_gssapi(subkey)

                input(self.gssapi)
                self.iterations += 1
                return token, False

            else:
                raise Exception('???????')

        else:
            apreq = self.ksspi.get_ticket_for_spn(self.target)
            return apreq, False
Beispiel #2
0
    def from_tgt(ksoc, tgt, key):
        """
        Sets up the kerberos object from tgt and the session key.
        Use this function when pulling the TGT from ccache file.
        """
        kc = KerbrosComm(None, ksoc)
        kc.kerberos_TGT = tgt

        kc.kerberos_cipher_type = key['keytype']
        kc.kerberos_session_key = Key(kc.kerberos_cipher_type, key['keyvalue'])
        kc.kerberos_cipher = _enctype_table[kc.kerberos_cipher_type]
        return kc
Beispiel #3
0
    async def authenticate(self,
                           authData,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        if self.iterations == 0:
            #tgt = await self.kc.get_TGT(override_etype=[18])
            tgt = await self.kc.get_TGT()
            tgs, encpart, self.session_key = await self.kc.get_TGS(self.target)
        ap_opts = []
        if is_rpc == True:
            if self.iterations == 0:
                ap_opts.append('mutual-required')
                flags = ChecksumFlags.GSS_C_CONF_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG | ChecksumFlags.GSS_C_SEQUENCE_FLAG|\
                  ChecksumFlags.GSS_C_REPLAY_FLAG | ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_DCE_STYLE

                apreq = self.kc.construct_apreq(tgs,
                                                encpart,
                                                self.session_key,
                                                flags=flags,
                                                seq_number=seq_number,
                                                ap_opts=ap_opts)
                self.iterations += 1
                return apreq, False

            else:
                #mutual authentication part here
                aprep = AP_REP.load(authData).native
                cipher = _enctype_table[int(aprep['enc-part']['etype'])]()
                cipher_text = aprep['enc-part']['cipher']
                temp = cipher.decrypt(self.session_key, 12, cipher_text)

                enc_part = EncAPRepPart.load(temp).native
                cipher = _enctype_table[int(enc_part['subkey']['keytype'])]()

                now = datetime.datetime.utcnow()
                apreppart_data = {}
                apreppart_data['cusec'] = now.microsecond
                apreppart_data['ctime'] = now
                apreppart_data['seq-number'] = enc_part['seq-number']

                apreppart_data_enc = cipher.encrypt(
                    self.session_key, 12,
                    EncAPRepPart(apreppart_data).dump(), None)

                #overriding current session key
                self.session_key = Key(cipher.enctype,
                                       enc_part['subkey']['keyvalue'])

                ap_rep = {}
                ap_rep['pvno'] = 5
                ap_rep['msg-type'] = MESSAGE_TYPE.KRB_AP_REP.value
                ap_rep['enc-part'] = EncryptedData({
                    'etype': self.session_key.enctype,
                    'cipher': apreppart_data_enc
                })

                token = AP_REP(ap_rep).dump()

                self.gssapi = get_gssapi(self.session_key)
                self.iterations += 1

                return token, False
        else:
            apreq = self.kc.construct_apreq(tgs,
                                            encpart,
                                            self.session_key,
                                            flags=flags,
                                            seq_number=seq_number,
                                            ap_opts=ap_opts)
            return apreq, False
Beispiel #4
0
    def S4U2self(self,
                 user_to_impersonate,
                 supp_enc_methods=SUPPORTED_METHODS):
        """
        user_to_impersonate : KerberosTarget class
        """

        if not self.kerberos_TGT:
            logger.debug(
                'S4U2self invoked, but TGT is not available! Fetching TGT...')
            self.get_TGT()

        supp_enc = self.usercreds.get_preferred_enctype(supp_enc_methods)
        auth_package_name = 'Kerberos'
        now = datetime.datetime.utcnow()

        # Calculating authenticator data
        authenticator_data = {}
        authenticator_data['authenticator-vno'] = krb5_pvno
        authenticator_data['crealm'] = Realm(
            as_str(self.kerberos_TGT['crealm']))
        authenticator_data['cname'] = self.kerberos_TGT['cname']
        authenticator_data['cusec'] = now.microsecond
        authenticator_data['ctime'] = now

        authenticator_data_enc = self.kerberos_cipher.encrypt(
            self.kerberos_session_key, 7,
            Authenticator(authenticator_data).dump(), None)

        ap_req = {}
        ap_req['pvno'] = krb5_pvno
        ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
        ap_req['ap-options'] = APOptions(set())
        ap_req['ticket'] = Ticket(self.kerberos_TGT['ticket'])
        ap_req['authenticator'] = EncryptedData({
            'etype':
            self.kerberos_cipher_type,
            'cipher':
            authenticator_data_enc
        })

        pa_data_auth = {}
        pa_data_auth['padata-type'] = PaDataType.TGS_REQ.value
        pa_data_auth['padata-value'] = AP_REQ(ap_req).dump()

        # Calculating checksum data

        S4UByteArray = NAME_TYPE.PRINCIPAL.value.to_bytes(4,
                                                          'little',
                                                          signed=False)
        S4UByteArray += user_to_impersonate.username.encode()
        S4UByteArray += user_to_impersonate.domain.encode()
        S4UByteArray += auth_package_name.encode()
        logger.debug('S4U2self: S4UByteArray: %s' % as_hex(S4UByteArray))
        logger.debug('S4U2self: S4UByteArray: %s' % S4UByteArray)

        chksum_data = _HMACMD5.checksum(self.kerberos_session_key, 17,
                                        S4UByteArray)
        logger.debug('S4U2self: chksum_data: %s' % as_hex(chksum_data))

        chksum = {}
        chksum['cksumtype'] = int(CKSUMTYPE('HMAC_MD5'))
        chksum['checksum'] = chksum_data

        # Filling out PA-FOR-USER data for impersonation
        pa_for_user_enc = {}
        pa_for_user_enc['userName'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string':
            user_to_impersonate.get_principalname()
        })
        pa_for_user_enc['userRealm'] = user_to_impersonate.domain
        pa_for_user_enc['cksum'] = Checksum(chksum)
        pa_for_user_enc['auth-package'] = auth_package_name

        pa_for_user = {}
        pa_for_user['padata-type'] = int(PADATA_TYPE('PA-FOR-USER'))
        pa_for_user['padata-value'] = PA_FOR_USER_ENC(pa_for_user_enc).dump()

        # Constructing body

        krb_tgs_body = {}
        krb_tgs_body['kdc-options'] = KDCOptions(
            set(['forwardable', 'renewable', 'canonicalize']))
        krb_tgs_body['sname'] = PrincipalName({
            'name-type':
            NAME_TYPE.UNKNOWN.value,
            'name-string': [self.usercreds.username]
        })
        krb_tgs_body['realm'] = self.usercreds.domain.upper()
        krb_tgs_body['till'] = now + datetime.timedelta(days=1)
        krb_tgs_body['nonce'], = struct.unpack('>i', os.urandom(4))
        # selecting according to server's preferences
        krb_tgs_body['etype'] = [supp_enc.value]

        krb_tgs_req = {}
        krb_tgs_req['pvno'] = krb5_pvno
        krb_tgs_req['msg-type'] = MESSAGE_TYPE.KRB_TGS_REQ.value
        krb_tgs_req['padata'] = [pa_data_auth, pa_for_user]
        krb_tgs_req['req-body'] = KDC_REQ_BODY(krb_tgs_body)

        req = TGS_REQ(krb_tgs_req)

        logger.debug('Sending S4U2self request to server')
        try:
            reply = self.ksoc.sendrecv(req.dump())
        except KerberosError as e:
            if e.errorcode.value == 16:
                logger.error(
                    'S4U2self: Failed to get S4U2self! Error code (16) indicates that delegation is not enabled for this account! Full error: %s'
                    % e)

            raise

        logger.debug('Got S4U2self reply, decrypting...')
        tgs = reply.native

        encTGSRepPart = EncTGSRepPart.load(
            self.kerberos_cipher.decrypt(self.kerberos_session_key, 8,
                                         tgs['enc-part']['cipher'])).native

        key = Key(encTGSRepPart['key']['keytype'],
                  encTGSRepPart['key']['keyvalue'])

        self.ccache.add_tgs(tgs, encTGSRepPart)
        logger.debug('Got valid TGS reply')
        self.kerberos_TGS = tgs
        return tgs, encTGSRepPart, key
Beispiel #5
0
    def get_TGS(self, spn_user, override_etype=None, is_linux=False):
        """
        Requests a TGS ticket for the specified user.
        Retruns the TGS ticket, end the decrpyted encTGSRepPart.

        spn_user: KerberosTarget: the service user you want to get TGS for.
        override_etype: None or list of etype values (int) Used mostly for kerberoasting, will override the AP_REQ supported etype values (which is derived from the TGT) to be able to recieve whatever tgs tiecket
        """
        # construct tgs_req
        logger.debug('Constructing TGS request for user %s' %
                     spn_user.get_formatted_pname())
        now = datetime.datetime.utcnow()
        kdc_req_body = {}
        kdc_req_body['kdc-options'] = KDCOptions(
            set(['forwardable', 'renewable', 'renewable_ok', 'canonicalize']))
        kdc_req_body['realm'] = as_str(spn_user.domain.upper())

        logger.debug('TGS principal: %s', spn_user.get_principalname())

        kdc_req_body['sname'] = PrincipalName({
            'name-type':
            NAME_TYPE.SRV_INST.value,
            'name-string':
            as_str(spn_user.get_principalname())
        })
        kdc_req_body['till'] = now + datetime.timedelta(days=1)
        kdc_req_body['nonce'], = struct.unpack('>i', os.urandom(4))
        if override_etype:
            kdc_req_body['etype'] = override_etype
        else:
            kdc_req_body['etype'] = [self.kerberos_cipher_type]

        authenticator_data = {}
        authenticator_data['authenticator-vno'] = krb5_pvno
        authenticator_data['crealm'] = Realm(
            as_str(self.kerberos_TGT['crealm']))
        authenticator_data['cname'] = self.kerberos_TGT['cname']
        authenticator_data['cusec'] = now.microsecond
        authenticator_data['ctime'] = now

        if is_linux:
            ac = AuthenticatorChecksum()
            ac.flags = 0
            ac.channel_binding = b'\x00' * 16

            chksum = {}
            chksum['cksumtype'] = 0x8003
            chksum['checksum'] = ac.to_bytes()
            print(chksum['checksum'])

            authenticator_data['cksum'] = Checksum(chksum)
            authenticator_data['seq-number'] = 0

        authenticator_data_enc = self.kerberos_cipher.encrypt(
            self.kerberos_session_key, 7,
            Authenticator(authenticator_data).dump(), None)

        ap_req = {}
        ap_req['pvno'] = krb5_pvno
        ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
        ap_req['ap-options'] = APOptions(set())
        ap_req['ticket'] = Ticket(self.kerberos_TGT['ticket'])
        ap_req['authenticator'] = EncryptedData({
            'etype':
            self.kerberos_cipher_type,
            'cipher':
            authenticator_data_enc
        })

        pa_data_1 = {}
        pa_data_1['padata-type'] = PaDataType.TGS_REQ.value
        pa_data_1['padata-value'] = AP_REQ(ap_req).dump()

        kdc_req = {}
        kdc_req['pvno'] = krb5_pvno
        kdc_req['msg-type'] = MESSAGE_TYPE.KRB_TGS_REQ.value
        kdc_req['padata'] = [pa_data_1]
        kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)

        req = TGS_REQ(kdc_req)
        logger.debug('Constructing TGS request to server')
        rep = self.ksoc.sendrecv(req.dump())
        logger.debug('Got TGS reply, decrypting...')
        tgs = rep.native

        encTGSRepPart = EncTGSRepPart.load(
            self.kerberos_cipher.decrypt(self.kerberos_session_key, 8,
                                         tgs['enc-part']['cipher'])).native
        key = Key(encTGSRepPart['key']['keytype'],
                  encTGSRepPart['key']['keyvalue'])

        self.ccache.add_tgs(tgs, encTGSRepPart)
        logger.debug('Got valid TGS reply')
        self.kerberos_TGS = tgs
        return tgs, encTGSRepPart, key
Beispiel #6
0
    def get_TGT(self, override_etype=None, decrypt_tgt=True):
        """
        decrypt_tgt: used for asreproast attacks
        Steps performed:
            1. Send and empty (no encrypted timestamp) AS_REQ with all the encryption types we support
            2. Depending on the response (either error or AS_REP with TGT) we either send another AS_REQ with the encrypted data or return the TGT (or fail miserably)
            3. PROFIT
        """
        logger.debug('Generating initial TGT without authentication data')

        now = datetime.datetime.utcnow()
        kdc_req_body = {}
        kdc_req_body['kdc-options'] = KDCOptions(
            set(['forwardable', 'renewable', 'proxiable']))

        kdc_req_body['cname'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string': [as_str(self.usercreds.username)]
        })

        kdc_req_body['realm'] = as_str(self.usercreds.domain.upper())
        kdc_req_body['sname'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string': ['krbtgt',
                            as_str(self.usercreds.domain).upper()]
        })

        kdc_req_body['till'] = now + datetime.timedelta(days=1)
        kdc_req_body['rtime'] = now + datetime.timedelta(days=1)
        kdc_req_body['nonce'], = struct.unpack('>i', os.urandom(4))

        if override_etype is None:
            kdc_req_body['etype'] = self.usercreds.get_supported_enctypes()
        else:
            kdc_req_body['etype'] = override_etype

        pa_data_1 = {}
        pa_data_1['padata-type'] = int(PADATA_TYPE('PA-PAC-REQUEST'))
        pa_data_1['padata-value'] = PA_PAC_REQUEST({
            'include-pac': True
        }).dump()

        kdc_req = {}
        kdc_req['pvno'] = krb5_pvno
        kdc_req['msg-type'] = MESSAGE_TYPE.KRB_AS_REQ.value
        kdc_req['padata'] = [pa_data_1]
        kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)

        req = AS_REQ(kdc_req)

        logger.debug('Sending initial TGT to %s' % self.ksoc.get_addr_str())
        rep = self.ksoc.sendrecv(req.dump(), throw=False)

        if rep.name != 'KRB_ERROR':
            # user can do kerberos auth without preauthentication!
            self.kerberos_TGT = rep.native

            # if we want to roast the asrep (tgt rep) part then we dont even have the proper keys to decrypt
            # so we just return, the asrep can be extracted from this object anyhow
            if decrypt_tgt == False:
                return

            self.kerberos_cipher = _get_enctype_profile[23]
            self.kerberos_cipher_type = 23
            self.kerberos_key = Key(
                self.kerberos_cipher.enctype,
                self.usercreds.get_key_for_enctype(
                    EncryptionType.ARCFOUR_HMAC_MD5))
        else:
            if rep.native[
                    'error-code'] != KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED.value:
                raise KerberosError(rep)
            rep = rep.native
            logger.debug('Got reply from server, asikg to provide auth data')

            rep = self.do_preauth(rep)
            logger.debug('Got valid TGT response from server')
            rep = rep.native
            self.kerberos_TGT = rep

        cipherText = rep['enc-part']['cipher']
        temp = self.kerberos_cipher.decrypt(self.kerberos_key, 3, cipherText)
        try:
            self.kerberos_TGT_encpart = EncASRepPart.load(temp).native
        except Exception as e:
            logger.debug('EncAsRepPart load failed, is this linux?')
            try:
                self.kerberos_TGT_encpart = EncTGSRepPart.load(temp).native
            except Exception as e:
                logger.error('Failed to load decrypted part of the reply!')
                raise

        self.kerberos_session_key = Key(
            self.kerberos_cipher.enctype,
            self.kerberos_TGT_encpart['key']['keyvalue'])
        self.ccache.add_tgt(self.kerberos_TGT,
                            self.kerberos_TGT_encpart,
                            override_pp=True)
        logger.debug('Got valid TGT')

        return
Beispiel #7
0
    def do_preauth(self, rep):
        # now getting server's supported encryption methods

        supp_enc_methods = collections.OrderedDict()
        for enc_method in METHOD_DATA.load(rep['e-data']).native:
            data_type = PaDataType(enc_method['padata-type'])

            if data_type == PaDataType.ETYPE_INFO or data_type == PaDataType.ETYPE_INFO2:
                if data_type == PaDataType.ETYPE_INFO:
                    enc_info_list = ETYPE_INFO.load(enc_method['padata-value'])

                elif data_type == PaDataType.ETYPE_INFO2:
                    enc_info_list = ETYPE_INFO2.load(
                        enc_method['padata-value'])

                for enc_info in enc_info_list.native:
                    supp_enc_methods[EncryptionType(
                        enc_info['etype'])] = enc_info['salt']
                    logger.debug(
                        'Server supports encryption type %s with salt %s' %
                        (EncryptionType(
                            enc_info['etype']).name, enc_info['salt']))

        logger.debug('Constructing TGT request with auth data')
        # now to create an AS_REQ with encrypted timestamp for authentication
        pa_data_1 = {}
        pa_data_1['padata-type'] = int(PADATA_TYPE('PA-PAC-REQUEST'))
        pa_data_1['padata-value'] = PA_PAC_REQUEST({
            'include-pac': True
        }).dump()

        now = datetime.datetime.utcnow()
        # creating timestamp asn1
        timestamp = PA_ENC_TS_ENC({
            'patimestamp': now,
            'pausec': now.microsecond
        }).dump()

        supp_enc = self.usercreds.get_preferred_enctype(supp_enc_methods)
        logger.debug('Selecting common encryption type: %s' % supp_enc.name)
        self.kerberos_cipher = _get_enctype_profile(supp_enc.value)
        self.kerberos_cipher_type = supp_enc.value
        if 'salt' in enc_info and enc_info['salt'] is not None:
            self.server_salt = enc_info['salt'].encode()
        self.kerberos_key = Key(
            self.kerberos_cipher.enctype,
            self.usercreds.get_key_for_enctype(supp_enc,
                                               salt=self.server_salt))
        enc_timestamp = self.kerberos_cipher.encrypt(self.kerberos_key, 1,
                                                     timestamp, None)

        pa_data_2 = {}
        pa_data_2['padata-type'] = int(PADATA_TYPE('ENC-TIMESTAMP'))
        pa_data_2['padata-value'] = EncryptedData({
            'etype': supp_enc.value,
            'cipher': enc_timestamp
        }).dump()

        kdc_req_body = {}
        kdc_req_body['kdc-options'] = KDCOptions(
            set(['forwardable', 'renewable', 'proxiable']))
        kdc_req_body['cname'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string': [as_str(self.usercreds.username)]
        })
        kdc_req_body['realm'] = as_str(self.usercreds.domain.upper())
        kdc_req_body['sname'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string': ['krbtgt',
                            as_str(self.usercreds.domain.upper())]
        })
        kdc_req_body['till'] = now + datetime.timedelta(days=1)
        kdc_req_body['rtime'] = now + datetime.timedelta(days=1)
        kdc_req_body['nonce'], = struct.unpack('>i', os.urandom(4))
        # selecting according to server's preferences
        kdc_req_body['etype'] = [supp_enc.value]

        kdc_req = {}
        kdc_req['pvno'] = krb5_pvno
        kdc_req['msg-type'] = MESSAGE_TYPE.KRB_AS_REQ.value
        kdc_req['padata'] = [pa_data_2, pa_data_1]
        kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)

        req = AS_REQ(kdc_req)

        logger.debug('Sending TGT request to server')
        return self.ksoc.sendrecv(req.dump())
	logging.debug('Getting TGT')
	
	kc = KerbrosComm(ccred, ksoc)
	kc.get_TGT()
	#kc.ccache.to_file(args.ccache)	
	logging.info('Done!')
	
	if args.verbose > 1:
		pprint.pprint(kc.kerberos_TGT)
		pprint.pprint(kc.kerberos_TGT_encpart)
	
	
	
	krbtgt_data = kc.kerberos_TGT['ticket']['enc-part']['cipher']
	et = EncryptionType(kc.kerberos_TGT['ticket']['enc-part']['etype'])
	krbtgt_key = Key(kc.kerberos_TGT['ticket']['enc-part']['etype'], ccred_krbtgt.get_key_for_enctype(et))
	
	krbtgt_cipher = _enctype_table[kc.kerberos_TGT['ticket']['enc-part']['etype']]
	
	temp = krbtgt_cipher.decrypt(krbtgt_key, kc.kerberos_TGT['ticket']['enc-part']['kvno'], krbtgt_data)
	print(temp.hex())
	krbtgt_enc = EncTicketPart.load(temp).native
	pprint.pprint(krbtgt_enc)
	
	#print(krbtgt_enc['authorization-data'][0]['ad-data'])
	ad_data = AD_IF_RELEVANT.load(krbtgt_enc['authorization-data'][0]['ad-data'])
	
	with open('addata.bin','wb') as f:
		f.write(ad_data.native[0]['ad-data'])
	
	
ccred = KerberosCredential()
ccred.username = '******'
ccred.domain = 'TEST.corp'

ccred2 = KerberosCredential()
ccred2.username = '******'
ccred2.domain = 'TEST.corp'

creds = [ccred, ccred2]

ks = KerberosSocket('192.168.9.1')

ar = APREPRoast(ks)
res = ar.run(creds)

rep = res[0]
print(res)

x, a, enctype, checksum, data = rep.split('$')

password = '******'
cipher = _enctype_table[int(enctype)]
key = Key(int(enctype),
          hashlib.new('md4', password.encode('utf-16-le')).digest())
cipherText = bytes.fromhex(checksum + data)
temp = cipher.decrypt(key, 3, cipherText)
print()
print()
print(temp.hex())
enc_as_rep_part = EncASRepPart.load(temp).native
#print(enc_as_rep_part)
Beispiel #10
0
import logging
from minikerberos.common import *
from minikerberos.communication import *
from minikerberos.ccache import CCACHE
from minikerberos.encryption import _enctype_table, Key
import pprint

ccred_krbtgt = KerberosCredential.from_connection_string(
    'DEMO1.FREEIPA.ORG/admin/pass:[email protected]')

cipher_data = bytes.fromhex(
    'a4134a8692a021f735418c549daad0ae2f7b309c027f20efebf52e0e0b6d0b269e0ff54c2af22cad5c67de121612e2eef0007d70b5798536a94bf9a4ee87da0de9df15ffc65a9e63eabc96edd4fb9659db8a40cb6fe0ee0336d79bc8f1c8df59287d6d8db1180ca00feb581445f57cf9b22c2cbe83354736ecc230948883db7507f094869dfc98bf2b8331690ed3f9e45760d97db175bfba9232366cb3e5faa38aa5770c5e62aa60c3e829e9c2c9835fa255611310a7364f55e90626714b69d9c03cd5c2ee1fb47590dfa403039803b243149bdfe7c3d9d4859969f7e2e3c96ac89f5cb3a4123ffbf2c35b340afd1ad3e1b32b978901b596901c957ce4894f4939b096051e9d3acf4ef942c5bc7806b39d51d0b08bd4fdd52be0f560af2760914ea814fce7b85a0172'
)

et = EncryptionType(18)
krbtgt_key = Key(
    18, ccred_krbtgt.get_key_for_enctype(et, salt="dc{< 5&c0'85-Y4K".encode()))
krbtgt_cipher = _enctype_table[18]
temp = krbtgt_cipher.decrypt(krbtgt_key, 3, cipher_data)
print(temp.hex())
krbtgt_enc = EncTGSRepPart.load(temp).native
pprint.pprint(krbtgt_enc)

session_key = Key(18, krbtgt_enc['key']['keyvalue'])
session_cipher = _enctype_table[18]

cipherText = bytes.fromhex(
    '351505edf3ecbb9fcf59299f28d23fd514e50b884f729ed43e6abf12451448e1e6db7a6da5dec0a39202eaa69b8be5ef4529e2006021fde7a1239d53904c9e06cdab9ba02fcc6b369d2421cdc21e7ee691c2958e3117159c5f572ba86fdd2208207fd15acd036eb11b18bf3654e344b5322463b6bfca45ee3c6e2f57c560fd8d70450a59e6a9b5499b48953017644f99282979c5220a1f6bc76ef9cdc5153ddd133b2541dee35f7c8e4607dd192eabbf'
)
temp = session_cipher.decrypt(session_key, 7, cipherText)
print(temp.hex())
auth = Authenticator.load(temp).native