Ejemplo n.º 1
0
    def setup_crypto(self):
        if self.mode.upper() == 'SERVER':
            self.EncryptedRandomSessionKey = self.ntlmAuthenticate.EncryptedRandomSession
            print('self.EncryptedRandomSessionKey %s' %
                  self.EncryptedRandomSessionKey)
            rc4 = RC4(self.KeyExchangeKey)
            self.RandomSessionKey = rc4.decrypt(self.EncryptedRandomSessionKey)

        else:
            if not self.RandomSessionKey:
                self.RandomSessionKey = os.urandom(16)

            if self.mode.upper() != 'MANUAL':
                #this check is here to provide the option to load the messages + the sessionbasekey manually
                #then you will be able to use the sign and seal functions provided by this class
                if self.settings.credential.is_guest == False:
                    self.SessionBaseKey = self.ntlm_credentials.SessionBaseKey

                rc4 = RC4(self.KeyExchangeKey)
                self.EncryptedRandomSessionKey = rc4.encrypt(
                    self.RandomSessionKey)

        self.calc_sealkey('Client')
        self.calc_sealkey('Server')
        self.calc_signkey('Client')
        self.calc_signkey('Server')
Ejemplo n.º 2
0
    async def sign(self, data, message_no, direction=None, reset_cipher=False):
        """
		Singing outgoing messages. The reset_cipher parameter is needed for calculating mechListMIC. 
		"""
        #print('sign data : %s' % data)
        #print('sign message_no : %s' % message_no)
        #print('sign direction : %s' % direction)
        signature = self.MAC(self.crypthandle_client.encrypt,
                             self.SignKey_client, message_no, data)
        if reset_cipher is True:
            self.crypthandle_client = RC4(self.SealKey_client)
            self.crypthandle_server = RC4(self.SealKey_server)
        self.seq_number += 1
        return signature
Ejemplo n.º 3
0
    def decrypt_lsa_key(self, data):
        logger.debug('[SECURITY] Decrypting LSA key...')
        if self.lsa_secret_key_vista_type is True:
            record = LSA_SECRET.from_bytes(data)
            key = SECURITY.sha256_multi(self.bootkey, record.data[:32])
            secret_dec = b''
            cipher = AES(key)
            n = 16
            for block in [
                    record.data[32:][i:i + n]
                    for i in range(0, len(record.data[32:]), n)
            ]:  #terrible, terrible workaround
                if len(block) < n:
                    block += b'\x00' * (n - len(block))
                secret_dec += cipher.decrypt(block)
            record = LSA_SECRET_BLOB.from_bytes(secret_dec)
            self.lsa_key = record.secret[52:][:32]

        else:
            ctx = hashlib.md5(self.bootkey)
            for i in range(1000):
                ctx.update(data[60:76])

            cipher = RC4(ctx.digest())
            record = cipher.decrypt(data[12:60])
            self.lsa_key = record[0x10:0x20]

        logger.debug('[SECURITY] LSA key value: %s' % self.lsa_key.hex())
        return self.lsa_key
Ejemplo n.º 4
0
    def decrypt_hash(self, rid, hashobj, constant):
        key1, key2 = SAM.rid_to_key(rid)
        des1 = DES(key1)
        des2 = DES(key2)

        if isinstance(hashobj, SAM_HASH):
            rc4key = hashlib.md5(
                self.hashed_bootkey[:0x10] +
                int(rid, 16).to_bytes(4, 'little', signed=False) +
                constant).digest()
            key = RC4(rc4key).encrypt(hashobj.hash)

        else:
            key = b''
            cipher = AES(self.hashed_bootkey[:0x10], MODE_CBC, IV=hashobj.salt)
            n = 16
            for block in [
                    hashobj.data[i:i + n]
                    for i in range(0, len(hashobj.data), n)
            ]:  #terrible, terrible workaround
                key += cipher.decrypt(block)

            key = key[:16]

        dec_hash = des1.decrypt(key[:8]) + des2.decrypt(key[8:])
        return dec_hash
Ejemplo n.º 5
0
    def calc_sealkey(self, mode='Client'):
        if NegotiateFlags.NEGOTIATE_EXTENDED_SESSIONSECURITY in self.ntlmChallenge.NegotiateFlags:
            if NegotiateFlags.NEGOTIATE_128 in self.ntlmChallenge.NegotiateFlags:
                sealkey = self.RandomSessionKey
            elif NegotiateFlags.NEGOTIATE_56 in self.ntlmChallenge.NegotiateFlags:
                sealkey = self.RandomSessionKey[:7]
            else:
                sealkey = self.RandomSessionKey[:5]

            if mode == 'Client':
                md5 = hashlib.new('md5')
                md5.update(
                    sealkey +
                    b'session key to client-to-server sealing key magic constant\x00'
                )
                sealkey = md5.digest()
            else:
                md5 = hashlib.new('md5')
                md5.update(
                    sealkey +
                    b'session key to server-to-client sealing key magic constant\x00'
                )
                sealkey = md5.digest()

        elif NegotiateFlags.NEGOTIATE_56 in self.ntlmChallenge.NegotiateFlags:
            sealkey = self.RandomSessionKey[:7] + b'\xa0'
        else:
            sealkey = self.RandomSessionKey[:5] + b'\xe5\x38\xb0'

        if mode == 'Client':
            self.SealKey_client = sealkey
            if sealkey is not None:
                self.crypthandle_client = RC4(self.SealKey_client)
        else:
            self.SealKey_server = sealkey
            if sealkey is not None:
                self.crypthandle_server = RC4(self.SealKey_server)

        return sealkey
Ejemplo n.º 6
0
    def decrypt(self, encrypted):
        # TODO: NT version specific, move from here in subclasses.
        cleartext = b''
        size = len(encrypted)
        if size:
            if (size % 8) != 0:
                ctx = RC4(self.random_key)
                cleartext = ctx.decrypt(encrypted)
            else:
                #print('Decryption not implemented!')
                cleartext = self.__desx_decrypt(encrypted)
                #raise Exception('Not implemented!')

        return cleartext
Ejemplo n.º 7
0
    def setup_crypto(self):
        if not self.RandomSessionKey:
            self.RandomSessionKey = os.urandom(16)

        if self.mode.upper() != 'MANUAL':
            #this check is here to provide the option to load the messages + the sessionbasekey manually
            #then you will be able to use the sign and seal functions provided by this class
            self.SessionBaseKey = self.ntlm_credentials.SessionBaseKey

            rc4 = RC4(self.KeyExchangeKey)
            self.EncryptedRandomSessionKey = rc4.encrypt(self.RandomSessionKey)

        self.calc_sealkey('Client')
        self.calc_sealkey('Server')
        self.calc_signkey('Client')
        self.calc_signkey('Server')
Ejemplo n.º 8
0
def DecryptAttributeValue(sessionKey, attribute):

	encryptedPayload = ENCRYPTED_PAYLOAD(attribute)

	md5 = hashlib.new('md5')
	md5.update(sessionKey)
	md5.update(encryptedPayload['Salt'])
	finalMD5 = md5.digest()

	cipher = RC4(finalMD5)
	plainText = cipher.decrypt(attribute[16:])

	#chkSum = (binascii.crc32(plainText[4:])) & 0xffffffff
	#if unpack('<L',plainText[:4])[0] != chkSum:
	#	print "RECEIVED 0x%x" % unpack('<L',plainText[:4])[0]
	#	print "CALCULATED 0x%x" % chkSum

	return plainText[4:]
Ejemplo n.º 9
0
    def GSS_GetMIC(self, data, sequenceNumber, direction='init'):
        raise Exception('Not tested! Sure it needs some changes')
        GSS_GETMIC_HEADER = b'\x60\x23\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02'

        # Let's pad the data
        pad = (4 - (len(data) % 4)) & 0x3
        padStr = bytes([pad]) * pad
        data += padStr

        mic = GSSMIC_RC4()

        if direction == 'init':
            mic.SND_SEQ = sequenceNumber.to_bytes(4, 'big',
                                                  signed=False) + b'\x00' * 4
        else:
            mic.SND_SEQ = sequenceNumber.to_bytes(4, 'big',
                                                  signed=False) + b'\xff' * 4

        Ksign_ctx = hmac.new(self.session_key.contents, digestmod='md5')
        Ksign_ctx.update(b'signaturekey\0')
        Ksign = Ksign_ctx.digest()

        id = 15
        temp = md5(
            id.to_bytes(4, 'little', signed=False) +
            mic.to_bytes()[:8]).digest()
        chksum_ctx = hmac.new(Ksign, digestmod='md5')
        chksum_ctx.update(temp)
        mic.SGN_CKSUM = chksum_ctx.digest()[:8]

        id = 0
        temp = hmac.new(self.session_key.contents, digestmod='md5')
        temp.update(id.to_bytes(4, 'little', signed=False))

        Kseq_ctx = hmac.new(temp.digest(), digestmod='md5')
        Kseq_ctx.update(mic.SGN_CKSUM)
        Kseq = Kseq_ctx.digest()

        mic.SGN_CKSUM = RC4(Kseq).encrypt(mic.SND_SEQ)

        return GSS_GETMIC_HEADER + mic.to_bytes()
Ejemplo n.º 10
0
    async def get_HBoot_key(self):
        logger.debug('SAM parsing hashed bootkey')
        QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
        DIGITS = b"0123456789012345678901234567890123456789\0"

        F = await self.hive.get_value(r'SAM\Domains\Account\F')
        F = F[1]
        logger.log(1, '[SAM] F key value: %s' % F)

        domain_properties = DOMAIN_ACCOUNT_F.from_bytes(F)

        if isinstance(domain_properties.key_0, SAM_KEY_DATA):
            rc4_key = hashlib.md5(domain_properties.key_0.salt + QWERTY +
                                  self.bootkey + DIGITS).digest()
            self.hashed_bootkey = RC4(rc4_key).encrypt(
                domain_properties.key_0.key + domain_properties.key_0.checksum)

            checksum = hashlib.md5(self.hashed_bootkey[:16] + DIGITS +
                                   self.hashed_bootkey[:16] + QWERTY).digest()

            if checksum != self.hashed_bootkey[16:]:
                logger.error('[SAM] HBootkey checksum verification failed!')
                raise Exception('[SAM] HBootkey checksum verification failed!')

        elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES):
            self.hashed_bootkey = b''
            cipher = AES(self.bootkey,
                         MODE_CBC,
                         IV=domain_properties.key_0.salt)
            n = 16
            for block in [
                    domain_properties.key_0.data[i:i + n]
                    for i in range(0, len(domain_properties.key_0.data), n)
            ]:  #terrible, terrible workaround
                self.hashed_bootkey += cipher.decrypt(block)

        logger.debug('[SAM] HBootkey: %s' % self.hashed_bootkey.hex())
        return self.hashed_bootkey
Ejemplo n.º 11
0
    def dump_dcc(self):
        logger.debug('[SECURITY] dump_dcc invoked')
        cache_reg = self.hive.find_key('Cache', False)
        if cache_reg is None:
            logger.debug('[SECURITY] No DCC secrets found')
            return
        values = self.hive.list_values(cache_reg)

        if values == []:
            logger.debug('[SECURITY] No DCC secrets found')
            return

        if b'NL$Control' in values:
            values.remove(b'NL$Control')

        if b'NL$IterationCount' in values:
            logger.debug('[SECURITY] DCC Setting iteration count')
            values.remove(b'NL$IterationCount')
            record = self.hive.get_value('Cache\\NL$IterationCount')[1]
            if record > 10240:
                self.dcc_iteration_count = record & 0xfffffc00
            else:
                self.dcc_iteration_count = record * 1024

        self.get_lsa_key()
        self.get_NKLM_key()

        for value in values:
            logger.debug('[SECURITY] DCC Checking value: %s' % value)
            record_data = self.hive.get_value('Cache\\%s' % value.decode())[1]
            record = NL_RECORD.from_bytes(record_data)

            if record.IV != b'\x00' * 16:
                if record.Flags & 1 == 1:
                    # Encrypted
                    if self.lsa_secret_key_vista_type is True:
                        plaintext = b''
                        cipher = AES(self.NKLM_key[16:32],
                                     MODE_CBC,
                                     IV=record.IV)
                        n = 16
                        for block in [
                                record.EncryptedData[i:i + n]
                                for i in range(0, len(record.EncryptedData), n)
                        ]:  #terrible, terrible workaround
                            if len(block) < 16:
                                block += b'\x00' * (16 - len(block))
                            plaintext += cipher.decrypt(block)

                    else:
                        key = hmac.new(self.NKLM_key,
                                       record.IV,
                                       digestmod='md5').digest()
                        cipher = RC4(key)
                        plaintext = cipher.decrypt(record.EncryptedData)

                else:
                    # Plain! Until we figure out what this is, we skip it
                    #plainText = record['EncryptedData']
                    logger.debug(
                        '[SECURITY] DCC Skipping value %s, unknown formet' %
                        value)
                    continue

                dcc_hash = plaintext[:0x10]
                blob = io.BytesIO(plaintext[0x48:])
                username = blob.read(record.UserLength).decode('utf-16-le')
                blob.seek(
                    self.__pad(record.UserLength) +
                    self.__pad(record.DomainNameLength))
                domain = blob.read(
                    record.DnsDomainNameLength).decode('utf-16-le')

                version = 2 if self.lsa_secret_key_vista_type is True else 1
                secret = LSADCCSecret(version,
                                      domain,
                                      username,
                                      dcc_hash,
                                      iteration=self.dcc_iteration_count)
                self.dcc_hashes.append(secret)

        return self.dcc_hashes
Ejemplo n.º 12
0
    def GSS_Wrap(self,
                 data,
                 seq_num,
                 direction='init',
                 encrypt=True,
                 auth_data=None):
        GSS_WRAP_HEADER = b'\x60\x2b\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02'

        pad = (8 - (len(data) % 8)) & 0x7
        padStr = bytes([pad]) * pad
        data += padStr

        token = GSSWRAP_RC4()
        token.SEAL_ALG = b'\x10\x00'

        if direction == 'init':
            token.SND_SEQ = seq_num.to_bytes(4, 'big',
                                             signed=False) + b'\x00' * 4
        else:
            token.SND_SEQ = seq_num.to_bytes(4, 'big',
                                             signed=False) + b'\xff' * 4

        token.Confounder = os.urandom(8)

        temp = hmac.new(self.session_key.contents, digestmod='md5')
        temp.update(b'signaturekey\0')
        Ksign = temp.digest()

        id = 13
        Sgn_Cksum = md5(
            id.to_bytes(4, 'little', signed=False) + token.to_bytes()[:8] +
            token.Confounder + data).digest()
        temp = hmac.new(Ksign, digestmod='md5')
        temp.update(Sgn_Cksum)
        token.SGN_CKSUM = temp.digest()[:8]

        klocal = b''
        for b in self.session_key.contents:
            klocal += bytes([b ^ 0xf0])

        id = 0
        temp = hmac.new(klocal, digestmod='md5')
        temp.update(id.to_bytes(4, 'little', signed=False))
        temp = hmac.new(temp.digest(), digestmod='md5')
        temp.update(seq_num.to_bytes(4, 'big', signed=False))
        Kcrypt = temp.digest()

        id = 0
        temp = hmac.new(self.session_key.contents, digestmod='md5')
        temp.update(id.to_bytes(4, 'little', signed=False))
        temp = hmac.new(temp.digest(), digestmod='md5')
        temp.update(token.SGN_CKSUM)
        Kseq = temp.digest()

        token.SND_SEQ = RC4(Kseq).encrypt(token.SND_SEQ)

        if auth_data is not None:
            wrap = GSSWRAP_RC4.from_bytes(auth_data[8 + len(GSS_WRAP_HEADER):])

            id = 0
            temp = hmac.new(self.session_key.contents, digestmod='md5')
            temp.update(id.to_bytes(4, 'little', signed=False))
            temp = hmac.new(temp.digest(), digestmod='md5')
            temp.update(wrap.SGN_CKSUM)

            snd_seq = RC4(temp.digest()).encrypt(wrap.SND_SEQ)

            id = 0
            temp = hmac.new(klocal, digestmod='md5')
            temp.update(id.to_bytes(4, 'little', signed=False))
            temp = hmac.new(temp.digest(), digestmod='md5')
            temp.update(snd_seq[:4])
            Kcrypt = temp.digest()

            rc4 = RC4(Kcrypt)
            cipherText = rc4.decrypt(token.Confounder + data)[8:]

        elif encrypt is True:
            rc4 = RC4(Kcrypt)
            token.Confounder = rc4.encrypt(token.Confounder)
            cipherText = rc4.encrypt(data)

        else:
            cipherText = data

        finalData = GSS_WRAP_HEADER + token.to_bytes()
        return cipherText, finalData
Ejemplo n.º 13
0
    def GSS_Wrap(self,
                 data,
                 seq_num,
                 direction='init',
                 encrypt=True,
                 cofounder=None):
        #direction = 'a'
        #seq_num = 0
        #print('[GSS_Wrap] data: %s' % data)
        #print('[GSS_Wrap] seq_num: %s' % seq_num.to_bytes(4, 'big', signed = False).hex())
        #print('[GSS_Wrap] direction: %s' % direction)
        #print('[GSS_Wrap] encrypt: %s' % encrypt)
        #
        #print('[GSS_Wrap] auth_data: %s' % auth_data)

        #pad = 0
        if encrypt is True:
            data += b'\x01'
            #pad = (8 - (len(data) % 8)) & 0x7
            #padStr = bytes([pad]) * pad
            #data += padStr
            #
            ##data += b'\x08' * 8
            #print('[GSS_Wrap] pad: %s' % pad)
            #print('[GSS_Wrap] data padded: %s' % data)

        token = GSSWRAP_RC4()
        token.SEAL_ALG = b'\x10\x00'  # RC4

        if direction == 'init':
            token.SND_SEQ = seq_num.to_bytes(4, 'big',
                                             signed=False) + b'\x00' * 4
        else:
            token.SND_SEQ = seq_num.to_bytes(4, 'big',
                                             signed=False) + b'\xff' * 4

        token.Confounder = os.urandom(8)
        #if cofounder is not None:
        #	token.Confounder = cofounder
        #	#testing purposes only, pls remove

        temp = hmac.new(self.session_key.contents, digestmod='md5')
        temp.update(b'signaturekey\0')
        Ksign = temp.digest()

        id = 13
        Sgn_Cksum = md5(
            id.to_bytes(4, 'little', signed=False) + token.to_bytes()[:8] +
            token.Confounder + data).digest()

        klocal = b''
        for b in self.session_key.contents:
            klocal += bytes([b ^ 0xf0])

        id = 0
        temp = hmac.new(klocal, digestmod='md5')
        temp.update(id.to_bytes(4, 'little', signed=False))
        temp = hmac.new(temp.digest(), digestmod='md5')
        temp.update(seq_num.to_bytes(4, 'big', signed=False))
        Kcrypt = temp.digest()

        temp = hmac.new(Ksign, digestmod='md5')
        temp.update(Sgn_Cksum)
        token.SGN_CKSUM = temp.digest()[:8]

        id = 0
        temp = hmac.new(self.session_key.contents, digestmod='md5')
        temp.update(id.to_bytes(4, 'little', signed=False))
        temp = hmac.new(temp.digest(), digestmod='md5')
        temp.update(token.SGN_CKSUM)
        Kseq = temp.digest()

        token.SND_SEQ = RC4(Kseq).encrypt(token.SND_SEQ)

        #if auth_data is not None:
        if encrypt is False:
            #print('Unwrap sessionkey: %s' % self.session_key.contents.hex())
            #print('Unwrap data      : %s' % data.hex())

            sspi_wrap = KRB5_MECH_INDEP_TOKEN.from_bytes(data)

            hdr = sspi_wrap.data[:32]
            data = sspi_wrap.data[32:]

            wrap = GSSWRAP_RC4.from_bytes(hdr)

            id = 0
            temp = hmac.new(self.session_key.contents, digestmod='md5')
            temp.update(id.to_bytes(4, 'little', signed=False))
            temp = hmac.new(temp.digest(), digestmod='md5')
            temp.update(wrap.SGN_CKSUM)
            Kseq = temp.digest()

            snd_seq = RC4(Kseq).encrypt(wrap.SND_SEQ)

            id = 0
            temp = hmac.new(klocal, digestmod='md5')
            temp.update(id.to_bytes(4, 'little', signed=False))
            temp = hmac.new(temp.digest(), digestmod='md5')
            temp.update(snd_seq[:4])
            Kcrypt = temp.digest()

            rc4 = RC4(Kcrypt)
            dec_cofounder = rc4.decrypt(wrap.Confounder)
            dec_data = rc4.decrypt(data)

            id = 13
            Sgn_Cksum_calc = md5(
                id.to_bytes(4, 'little', signed=False) + wrap.to_bytes()[:8] +
                dec_cofounder + dec_data).digest()

            temp = hmac.new(Ksign, digestmod='md5')
            temp.update(Sgn_Cksum_calc)
            Sgn_Cksum_calc = temp.digest()[:8]

            if wrap.SGN_CKSUM != Sgn_Cksum_calc[:8]:
                return None, Exception('Integrity verification failed')

            pad = 1
            return dec_data[:-pad], None

        elif encrypt is True:
            rc4 = RC4(Kcrypt)
            token.Confounder = rc4.encrypt(token.Confounder)
            cipherText = rc4.encrypt(data)
            finalData, cipherText = KRB5_MECH_INDEP_TOKEN(
                token.to_bytes() + cipherText,
                '1.2.840.113554.1.2.2').to_bytes()

            #print('cipherText  %s' % cipherText.hex())
            #print('finalData   %s' % finalData.hex())
            #print('sessionkey  %s' % self.session_key.contents.hex())
            return cipherText, finalData
Ejemplo n.º 14
0
    async def bind(self,
                   iface_uuid,
                   alter=0,
                   bogus_binds=0,
                   transfer_syntax=('8a885d04-1ceb-11c9-9fe8-08002b104860',
                                    '2.0')):
        """
		Performs bind operation. Does authentication and sets up the keys for further communication
		"""
        try:
            bind = MSRPCBind()
            #item['TransferSyntax']['Version'] = 1
            ctx = self.ctx
            for _ in range(bogus_binds):
                item = CtxItem()
                item['ContextID'] = ctx
                item['TransItems'] = 1
                item['ContextID'] = ctx
                # We generate random UUIDs for bogus binds
                item['AbstractSyntax'] = generate() + stringver_to_bin('2.0')
                item['TransferSyntax'] = uuidtup_to_bin(transfer_syntax)
                bind.addCtxItem(item)
                self.ctx += 1
                ctx += 1

            # The true one :)
            item = CtxItem()
            item['AbstractSyntax'] = iface_uuid
            item['TransferSyntax'] = uuidtup_to_bin(transfer_syntax)
            item['ContextID'] = ctx
            item['TransItems'] = 1
            bind.addCtxItem(item)

            packet = MSRPCHeader()
            packet['type'] = MSRPC_BIND
            packet['pduData'] = bind.getData()
            packet['call_id'] = self.callid

            if alter:
                packet['type'] = MSRPC_ALTERCTX

            if self.auth_level != RPC_C_AUTHN_LEVEL_NONE:
                #authentication required
                if self.auth_type == RPC_C_AUTHN_WINNT:

                    #seal flag MUST be turned on in the handshake flags!!!!!!!
                    #it is "signaled via the is_rpc variable"
                    auth, res, err = await self.gssapi.ntlm.authenticate(
                        None, is_rpc=True)
                    if err is not None:
                        return None, err

                elif self.auth_type == RPC_C_AUTHN_NETLOGON:
                    return False, Exception(
                        'RPC_C_AUTHN_NETLOGON Not implemented!')

                elif self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE:
                    auth, res, err  = await self.gssapi.gssapi.authenticate(
                     None,
                     flags = GSSAPIFlags.GSS_C_CONF_FLAG |\
                       GSSAPIFlags.GSS_C_INTEG_FLAG | \
                       GSSAPIFlags.GSS_C_SEQUENCE_FLAG | \
                       GSSAPIFlags.GSS_C_REPLAY_FLAG | \
                       GSSAPIFlags.GSS_C_MUTUAL_FLAG | \
                       GSSAPIFlags.GSS_C_DCE_STYLE,
                     seq_number = 0,
                     is_rpc = True
                    )
                    if err is not None:
                        return None, err
                else:
                    return None, Exception('Unsupported auth type!')

                sec_trailer = SEC_TRAILER()
                sec_trailer['auth_type'] = self.auth_type
                sec_trailer['auth_level'] = self.auth_level
                sec_trailer['auth_ctx_id'] = self.ctx + 79231

                pad = (4 - (len(packet.get_packet()) % 4)) % 4
                if pad != 0:
                    packet['pduData'] += b'\xFF' * pad
                    sec_trailer['auth_pad_len'] = pad

                packet['sec_trailer'] = sec_trailer
                packet['auth_data'] = auth

            _, err = await self.transport.send(packet.get_packet())
            if err is not None:
                raise err

            data, err = await self.recv_one()
            if err is not None:
                raise err

            resp = MSRPCHeader(data)

            if resp['type'] == MSRPC_BINDACK or resp[
                    'type'] == MSRPC_ALTERCTX_R:
                bindResp = MSRPCBindAck(resp.getData())
            elif resp['type'] == MSRPC_BINDNAK or resp['type'] == MSRPC_FAULT:
                if resp['type'] == MSRPC_FAULT:
                    resp = MSRPCRespHeader(resp.getData())
                    status_code = unpack('<L', resp['pduData'][:4])[0]
                else:
                    resp = MSRPCBindNak(resp['pduData'])
                    status_code = resp['RejectedReason']
                if status_code in rpc_status_codes:
                    return False, DCERPCException(error_code=status_code)
                elif status_code in rpc_provider_reason:
                    return False, DCERPCException(
                        "Bind context rejected: %s" %
                        rpc_provider_reason[status_code])
                else:
                    return False, DCERPCException(
                        'Unknown DCE RPC fault status code: %.8x' %
                        status_code)
            else:
                return False, DCERPCException(
                    'Unknown DCE RPC packet type received: %d' % resp['type'])

            # check ack results for each context, except for the bogus ones
            for ctx in range(bogus_binds + 1, bindResp['ctx_num'] + 1):
                ctxItems = bindResp.getCtxItem(ctx)
                if ctxItems['Result'] != 0:
                    msg = "Bind context %d rejected: " % ctx
                    msg += rpc_cont_def_result.get(
                        ctxItems['Result'],
                        'Unknown DCE RPC context result code: %.4x' %
                        ctxItems['Result'])
                    msg += "; "
                    reason = bindResp.getCtxItem(ctx)['Reason']
                    msg += rpc_provider_reason.get(
                        reason, 'Unknown reason code: %.4x' % reason)
                    if (ctxItems['Result'], reason) == (
                            2, 1
                    ):  # provider_rejection, abstract syntax not supported
                        msg += " (this usually means the interface isn't listening on the given endpoint)"
                    raise DCERPCException(msg)

                # Save the transfer syntax for later use
                self.transfer_syntax = ctxItems['TransferSyntax']

            # The received transmit size becomes the client's receive size, and the received receive size becomes the client's transmit size.
            self.__max_xmit_size = bindResp['max_rfrag']

            if self.auth_level != RPC_C_AUTHN_LEVEL_NONE:
                if self.auth_type == RPC_C_AUTHN_WINNT:
                    response, res, err = await self.gssapi.ntlm.authenticate(
                        bindResp['auth_data'], is_rpc=True)
                    if err is not None:
                        return None, err

                    self.__sessionKey = self.gssapi.ntlm.get_session_key()

                elif self.auth_type == RPC_C_AUTHN_NETLOGON:
                    response = None
                elif self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE:
                    response, res, err  = await self.gssapi.gssapi.authenticate(
                     bindResp['auth_data'],
                     is_rpc = True,
                     flags = GSSAPIFlags.GSS_C_CONF_FLAG |\
                      GSSAPIFlags.GSS_C_INTEG_FLAG | \
                      GSSAPIFlags.GSS_C_SEQUENCE_FLAG | \
                      GSSAPIFlags.GSS_C_REPLAY_FLAG | \
                      GSSAPIFlags.GSS_C_MUTUAL_FLAG | \
                      GSSAPIFlags.GSS_C_DCE_STYLE
                    )
                    if err is not None:
                        return None, err

                    self.__sessionKey = self.gssapi.gssapi.get_session_key()

                self.__sequence = 0

                if self.auth_level in (RPC_C_AUTHN_LEVEL_CONNECT,
                                       RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,
                                       RPC_C_AUTHN_LEVEL_PKT_PRIVACY):
                    if self.auth_type == RPC_C_AUTHN_WINNT:
                        if self.gssapi.ntlm.is_extended_security() == True:
                            self.__clientSigningKey = self.gssapi.ntlm.get_signkey(
                            )
                            self.__serverSigningKey = self.gssapi.ntlm.get_signkey(
                                'Server')
                            self.__clientSealingKey = self.gssapi.ntlm.get_sealkey(
                            )
                            self.__serverSealingKey = self.gssapi.ntlm.get_sealkey(
                                'Server')
                            cipher3 = RC4(self.__clientSealingKey)
                            self.__clientSealingHandle = cipher3.encrypt
                            cipher4 = RC4(self.__serverSealingKey)
                            self.__serverSealingHandle = cipher4.encrypt

                        else:
                            # Same key for everything
                            self.__clientSigningKey = self.gssapi.ntlm.get_session_key(
                            )
                            self.__serverSigningKey = self.gssapi.ntlm.get_session_key(
                            )
                            self.__clientSealingKey = self.gssapi.ntlm.get_session_key(
                            )
                            self.__serverSealingKey = self.gssapi.ntlm.get_session_key(
                            )
                            cipher = RC4(self.__clientSigningKey)
                            self.__clientSealingHandle = cipher.encrypt
                            self.__serverSealingHandle = cipher.encrypt

                    elif self.auth_type == RPC_C_AUTHN_NETLOGON:
                        raise Exception(
                            'RPC_C_AUTHN_NETLOGON is not implemented!')

                sec_trailer = SEC_TRAILER()
                sec_trailer['auth_type'] = self.auth_type
                sec_trailer['auth_level'] = self.auth_level
                sec_trailer['auth_ctx_id'] = self.ctx + 79231

                if response is not None:
                    if self.auth_type == RPC_C_AUTHN_GSS_NEGOTIATE:
                        alter_ctx = MSRPCHeader()
                        alter_ctx['type'] = MSRPC_ALTERCTX
                        alter_ctx['pduData'] = bind.getData()
                        alter_ctx['sec_trailer'] = sec_trailer
                        alter_ctx['auth_data'] = response

                        _, err = await self.transport.send(
                            alter_ctx.get_packet(), forceWriteAndx=1)
                        if err is not None:
                            raise err

                        self.__sequence = 0
                        data, err = await self.recv_one(
                        )  #recieving the result of alter_context command
                        if err is not None:
                            raise err

                        self.__sequence = self.gssapi.gssapi.selected_authentication_context.seq_number
                    else:
                        auth3 = MSRPCHeader()
                        auth3['type'] = MSRPC_AUTH3
                        # pad (4 bytes): Can be set to any arbitrary value when set and MUST be
                        # ignored on receipt. The pad field MUST be immediately followed by a
                        # sec_trailer structure whose layout, location, and alignment are as
                        # specified in section 2.2.2.11
                        auth3[
                            'pduData'] = b' ' * 4  #SkelSec: I have spent 3 hours to find this bug, that I caused by replacing spaces to tabs :(
                        auth3['sec_trailer'] = sec_trailer
                        #SkelSec auth3['auth_data'] = response.getData()
                        auth3['auth_data'] = response

                        # Use the same call_id
                        self.callid = resp['call_id']
                        auth3['call_id'] = self.callid
                        _, err = await self.transport.send(auth3.get_packet(),
                                                           forceWriteAndx=1)
                        if err is not None:
                            raise err

                self.callid += 1
            return resp, None  # means packet is signed, if verifier is wrong it fails

        except Exception as e:
            return False, e