Beispiel #1
0
    async def get_NKLM_key(self):
        logger.debug('[SECURITY] Fetching NK$LM key...')
        if self.lsa_key is None:
            await self.get_lsa_key()

        value = await self.hive.get_value(
            'Policy\\Secrets\\NL$KM\\CurrVal\\default')
        if value is None:
            logger.error('[SECURITY] Could not find NL$KM in registry')
            raise Exception('Could not find NL$KM in registry :(')

        if self.lsa_secret_key_vista_type is True:
            self.NKLM_key = b''
            record = LSA_SECRET.from_bytes(value[1])
            key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
            cipher = AESModeOfOperationECB(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' * (16 - len(block))
                self.NKLM_key += cipher.decrypt(block)

        else:
            self.NKLM_key = self.decrypt_secret(self.lsa_key, value[1])

        logger.debug('[SECURITY] NL$KM key: %s' % self.NKLM_key.hex())
        return self.NKLM_key
Beispiel #2
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 = AESModeOfOperationECB(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 #3
0
    def decrypt_lsa_key(self, data):
        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 = AESModeOfOperationECB(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
                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(value[60:76])

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

        return self.lsa_key
Beispiel #4
0
    def get_secrets(self):
        logger.debug('[SECURITY] get_secrets')
        self.get_lsa_key()

        self.dump_dcc()

        # Let's first see if there are cached entries
        keys = self.hive.enum_key('Policy\\Secrets')
        if keys is None:
            logger.debug('[SECURITY] No cached secrets found in hive')
            return

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

        for key_name in keys:
            for vl in ['CurrVal', 'OldVal']:
                key_path = 'Policy\\Secrets\\{}\\{}\\default'.format(
                    key_name, vl)
                logger.debug('[SECURITY] Parsing secrets in %s' % key_path)
                v = self.hive.get_value(key_path, False)
                if v and v[1] != 0:
                    logger.log(1,
                               '[SECURITY] Key %s Value %s' % (key_path, v[1]))
                    if self.lsa_secret_key_vista_type is True:
                        record = LSA_SECRET.from_bytes(v[1])
                        key = SECURITY.sha256_multi(self.lsa_key,
                                                    record.data[:32])
                        secret_dec = b''
                        cipher = AESModeOfOperationECB(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)
                        dec_blob = record.secret

                    else:
                        dec_blob = self.decrypt_secret(self.lsa_key, v[1])

                    secret = LSASecret.process(key_name, dec_blob,
                                               vl == 'OldVal',
                                               self.system_hive)
                    if secret is not None:
                        self.cached_secrets.append(secret)

                else:
                    logger.debug('[SECURITY] Could not open %s, skipping!' %
                                 key_path)
Beispiel #5
0
 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!')
Beispiel #6
0
    def change_key(self, master_key):
        #if len(master_key) != 16:
        #	raise InvalidInputException('Master key should be 128-bit')

        self.__master_key = master_key
        self.__aes_ecb = AESModeOfOperationECB(self.__master_key)
        self.__auth_key = int.from_bytes(self.__aes_ecb.encrypt(b'\x00' * 16),
                                         byteorder='big',
                                         signed=False)

        # precompute the table for multiplication in finite field
        table = []  # for 8-bit
        for i in range(16):
            row = []
            for j in range(256):
                row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
            table.append(tuple(row))
        self.__pre_table = tuple(table)

        self.prev_init_value = None  # reset
Beispiel #7
0
    def dump_secrets(self):
        self.get_lsa_key()
        self.get_NKLM_key()

        # Let's first see if there are cached entries
        keys = self.hive.enum_key('Policy\\Secrets')
        if keys is None:
            # No entries
            return

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

        for key_name in keys:
            for vl in ['CurrVal', 'OldVal']:
                key_path = 'Policy\\Secrets\\{}\\{}\\default'.format(
                    key_name, vl)
                print(key_path)
                v = self.hive.get_value(key_path)
                if v and v[1] != 0:
                    if self.lsa_secret_key_vista_type is True:
                        record = LSA_SECRET.from_bytes(v[1])
                        key = SECURITY.sha256_multi(self.lsa_key,
                                                    record.data[:32])
                        secret_dec = b''
                        cipher = AESModeOfOperationECB(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
                            secret_dec += cipher.decrypt(block)
                        record = LSA_SECRET_BLOB.from_bytes(secret_dec)
                        dec_blob = record.secret

                    else:
                        dec_blob = self.decrypt_secret(self.lsa_key, v[1])

                secret = LSASecret.process(key_name, dec_blob, vl == 'OldVal')
                print(str(secret))
Beispiel #8
0
    def get_NKLM_key(self):
        if self.lsa_key is None:
            self.get_lsa_secret_key()

        value = self.hive.get_value('Policy\\Secrets\\NL$KM\\CurrVal\\default')
        if value is None:
            raise Exception('Could not find NL$KM in registry :(')

        if self.lsa_secret_key_vista_type is True:
            self.NKLM_key = b''
            record = LSA_SECRET.from_bytes(value[1])
            key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
            cipher = AESModeOfOperationECB(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
                self.NKLM_key += cipher.decrypt(block)

        else:
            self.NKLM_key = self.decrypt_secret(self.lsa_key, value[1])

        return self.NKLM_key
Beispiel #9
0
class AES_GCM:
    def __init__(self, master_key):
        self.change_key(master_key)

    def change_key(self, master_key):
        #if len(master_key) != 16:
        #	raise InvalidInputException('Master key should be 128-bit')

        self.__master_key = master_key
        self.__aes_ecb = AESModeOfOperationECB(self.__master_key)
        self.__auth_key = int.from_bytes(self.__aes_ecb.encrypt(b'\x00' * 16),
                                         byteorder='big',
                                         signed=False)

        # precompute the table for multiplication in finite field
        table = []  # for 8-bit
        for i in range(16):
            row = []
            for j in range(256):
                row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
            table.append(tuple(row))
        self.__pre_table = tuple(table)

        self.prev_init_value = None  # reset

    def __times_auth_key(self, val):
        res = 0
        for i in range(16):
            res ^= self.__pre_table[i][val & 0xFF]
            val >>= 8
        return res

    def __ghash(self, aad, txt):
        len_aad = len(aad)
        len_txt = len(txt)

        # padding
        if 0 == len_aad % 16:
            data = aad
        else:
            data = aad + b'\x00' * (16 - len_aad % 16)
        if 0 == len_txt % 16:
            data += txt
        else:
            data += txt + b'\x00' * (16 - len_txt % 16)

        tag = 0
        assert len(data) % 16 == 0
        for i in range(len(data) // 16):
            tag ^= int.from_bytes(data[i * 16:(i + 1) * 16],
                                  byteorder='big',
                                  signed=False)
            tag = self.__times_auth_key(tag)
            # print 'X\t', hex(tag)
        tag ^= ((8 * len_aad) << 64) | (8 * len_txt)
        tag = self.__times_auth_key(tag)

        return tag

    def encrypt(self, init_value, plaintext, auth_data=b''):
        if len(init_value) != 12:
            raise InvalidInputException('IV should be 96-bit')
        # a naive checking for IV reuse
        if init_value == self.prev_init_value:
            raise InvalidInputException('IV must not be reused!')
        self.prev_init_value = init_value

        len_plaintext = len(plaintext)

        if len_plaintext > 0:
            ctrval_init = init_value + b'\x00' * 4
            ctrval = int.from_bytes(ctrval_init, byteorder='big', signed=False)
            counter = Counter(initial_value=ctrval + 2)  #+2 ????
            aes_ctr = AESModeOfOperationCTR(self.__master_key, counter=counter)

            if 0 != len_plaintext % 16:
                padded_plaintext = plaintext + \
                 b'\x00' * (16 - len_plaintext % 16)
            else:
                padded_plaintext = plaintext
            ciphertext = aes_ctr.encrypt(padded_plaintext)[:len_plaintext]

        else:
            ciphertext = b''

        auth_tag = self.__ghash(auth_data, ciphertext)
        iv_int = int.from_bytes(init_value, byteorder='big', signed=False)
        iv_int = (iv_int << 32) | 1
        iv_int = iv_int.to_bytes(16, byteorder='big', signed=False)
        iv_int_enc = self.__aes_ecb.encrypt(iv_int)
        iv_int_enc = int.from_bytes(iv_int_enc, byteorder='big', signed=False)

        auth_tag ^= iv_int_enc

        assert auth_tag < (1 << 128)
        return ciphertext, auth_tag.to_bytes(16, byteorder='big', signed=False)

    def decrypt(self, init_value, ciphertext, auth_tag, auth_data=b''):
        if len(init_value) != 12:
            raise InvalidInputException('IV should be 96-bit')
        if len(auth_tag) != 16:
            raise InvalidInputException('Tag should be 128-bit')

        iv_int = int.from_bytes(init_value, byteorder='big', signed=False)
        iv_int = (iv_int << 32) | 1
        iv_int = iv_int.to_bytes(16, byteorder='big', signed=False)
        iv_int_enc = self.__aes_ecb.encrypt(iv_int)
        iv_int_enc = int.from_bytes(iv_int_enc, byteorder='big', signed=False)
        auth_tag_verify = self.__ghash(auth_data, ciphertext) ^ iv_int_enc
        auth_tag_verify = auth_tag_verify.to_bytes(16,
                                                   byteorder='big',
                                                   signed=False)
        if auth_tag != auth_tag_verify:
            raise InvalidTagException

        len_ciphertext = len(ciphertext)
        if len_ciphertext > 0:
            ctrval_init = init_value + b'\x00' * 4
            ctrval = int.from_bytes(ctrval_init, byteorder='big', signed=False)
            counter = Counter(initial_value=ctrval + 2)  #+2 ????
            aes_ctr = AESModeOfOperationCTR(self.__master_key, counter=counter)

            if 0 != len_ciphertext % 16:
                padded_ciphertext = ciphertext + \
                 b'\x00' * (16 - len_ciphertext % 16)
            else:
                padded_ciphertext = ciphertext
            plaintext = aes_ctr.decrypt(padded_ciphertext)[:len_ciphertext]

        else:
            plaintext = b''

        return plaintext