BitLocker and Self-Immolation

My primary device is corporate-owned, and contains a lot of corporate data.  Policy says to have it secured by BitLocker, so I’ll have it secured by BitLocker.  Perfectly reasonable, no?

However, I suspect something is wrong with this laptop’s TPM chip.  Every so often, it decides that it won’t accept my BitLocker PIN, and requires I have the recovery passcode, all 48 digits of it.  I save it to my SkyDrive (so I can read it via my phone if/when I need it), but sometimes I forget to do so.  Both as an academic exercise, and as a way making it possible for me to schedule it as a task, I wrote the script below.

The two key takeaways are:

– Get-BitLockerVolume gives the BitLocker recovery data

– Start-Process PowerShell.exe –Verb RunAs escalates permissions


<# .Synopsis
Save the bitlocker recovery key.

Save the bitlocker recovery key for the specified drive, elevating itself to Administrator if possible.  

The self-elevation is brittle as hell.  This script must be placed in a path that does not have special characters.  Specifically ‘$home\Skydrive @ Microsoft\foo’ does NOT work.


param (
     [string]$Path = “$home\SkyDrive\BitlockerRecovery\$env:ComputerName-$(Get-Date -Format ‘yyyy-MM-dd’).txt”,
     [string]$Drive = “c”

function Get-BitLockerRecoveryKey {
     param (
         [string]$Path = “$home\SkyDrive\BitlockerRecovery\$env:ComputerName-$(Get-Date -Format ‘yyyy-MM-dd’).txt”,
         [string]$Drive = “c”

     # move existing key
     if (Test-Path -Path $path) { mv $path (“$path-$(Get-Date -Format yyyyMMddhhmmss).txt”); }

     # attempt to create destination folder if it doesn’t exist
     $pathDirName = Split-Path -Parent -Path $Path;
     if (!(Test-Path -Path $pathDirName)) { New-Item -ItemType Directory -Path $path -ErrorAction SilentlyContinue | Out-null; }
     if (Test-Path -Path $pathDirName) {
         # If the folder exists, perform the heavy lifting
         $scriptBlock = {
             param (
                 [string]$Path = “$home\SkyDrive\BitlockerRecovery\$env:ComputerName-$(Get-Date -Format ‘yyyy-MM-dd’).txt”,
                 [string]$Drive = “c”

             $KeyProtector = (Get-BitLockerVolume -ErrorAction SilentlyContinue -MountPoint $Drive).KeyProtector | ? { $_.KeyProtectorType -eq ‘RecoveryPassword’; }
             if ($keyProtector) { “ID: $($KeyProtector.KeyProtectorId -replace ‘[{}]’)`n`nKey: $($KeyProtector.RecoveryPassword)” | Out-File -FilePath $Path; }

         } # $scriptBlock =
         Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $Path, $Drive;
         if (Test-Path -path $Path) { 
             # if the file exists, this worked (but that’s normally not the case)
         } else {
             # if the file doesn’t exist, elevate itself.
             Start-Process PowerShell.Exe -WindowStyle Hidden -Verb RunAs -ArgumentList “-NoProfile -File $($MyInvocation.ScriptName) -Drive $Drive -Path $Path” -Wait;
             if (Test-Path -Path $Path) {
                 # if the file exists, this worked
             } else {
                 # otherwise, carp and exit
                 Write-Warning “Unable to save BitLocker recovery key for drive ${drive}:”;
             } # if (Test-Path -Path $Path)

         } # if (Test-Path $Path)

     } else {
         # if output folder doesn’t exist, carp and exit
         Write-Warning “Unable to find nor create $pathDirName”;

     } # if (Test-Path -Path $pathDirName)

} # function

# run it.
Get-BitLockerRecoveryKey -Path $Path -Drive $Drive;

Comments (2)

  1. Sam says:

    Every now and then I also face the same problem: My corporate PC asks me to input the recovery key for no reason. I recently discovered that plugging in some USB devices might trigger this behaviour. I just have to unplug it, reboot and everything goes back to normal (i.e. prompting for PIN).

    I initially thought it only happened with external drives, but my 4G USB modem is also seen as an external USB drive though.

  2. timdunn says:

    Here's a cleaner way to do it:

    param (

       $Path = "$homeOneDriveBitlockerRecovery$env:Computername.$((Get-WmiObject -Class Win32_Computersystem).Domain).txt".ToLower()


    if (

       (New-Object -TypeName Security.Principal.WindowsPrincipal -ArgumentList (





       if (!(Test-Path -Path $Path))

       { if (New-Item -Path $Path -ItemType Directory) { Remove-Item -Path $Path; } }

       Import-Module -Name Bitlocker;

       Get-BitLockerVolume |

       % {

           $volumeData = $_;

           $volumeData |

           % {            

               "Drive: " + $_.MountPoint;

               "GUID:  " + $_.KeyProtector[1].KeyProtectorId -replace '[{}]';

               "Key:   " + $_.KeyProtector[1].RecoveryPassword



       } | Set-Content -Path $Path

       Write-Host -ForegroundColor Green "Created file " -NoNewline;

       (Resolve-Path -Path $Path).ProviderPath;



    { Write-Error "Must be in a 'Run as Administrator' window."; }