Beispiel #1
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
Beispiel #2
0
	def construct(server_challenge, client_challenge, credentials):
		ntlm_creds = netntlm_ess()
		ntlm_creds.credentials = credentials
		ntlm_creds.ServerChallenge = server_challenge
		
		if credentials.password:
			nt_hash = NTOWFv1(credentials.password)
			lm_hash = LMOWFv1(credentials.password)
		else:
			nt_hash = bytes.fromhex(credentials.nt_hash)
			lm_hash = bytes.fromhex(credentials.lm_hash) if credentials.lm_hash else None
		
		
		ntlm_creds.LMResponse = LMResponse()
		ntlm_creds.LMResponse.Response = client_challenge + b'\x00' * 16
		
		temp_1 = md5(server_challenge + client_challenge[:8]).digest()
		data = DESL(nt_hash, temp_1[:8])
		
		ntlm_creds.NTResponse = NTLMv1Response()
		ntlm_creds.NTResponse.Response = data
		
		ntlm_creds.SessionBaseKey = md4(nt_hash).digest()
		
		return ntlm_creds
Beispiel #3
0
	def verify(self, creds, credtype='plain'):
		"""
		Verifies the authentication data against the user credentials
		:param creds: dictionary containing the domain, user, hash/password
		:param credtype: can be 'plain' or 'hash' this indicates what type of credential lookup to perform
		:return: bool
		"""
		if creds is None:
			return True
		if self.domain not in creds:
			return False
		if self.username not in creds[self.domain]:
			return False

		if credtype == 'plain':
			nt_hash = NTOWFv1(creds[self.domain][self.username])
		elif credtype == 'hash':
			nt_hash = bytes.fromhex(creds[self.domain][self.username])
		else:
			raise Exception('Unknown cred type!')

		# print('Server chall: %s' % self.ServerChallenge)
		# print('Client chall: %s' % self.ChallengeFromClinet)

		temp_1 = md5(bytes.fromhex(self.ServerChallenge) + bytes.fromhex(self.ChallengeFromClinet)[:8]).digest()
		calc_response = DESL(nt_hash, temp_1[:8])
		# print('calc_response: %s' % calc_response.hex())
		# print('ClientResponse: %s' %  self.ClientResponse)

		return calc_response == bytes.fromhex(self.ClientResponse)
Beispiel #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
Beispiel #5
0
	def construct_apreq(self, tgs, encTGSRepPart, sessionkey, flags = None, seq_number = 0, ap_opts = [], cb_data = None):
		now = datetime.datetime.now(datetime.timezone.utc)
		authenticator_data = {}
		authenticator_data['authenticator-vno'] = krb5_pvno
		authenticator_data['crealm'] = Realm(self.kerberos_TGT['crealm'])
		authenticator_data['cname'] = self.kerberos_TGT['cname']
		authenticator_data['cusec'] = now.microsecond
		authenticator_data['ctime'] = now.replace(microsecond=0)
		if flags is not None:
			ac = AuthenticatorChecksum()
			ac.flags = flags

			ac.channel_binding = b'\x00'*16
			if cb_data is not None:
				ac.channel_binding = hashlib.md5(cb_data).digest()
			
			chksum = {}
			chksum['cksumtype'] = 0x8003
			chksum['checksum'] = ac.to_bytes()
			
			authenticator_data['cksum'] = Checksum(chksum)
			authenticator_data['seq-number'] = seq_number
		
		cipher = _enctype_table[encTGSRepPart['key']['keytype']]
		authenticator_data_enc = cipher.encrypt(sessionkey, 11, Authenticator(authenticator_data).dump(), None)
		
		ap_req = {}
		ap_req['pvno'] = krb5_pvno
		ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
		ap_req['ticket'] = Ticket(tgs['ticket'])
		ap_req['ap-options'] = APOptions(set(ap_opts))
		ap_req['authenticator'] = EncryptedData({'etype': self.kerberos_cipher_type, 'cipher': authenticator_data_enc})

		return AP_REQ(ap_req).dump()
Beispiel #6
0
    def construct_apreq_from_ticket(ticket_data,
                                    sessionkey,
                                    crealm,
                                    cname,
                                    flags=None,
                                    seq_number=0,
                                    ap_opts=[],
                                    cb_data=None):
        """
		ticket: bytes of Ticket
		"""
        now = datetime.datetime.now(datetime.timezone.utc)
        authenticator_data = {}
        authenticator_data['authenticator-vno'] = krb5_pvno
        authenticator_data['crealm'] = Realm(crealm)
        authenticator_data['cname'] = PrincipalName({
            'name-type':
            NAME_TYPE.PRINCIPAL.value,
            'name-string': [cname]
        })
        authenticator_data['cusec'] = now.microsecond
        authenticator_data['ctime'] = now.replace(microsecond=0)
        if flags is not None:

            ac = AuthenticatorChecksum()
            ac.flags = flags
            ac.channel_binding = b'\x00' * 16
            if cb_data is not None:
                ac.channel_binding = hashlib.md5(cb_data).digest()

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

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

        cipher = _enctype_table[sessionkey.enctype]
        authenticator_data_enc = cipher.encrypt(
            sessionkey, 11,
            Authenticator(authenticator_data).dump(), None)

        ap_req = {}
        ap_req['pvno'] = krb5_pvno
        ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
        ap_req['ticket'] = Ticket.load(ticket_data)
        ap_req['ap-options'] = APOptions(set(ap_opts))
        ap_req['authenticator'] = EncryptedData({
            'etype':
            sessionkey.enctype,
            'cipher':
            authenticator_data_enc
        })

        return AP_REQ(ap_req).dump()
Beispiel #7
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
Beispiel #8
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()
Beispiel #9
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
Beispiel #10
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