Ejemplo n.º 1
0
 def test_decryptCredential(self):
     credFile = CredentialFile(self.credentialFile)
     credFile.dump()
     blob = DPAPI_BLOB(credFile['Data'])
     decrypted = blob.decrypt(self.adminMasterKey)
     creds = CREDENTIAL_BLOB(decrypted)
     creds.dump()
     self.assertEqual(creds['Username'], self.username.encode('utf-16le'))
Ejemplo n.º 2
0
 def test_decryptCredential(self):
     credFile = CredentialFile(self.credentialFile)
     credFile.dump()
     blob = DPAPI_BLOB(credFile['Data'])
     decrypted = blob.decrypt(self.adminMasterKey)
     creds = CREDENTIAL_BLOB(decrypted)
     creds.dump()
     self.assertEqual(creds['Username'], 'david.bowie\x00'.encode('utf-16le'))
Ejemplo n.º 3
0
 def test_unprotect_with_entropy(self):
     """Simple test to decrypt a protected blob providing an entropy string.
     The blob was obtained using the dpapi_protect helper function and key extracted from a
     test system with secretsdump/mimikatz.
     """
     plain_blob = b"Some test string"
     entropy = b"Some entropy"
     key = unhexlify("9828d9873735439e823dbd216205ff88266d28ad685a413970c640d5ee943154bbade31fada673d542c72d707a163bb3d1bceb0c50465b359ae06998481b0ce3")
     encrypted_blob = unhexlify("01000000d08c9ddf0115d1118c7a00c04fc297eb0100000033f19f5ee340be4a8a2e2b4e62bd0cc600000000020000000000106600000001000020000000f239c0018e71b33bef9a6299675c7e209eef1f6447bd578d19c7973548737545000000000e80000000020000200000009d9ef33e15ffb1b310a13ecec39b1c02adc39e8d40a7162f9f9bb3170c699a812000000040e820259332c47af42e5f9de629e109d1504641aad853f3818c40ac311cf24a4000000010f01a84a5cc0393d3ea44cc3a8ff00ca4d02fcabc7c353a6823c53e4e719c9b398282a06b8878250205160ed79fef8b026093ad5a467594953d6de28d71f8c9")
     dpapi_blob = DPAPI_BLOB(encrypted_blob)
     decrypted_blob = dpapi_blob.decrypt(key, entropy)
     self.assertEqual(plain_blob, decrypted_blob)
Ejemplo n.º 4
0
 def test_unprotect_without_entropy(self):
     """Simple test to decrypt a protected blob without providing an entropy string.
     The blob was obtained using the dpapi_protect helper function and key extracted from a
     test system with secretsdump/mimikatz.
     """
     plain_blob = b"Some test string"
     entropy = None
     key = unhexlify("9828d9873735439e823dbd216205ff88266d28ad685a413970c640d5ee943154bbade31fada673d542c72d707a163bb3d1bceb0c50465b359ae06998481b0ce3")
     encrypted_blob = unhexlify("01000000d08c9ddf0115d1118c7a00c04fc297eb0100000033f19f5ee340be4a8a2e2b4e62bd0cc6000000000200000000001066000000010000200000000d1af96e5e102266fd36d96ac7d1595552e5a4e972463f77e6e227f22d5fc8df000000000e8000000002000020000000834f3c5710c8a7474f7dbcea8ba28ab8e4d4443f50a0c63ff4eba1cce485295f20000000b61d7576c0c6caf3690edb247bde3f7edaa59580e3b4be1265ea78e8c1b8a61d400000001c03ab807147742649b6bdfd1c1344d178bb163842d70abacfd51233af909cb81a677ec05d8db996f587ef5ac410dc189beda756eb0d1b6ee376823e80968538")
     dpapi_blob = DPAPI_BLOB(encrypted_blob)
     decrypted_blob = dpapi_blob.decrypt(key, entropy)
     self.assertEqual(plain_blob, decrypted_blob)
Ejemplo n.º 5
0
    def test_dumpBlobProtectAPI(self):
        """Protect a blob using DPAPI and then parse and dump it. We're not testing the
        correct decryption at this point.

        TODO: It would be great to have a complete functional test to protect using DPAPI and
              then unprotect it but it will require also dumping the master key from the test
              system.
        """
        plain_blob = b"Some test string"
        entropy = b"Some entropy"
        encrypted_blob = dpapi_protect(plain_blob, entropy)
        dpapi_blob = DPAPI_BLOB(encrypted_blob)
        dpapi_blob.dump()
Ejemplo n.º 6
0
    def run(self, profile):
        pwd_found = []

        creds_directory = os.path.join(profile['LOCALAPPDATA'], 'Microsoft',
                                       'Credentials')
        creds_directory2 = os.path.join(profile['APPDATA'], 'Microsoft',
                                        'Credentials')
        if not profile.get('mkfiles'):
            return
        for folder in [creds_directory, creds_directory2]:
            if not os.path.isdir(creds_directory):
                continue
            for cred_file in os.listdir(folder):
                try:
                    data = open(os.path.join(folder, cred_file), 'rb').read()
                    cred = CredentialFile(data)
                    blob = DPAPI_BLOB(cred['Data'])

                    masterkey = profile['mkfiles'].get(
                        bin_to_string(blob['GuidMasterKey']).lower())

                    if masterkey:
                        decrypted = blob.decrypt(masterkey)
                        if decrypted is not None:
                            blob = CREDENTIAL_BLOB(decrypted)
                            pwd = blob['Unknown3']
                            try:
                                pwd = pwd.decode('utf-16-le').rstrip('\0')
                            except:
                                pass
                            pwd_found.append({
                                'Target':
                                blob['Target'].decode('utf-16-le').rstrip(
                                    '\0'),
                                'Username':
                                blob['Username'].decode('utf-16-le').rstrip(
                                    '\0'),
                                'Password':
                                pwd,
                                'LastWritten':
                                datetime.utcfromtimestamp(
                                    getUnixTime(blob['LastWritten']))
                            })
                except Exception:
                    log.error(traceback.format_exc())

            return pwd_found
Ejemplo n.º 7
0
def CryptUnprotectData(cipherText, profile, entropy=None):
    decrypted = None

    blob = DPAPI_BLOB(cipherText)
    masterkey = profile['mkfiles'].get(
        bin_to_string(blob['GuidMasterKey']).lower())
    if masterkey:
        decrypted = blob.decrypt(masterkey)

    if decrypted is None and profile.get('is_current_user'):
        try:
            decrypted = win32crypt.CryptUnprotectData(cipherText, None,
                                                      entropy, None, 0)[1]
        except:
            pass

    return decrypted
Ejemplo n.º 8
0
    def decrypt_using_lsa_secret(self, key_material, profile):
        """
        Needs admin priv but will work with all systems
        """
        if profile.get('sys32'):
            blob = DPAPI_BLOB(bytes.fromhex(key_material))
            masterkey = profile['sys32'].get('user', {}).get(bin_to_string(blob['GuidMasterKey']).lower())
            if not masterkey:
                masterkey = profile['sys32'].get('machine', {}).get(bin_to_string(blob['GuidMasterKey']).lower())

            if masterkey:
                decrypted = blob.decrypt(masterkey)
                if decrypted:
                    decrypted = decrypted.rstrip(b'\0')
                    try:
                        return decrypted.decode(sys.getfilesystemencoding())
                    except UnicodeDecodeError:
                        return str(decrypted)
Ejemplo n.º 9
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf = MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security and self.options.sid is None:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.system and self.options.security:
                # Use SID + hash
                # We have hives, let's try to decrypt with them
                self.getLSA()
                key1, key2 = self.deriveKeysFromUserkey(
                    self.options.sid, self.dpapiSystem['UserKey'])
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key and self.options.sid:
                key = unhexlify(self.options.key[2:])
                key1, key2 = self.deriveKeysFromUserkey(self.options.sid, key)
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(
                        decryptedKey)
                    key = domain_master_key[
                        'buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug(
                            "Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey).decode('latin-1'))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][
                        backup_key['KeyLength']:backup_key['KeyLength'] +
                        backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug(
                            "Exporting certificate to file {}".format(name +
                                                                      ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug(
                            "Exporting private key to file {}".format(name +
                                                                      ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" %
                              (hexlify(backupkey).decode('latin-1')))
                        print("\n")
            return

        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print(
                    'You must specify either -vcrd or -vpol parameter. Type --help for more info'
                )
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(
                                    attribute['IV']) == 16:
                                cipher = AES.new(key,
                                                 AES.MODE_CBC,
                                                 iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode(
                                'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[
                                blob['FriendlyName'].decode('utf-16le')[:-1]](
                                    cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return
        elif self.options.action.upper() == 'UNPROTECT':
            fp = open(options.file, 'rb')
            data = fp.read()
            blob = DPAPI_BLOB(data)

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                if self.options.entropy_file is not None:
                    fp2 = open(self.options.entropy_file, 'rb')
                    entropy = fp2.read()
                    fp2.close()
                elif self.options.entropy is not None:
                    entropy = b(self.options.entropy)
                else:
                    entropy = None

                decrypted = blob.decrypt(key, entropy)
                if decrypted is not None:
                    print('Successfully decrypted data')
                    hexdump(decrypted)
                    return
            else:
                # Just print the data
                blob.dump()

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Ejemplo n.º 10
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf= MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey)
                    key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug("Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey).decode('latin-1'))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug("Exporting certificate to file {}".format(name + ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug("Exporting private key to file {}".format(name + ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey).decode('latin-1')))
                        print("\n")
            return


        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print('You must specify either -vcrd or -vpol parameter. Type --help for more info')
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(attribute['IV']) == 16:
                                cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Ejemplo n.º 11
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf= MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey)
                    key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug("Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug("Exporting certificate to file {}".format(name + ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug("Exporting private key to file {}".format(name + ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey)))
                        print("\n")
            return


        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print('You must specify either -vcrd or -vpol parameter. Type --help for more info')
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(attribute['IV']) == 16:
                                cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Ejemplo n.º 12
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf = MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:")
                else:
                    password = options.password
                key1, key2, key3 = self.deriveKeysFromUser(
                    self.options.sid, password)

                # if mkf['flags'] & 4 ? SHA1 : MD4
                decryptedKey = mk.decrypt(key3)
                if decryptedKey:
                    print('Decrypted key with User Key (MD4 protected)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with User Key (MD4)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with User Key (SHA1)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

                decryptedKey = bkmk.decrypt(key3)
                if decryptedKey:
                    print('Decrypted Backup key with User Key (MD4 protected)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

                decryptedKey = bkmk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted Backup key with User Key (MD4)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

                decryptedKey = bkmk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted Backup key with User Key (SHA1)')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

            else:
                # Just print key's data
                if mkf['MasterKeyLen'] > 0:
                    mk.dump()

                if mkf['BackupKeyLen'] > 0:
                    bkmk.dump()

                if mkf['CredHistLen'] > 0:
                    ch.dump()

                if mkf['DomainKeyLen'] > 0:
                    dk.dump()

        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print(
                    'You must specify either -vcrd or -vpol parameter. Type --help for more info'
                )
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(
                                    attribute['IV']) == 16:
                                cipher = AES.new(key,
                                                 AES.MODE_CBC,
                                                 iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode(
                                'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[
                                blob['FriendlyName'].decode('utf-16le')[:-1]](
                                    cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')