Beispiel #1
0
	def get_HBoot_key(self):
		logger.debug('SAM parsing hashed bootkey')
		QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
		DIGITS = b"0123456789012345678901234567890123456789\0"
		
		F = self.hive.get_value(r'SAM\Domains\Account\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 = AESModeOfOperationCBC(self.bootkey, 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 #2
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 = AESModeOfOperationCBC(self.hashed_bootkey[:0x10],
                                           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 #3
0
	def decrypt(self, encrypted):
		# TODO: NT version specific, move from here in subclasses.
		cleartext = b''
		size = len(encrypted)
		if size:
			if size % 8:
				if not self.aes_key or not self.iv:
					return cleartext
				cipher = AESModeOfOperationCBC(self.aes_key, iv = self.iv)
				n = 16
				for block in [encrypted[i:i+n] for i in range(0, len(encrypted), n)]:  #terrible, terrible workaround
					cleartext += cipher.decrypt(block)
			else:
				if not self.des_key or not self.iv:
					return cleartext
				#cipher = DES3.new(self.des_key, DES3.MODE_CBC, self.iv[:8])
				cipher = triple_des(self.des_key, CBC, self.iv[:8])
				cleartext = cipher.decrypt(encrypted)
		return cleartext
Beispiel #4
0
 def decrypt(self, encrypted):
     # TODO: NT version specific, move from here in subclasses.
     cleartext = ''
     size = len(encrypted)
     if size:
         if size % 8:
             if not self.aes_key or not self.iv:
                 return cleartext
             cipher = AESModeOfOperationCBC(self.aes_key, iv=self.IV)
         else:
             if not self.des_key or not self.iv:
                 return cleartext
             #cipher = DES3.new(self.des_key, DES3.MODE_CBC, self.iv[:8])
             cipher = triple_des(self.des_key, CBC, self.iv[:8])
         cleartext = cipher.decrypt(encrypted)
     return cleartext
Beispiel #5
0
class AES:
    def __init__(self, key, mode=SYMMETRIC_MODE.ECB, iv=None):
        self.key = key
        self.mode = mode
        self.iv = iv
        self.block_size = 16
        self.ctx = None
        self.setup()

    def setup(self):
        if self.mode == SYMMETRIC_MODE.ECB:
            self.ctx = AESModeOfOperationECB(self.key)
        elif self.mode == SYMMETRIC_MODE.CBC:
            self.ctx = AESModeOfOperationCBC(self.key, iv=self.iv)
        else:
            raise Exception('Unknown mode!')

    def encrypt(self, data):
        if len(data) % self.block_size != 0:
            raise Exception('Data size not matching blocksize!')
        res = b''
        for block in [
                data[i:i + self.block_size]
                for i in range(0, len(data), self.block_size)
        ]:  #terrible, terrible workaround
            res += self.ctx.encrypt(block)
        return res

    def decrypt(self, data):
        if len(data) % self.block_size != 0:
            raise Exception('Data size not matching blocksize!')
        res = b''
        for block in [
                data[i:i + self.block_size]
                for i in range(0, len(data), self.block_size)
        ]:  #terrible, terrible workaround
            res += self.ctx.decrypt(block)
        return res
Beispiel #6
0
    async def dump_dcc(self):
        logger.debug('[SECURITY] dump_dcc invoked')
        cache_reg = await self.hive.find_key('Cache', False)
        if cache_reg is None:
            logger.debug('[SECURITY] No DCC secrets found')
            return
        values = await 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 = await self.hive.get_value('Cache\\NL$IterationCount')
            record = record[1]
            if record > 10240:
                self.dcc_iteration_count = record & 0xfffffc00
            else:
                self.dcc_iteration_count = record * 1024

        await self.get_lsa_key()
        await self.get_NKLM_key()

        for value in values:
            logger.debug('[SECURITY] DCC Checking value: %s' % value)
            record_data = await self.hive.get_value('Cache\\%s' %
                                                    value.decode())
            record_data = record_data[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 = AESModeOfOperationCBC(self.NKLM_key[16:32],
                                                       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).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
Beispiel #7
0
    def dump_dcc(self):
        cache_reg = self.hive.find_key('Cache')
        values = self.hive.list_values(cache_reg)
        if values == []:
            return

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

        if b'NL$IterationCount' in values:
            values.remove(b'NL$IterationCount')
            record = self.getValue('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()

        print(self.lsa_key)
        print(self.NKLM_key)

        for value in values:
            print('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 = AESModeOfOperationCBC(self.NKLM_key[16:32],
                                                       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).digest()
                        cipher = RC4(key)
                        plaintext = cipher.decrypt(record.EncryptedData)

                else:
                    # Plain! Until we figure out what this is, we skip it
                    #plainText = record['EncryptedData']
                    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')

                if self.lsa_secret_key_vista_type is True:
                    ans = "%s/%s:$DCC2$%s#%s#%s" % (domain, username,
                                                    self.dcc_iteration_count,
                                                    username, dcc_hash.hex())
                else:
                    ans = "%s/%s:%s:%s" % (domain, username, dcc_hash.hex(),
                                           username)

                print(ans)