Share via


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.

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

.Notes
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)
             $Path; 
         } 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
                 $Path;
             } 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

  • Anonymous
    November 01, 2013
    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.

  • Anonymous
    August 09, 2014
    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 (            [Security.Principal.WindowsIdentity]::GetCurrent()    )).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)         ) {    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; } else { Write-Error "Must be in a 'Run as Administrator' window."; }