Search
StarWind is a hyperconverged (HCI) vendor with focus on Enterprise ROBO, SMB & Edge

How to Unlock BitLocker-Encrypted Azure VM Disks in a Recovery VM

  • May 7, 2025
  • 28 min read
Cloud and Virtualization Architect. Didier is an IT veteran with over 20 years of expertise in Microsoft technologies, storage, virtualization, and networking. Didier primarily works as an expert advisor and infrastructure architect.
Cloud and Virtualization Architect. Didier is an IT veteran with over 20 years of expertise in Microsoft technologies, storage, virtualization, and networking. Didier primarily works as an expert advisor and infrastructure architect.

If your Azure VM is down and the OS disk is encrypted with BitLocker, this guide is for you. Learn how to mount the disk to a recovery #VM and unlock it securely using PowerShell and Azure Key Vault.

Introduction

I will provide an overview of a script I recently wrote to easily grab both nonencrypted and encrypted (wrapped with a Key Encryption Key or KEK for short) BitLocker Encryption Keys (BEK) from an Azure Key Vault.

If you need to access a BitLocker-encrypted disk outside of the original server, you will need the BEK to decrypt the disk. Those can be stored in Active Directory, a TPM module, Azure Key Vault, an HSM (Hardware Security Module), and even a password. You’ll need a recovery key if you don’t have any of those. Azure VMs use a key vault.

Without a recovery key configured and no decent USB key passthrough in Hyper-V, we need to mount the disks in a recovery VM with a functional OS, as we cannot boot from the encrypted disk. But even then, you need the BEK files to unlock the disks.

Just mounting the Azure disks in a VM will not do.

Figure 1: Just mounting the Azure disks in a VM will not do.

The Issue

When preparing or accessing an OS volume or data disk volumes of a Windows Virtual Machine in Azure offline in a recovery VM that boots from its OS disk or via Windows PE using a virtual DVD-mounted ISO, you will notice those disks appear locked when you bring them online in a repair VM. That happens when Azure Disk Encryption is enabled on those disks. It does not matter if you do this on a repair VM in Azure or on-premises after downloading the VHDs.

In our example scenario, we need to access the disk of a domain controller in Azure. That VM has an OS disk (127GB) and a data disk (64GB) with the NTDS database.

wp-image-31219

Figure 2: The OS and data disks have been brought online in a recovery VM.

 

wp-image-31221

Figure 3: Volumes E and F are locked (BitLocker).

 

Unlocking the disks is necessary to access data and repair a file system; otherwise, the VM cannot boot.

I will show you how to retrieve the BEK files and use those to unlock these disks. But first, we need to get a copy of those disks to work with. Avoid using the original disk so other attempts can start from the original situation. Do not touch the source disks to maintain all options.

Note that other scenarios are possible with managed disks, but those are not the ones we address here. For more info on those, go here: https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/windows/repair-windows-vm-using-azure-virtual-machine-repair-commands?WT.mc_id=AZ-MVP-4038163 and here: https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/windows/unlock-encrypted-disk-offline#resolution-2-semi-automated-method-to-unlock-an-encrypted-disk-on-a-repair-vm?WT.mc_id=AZ-MVP-4038163.

Getting a copy of the original disks for offline use

We need copies of the original disk(s) to work with, and we’ll show you how to get those.

Create a snapshot of the original disks

In Azure, navigate to the disk(s) from which you need a snapshot and click “Create snapshot.” Follow the wizard to give the snapshot a recognizable name and choose a destination resource. What can be filled in for the disk selected works fine; if not, most default options will do. Pay attention to accessibility and security.

Select the desired access under the Networking tab.

wp-image-31222

 

Select the authentication needed in the Advanced tab.

wp-image-31223

 

Those should depend on your Azure environment’s security measures and policies. Go ahead and create your snapshot.

Convert the snapshots to disks

Once you have a snapshot, you can convert it into a virtual disk (VHD). In Azure, navigate to the snapshots you need to convert to disk. Click “Create disk” and follow the wizard to give the disk a recognizable name and choose a destination resource. It will auto-fill what it can for the disk selected, and that should work fine; if not, most default options will do. Pay attention to accessibility and security.

Select the desired access under the Networking tab.

wp-image-31225

 

In the Advanced tab, select what fits your case. Pay attention to “Data access authentication mode,” and choose what applies to your case.

wp-image-31226

 

Those should depend on your Azure environment’s security measures and policies.

Use or download the disks

You can now work on those disks in Azure or download them on-premises. In Azure, you can create a new disk from the snapshot if you need to start over. I tend to download them on-premises using Azure Storage Explorer, as my Hyper-V environment gives me all the flexibility and speed I need to test and experiment in many scenarios. I can keep a copy of the download disks to have a fresh starting point for new scenarios and leverage checkpoints. Reverting to the on-prem checkpoint is so easy and fast that I can go back easily to every step in any process. But do what you prefer and what is possible for you. You can do this in both Azure and on-premises.

Getting the BEK files from Azure Key Vault

Before using the disks we created from the snapshots, we must grab the BEK files from the Azure Key Vault. That is quite an undertaking and requires some PowerShell scripting. No worries, I have you covered with a complete script you can find in a GitHub repository of mine.

This PowerShell script retrieves wrapped BitLocker Encryption Keys (BEKs) from an Azure Key Vault, unwraps them using their associated Key Encryption Keys (KEKs), and saves the decrypted BEKs to a local directory. We use these to unlock the encrypted disks of a Windows virtual machine for offline repair. It also supports non-wrapped (not KEK encrypted) BEKs.

How it works

The script follows a structured process:

  • Retrieve all wrapped BEKs (secrets) in the specified Azure Key Vault matching a GUID format and with the ContentType of “Wrapped BEK.” It also supports non-wrapped BEKS
  • Identify each BEK’s correct KEK (Azure Key Vault key) based on the MachineName tag.
  • Prepare the Base64 string for decoding and handle any necessary padding.
  • Unwrap the BEK using the KEK and the RSA-OAEP algorithm.
  • Save the unwrapped BEK as a .bek file to your specified output directory.

All steps include error handling. If an error occurs during BEK processing, the script logs the error and continues with the next BEK — no premature termination! The console will remain open after execution so you can review the results.

Prerequisites

Azure PowerShell Modules :

  • Az.Accounts
  • Az.KeyVault

Permissions for the executing user or service principal on the Azure Key Vault:

  • Key Management Operations:
    • Get
    • List
    • Update (not required for retrieval)
    • Create (not required for retrieval)
  • Secret Permissions:
    • Get
    • List
    • Set (not required for retrieval)
  • Cryptographic Operations
    • Unwrap key

These can be given via RBAC and should not be available to a user by default. A PIM role can be a great way of predefining such rights to enable them on demand. Look at Key Vault Crypto Service Encryption User, Key Vault Crypto User, and Key Vault Secrets User, depending on what you need to achieve finally.

Finding out what Azure Key Vault a VM uses

I hope you all realize you must log in to your Azure tenant, select a specific subscription, or accept the default one. This command will serve you well:

Connect-AzAccount -TenantId 'e8c19205-0704-414b-a128-8c9c1308108b' -Subscription ‘12345678-90ab-cdef-1234-567890abcdef’

Jump through any MFA hoops you need to. After that, you’ll need to ensure you have the required permissions and activate them via PIM when necessary.

Run the below commands for your resource group and VM:

$VMInfo = Get-AzVmDiskEncryptionStatus -ResourceGroupName "rg-adds-virtual-machines" -VMName "vm-addsdwt1dc-001"

$VMInfo.OsVolumeEncryptionSettings.DiskEncryptionKey | Format-List *

$VMInfo.OsVolumeEncryptionSettings.KeyEncryptionKey | Format-List *

The results contain the name of the Azure Key Vault in the Secret and or Key URL to help you identify it in Azure.

KeyUrl : https://k-adds-virtual-machines.vault.azure.net/keys/vm-addsdwt1dc-001/9545fac8b2034ceecc00bc417768cd0c

SourceVault : Microsoft.Azure.Management.Compute.Models.SubResource

SecretUrl : https://kv-adds-virtual-machines.vault.azure.net/secrets/3A9F6D7C-ED10-49E3-A533-C3334E1AD483/b5317c6cee414ef388f4746cc9be7a76

SourceVault : Microsoft.Azure.Management.Compute.Models.SubResource

Now that you know the Key Vault, we can start grabbing the BEK files from all VMs that use that key vault to store those using the script.

Script walk-through

You already know the name of the key vault, as we showed you how to get it earlier. If you don’t like C: Temp, change the path where to save the BEK files.

The script will grab all the BEKs and Wrapped BEKs in the key vault.

$beks = Get-AzKeyVaultSecret -VaultName $keyVaultName | Where-Object {

$_.Name -match "^[0-9A-Fa-f\-]{36}$" -and ($_.ContentType -eq "Wrapped BEK" -or $_.ContentType -eq "BEK")

}

It will then loop through them individually and, based on the Content-Type property, determine whether we are dealing with a BEK or a Wrappes BEK.

If it is a wrapped BEK, it grabs it in step 1.1, and it needs to identify the Key Encryption Key (KEK) in step 1.2 to unwrap it later.

Step 1.3 sanitizes the URL-safe Base64 string by replacing dashes and pluses with underscores and slashes. This step took me a long time to complete before I realized I needed it.

We handle any needed padding with “=” in step 1.4 to ensure the string’s length is a multiple of 4, as required by the Base64 standard.

In step 1.5, we unwrap (decrypt) the BEK. We assign the raw result to $bekBytes. The PowerShell command makes things much easier than when we needed to leverage a REST API to achieve this.

When the BEK is unwrapped, we can grab it easily, as it does not need decryption.

All that is left to do is generate a usable file name for the BEK (it shows the drive letter of the volume decrypts, the volume label, the Windows name of the VM, and a time stamp. The naming helps to find the correct one to use.

# Step 1: Process each BEK individually

foreach ($bekSecret in $beks) {

Write-Host ""

Write-Host "Step 1: Processing BEK: $($bekSecret.Name)" -ForegroundColor Yellow

try {

Write-Host "Step 1.1: Retrieving BEK from Key Vault..."

$bek = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $bekSecret.Name

if (-not $bek) {

Write-Error "ERROR: BEK '$($bekSecret.Name)' not found in Key Vault."

continue

}

$ContentType = $bek.ContentType

# Determine processing based on ContentType

if ($ContentType -eq "Wrapped BEK") {

Write-Host "INFO: Detected Wrapped BEK. Unwrapping required..." -ForegroundColor Cyan

#Step 1..1: Decode the Base64 string to get the wrapped BEK bytes

$Base64String = $bek.SecretValue | ConvertFrom-SecureString -AsPlainText

# Step 1.2: Identify the correct KEK by matching the machine name

Write-Host "Step 1.2: Identifying correct KEK for unwrapping..."

$KEKNames = (Get-AzKeyVaultKey -VaultName $keyVaultName).Name

$kekName = $null

foreach ($RetrievedKekName in $KEKNames) {

if ($RetrievedKekName -like "*$($bek.Tags.MachineName)*") {

$kekName = $RetrievedKekName

Write-Host "Step 1.2.1: Matched KEK: $kekName" -ForegroundColor Magenta

break

}

}

if (-not $kekName) {

Write-Error "ERROR: No matching KEK found for machine name '$($bek.Tags.MachineName)'."

continue

}

# Step 1.3: Prepare the wrapped BEK bytes

Write-Host "Step 1.3: Preparing Base64 string for decoding..."

$Base64String = $Base64String -replace "-", "+" -replace "_", "/"

# Step 1.4: Correct Base64 padding if necessary

Write-Host "Step 1.4: Correcting Base64 padding if necessary..."

switch ($Base64String.Length % 4) {

2 { $Base64String += "==" }

3 { $Base64String += "=" }

}

$WrappedBEKBytes = [Convert]::FromBase64String($Base64String)

# Step 1.5: Unwrap the BEK using the KEK

Write-Host "Step 1.5: Unwrapping BEK using KEK..."

$unwrappedResult = Invoke-AzKeyVaultKeyOperation `

-Operation Unwrap `

-Algorithm RSA-OAEP `

-VaultName $keyVaultName `

-Name $kekName `

-ByteArrayValue $WrappedBEKBytes

if (-not ($unwrappedResult -and $unwrappedResult.RawResult)) {

Write-Error "ERROR: Failed to unwrap the BEK '$($bekSecret.Name)'."

continue

}

$bekBytes = $unwrappedResult.RawResult

}

elseif ($ContentType -eq "BEK") {

Write-Host "INFO: Detected Plain BEK. No unwrapping required..." -ForegroundColor Cyan

$Base64String = $bek.SecretValue | ConvertFrom-SecureString -AsPlainText

$bekBytes = [Convert]::FromBase64String($Base64String)

}

else {

Write-Error "ERROR: Unknown ContentType '$ContentType' for BEK '$($bekSecret.Name)'. Skipping..."

continue

}

# Step 1.6: Save the BEK to a file

Write-Host "Step 1.6: Saving BEK to file..."

$driveLetter = $bek.Tags.VolumeLetter.TrimEnd(":\\")

$timestamp = (Get-Date).ToString("yyyyMMddHHmmss")

$uniqueBekFileName = "$driveLetter-$($bek.Tags.VolumeLabel)-$($bek.Tags.MachineName)-$($ContentType.Replace(' ',''))-$($bek.Name)-$timestamp.bek"

$FullFilePath = Join-Path -Path $UnwrappedBekPath -ChildPath $uniqueBekFileName

[System.IO.File]::WriteAllBytes($FullFilePath, $bekBytes)

Write-Host "SUCCESS: Saved BEK to: $FullFilePath" -ForegroundColor Green

}

catch {

Write-Error "ERROR: Processing BEK '$($bekSecret.Name)' failed. Details: $_"

continue

}

}

The output will look like this.

wp-image-31227

 

If you open one in Notepad and see “B i t l o c k e r E x t e n s i o n K e y P r o t e c t o r” in there, you know it is what you are after and succeeded.

wp-image-31228

 

Now that we have our BEKs for all disks of all virtual machines the key vault is serving, we can use it to decrypt those disks.

Please grab the script from https://github.com/WorkingHardInIT/Unwrap-BEKs-from-Azure-Key-Vault-and-Save-to-Disk and don’t copy and paste it from this article to avoid any character mangling that would hinder execution.

Decrypting or unlocking the volumes

Leverage a recovery VM

If you don’t have one handy, create a Windows VM with the same OS (preferably) as the one from which you got the disks. Mount the disks you created and downloaded from Azure. As said, I keep an original of the downloaded disks to start over quickly if things go bad. The recovery VM needs to have the BitLocker feature installed to have the tools you need handy.

You can use the GUI or PowerShell for this.

#Find out free locations on the SCSI controller

Get-VMScsiController -VMName "AZDC01RECOVER"

#Add the disks to recover

Add-VMHardDiskDrive -VMName "AZDC01RECOVER" -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 2 -Path "T:\VirtualMachines\AZureDC01RECOVER\Virtual Hard Disks\RecoverOSDiskDC01.vhd"

Add-VMHardDiskDrive -VMName "AZDC01RECOVER" -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 3 -Path "T:\VirtualMachines\AZureDC01RECOVER\Virtual Hard Disks\RecoverNTDSDISKDC01.vhd"

#CHeck your handy work

Get-VMScsiController -VMName "AZDC01RECOVER"

As you can see, I am mounting the disks to locations 2 and 3, which were free. You can bring the disks online in Disk Manager and ensure the (encrypted) volumes have a drive letter assigned. That is your starting point.

wp-image-31229

 

Copy the BEK files you got via the PowerShell script into the recovery VM.

wp-image-31230

Open an elevated command prompt and run the following commands to unlock both disks.

manage-bde -unlock E: -RecoveryKey "C:\SysAdmin\BEKFiles\C-Windows-addsdwt1dc-001-WrappedBEK-3A9F6D7C-ED10-49E3-A533-C3334E1AD483-20250427113318.bek"

manage-bde -unlock F: -RecoveryKey "C:\SysAdmin\BEKFiles\N-NTDS-DISK-addsdwt1dc-001-WrappedBEK-360F5599-8B3D-4D36-A897-ECFED10FB44A-20250427113317.bek"

In Windows Explorer, both disks show as unlocked and accessible!

wp-image-31231

 

Depending on the use case, we might want to boot from the OS to work on the disks, so we need the decrypted. Once done, we can attach them to the original VM and handle BitLocker encryption. Run these commands from an elevated command prompt.

manage-bde -off E: 

manage-bde -off F: 

That will turn off BitLocker and decrypt the drives. You can follow the progress of the decryption using:

manage-bde -status

wp-image-31232

You can do all the above using PowerShell as well.

# Unlocking drive E: with a Recovery Key

Unlock-BitLocker -MountPoint "E:" -RecoveryKeyPath "C:\SysAdmin\BEKFiles\C-Windows-addsdwt1dc-001-WrappedBEK-3A9F6D7C-ED10-49E3-A533-C3334E1AD483-20250427113318.bek"

# Unlocking drive F: with a Recovery Key

Unlock-BitLocker -MountPoint "F:" -RecoveryKeyPath "C:\SysAdmin\BEKFiles\N-NTDS-DISK-addsdwt1dc-001-WrappedBEK-360F5599-8B3D-4D36-A897-ECFED10FB44A-20250427113317.bek"

# Disabling BitLocker on drive E:

Disable-BitLocker -MountPoint "E:"

# Disabling BitLocker on drive F:

Disable-BitLocker -MountPoint "F:"

# Displaying the BitLocker status of all volumes

Get-BitLockerVolume

# Displaying the BitLocker status of drive E:

Get-BitLockerVolume -MountPoint "E:"

You now have the unencrypted disks with BitLocker turned off to repair, test, and recover data from, create a new VM, experiment with various scenarios, and eventually, if desired, swap out the current one of your problematic Azure virtual machine. Mission accomplished!

This article describes methods for attaching an encrypted OS disk to a recovery VM and unlocking it. After the disk is unlocked, you can repair it, grab data from it, etc. As a final step, you can replace the OS disk on the original VM with the repaired one(s), depending on the use case and needs.

Conclusion

In this article, I have demonstrated how to grab the BEK files you need to unlock Azure Encrypted Disk and how to use those BEK files. I hope this overview and the script help you out someday. Good luck.

Hey! Found Didier’s article helpful? Looking to deploy a new, easy-to-manage, and cost-effective hyperconverged infrastructure?
Alex Bykovskyi
Alex Bykovskyi StarWind Virtual HCI Appliance Product Manager
Well, we can help you with this one! Building a new hyperconverged environment is a breeze with StarWind Virtual HCI Appliance (VHCA). It’s a complete hyperconverged infrastructure solution that combines hypervisor (vSphere, Hyper-V, Proxmox, or our custom version of KVM), software-defined storage (StarWind VSAN), and streamlined management tools. Interested in diving deeper into VHCA’s capabilities and features? Book your StarWind Virtual HCI Appliance demo today!