The PowerShell script I discuss in this post allows you to search and find BitLocker recovery passwords stored in Active Directory (AD).

Recently I had a support call where I was concerned a laptop I was working on remotely had gone into BitLocker recovery. It had become nonresponsive after a reboot, and an onsite contact reported it was on a "blue screen with a load of numbers asking for a code."

An all-too-familiar but unwelcome chill ran through me as I realized the BitLocker Key had not been successfully backed up to Active Directory. However, now was not the time to wonder why that hadn't happened; now was the time to panic about the CEO of my largest client being locked out of their laptop.

Of course, it turned out to be much simpler. The laptop had booted into Dell's diagnostic screen, BitLocker had not been successfully enabled on the laptop, and all was nearly right with the world again. However, I still needed answers.

So, firstly, why wasn't the BitLocker recovery password in AD?

I had set up numerous laptops for this client before, and sure enough, once domain joined, the key had appeared in the properties of the computer object. However, what I had misunderstood about the BitLocker Group Policy Object (GPO) is that although it sets policies on recovery options, it does not go so far as to encrypt the volumes defined in the policy (OS, Data, etc.). So you may also need to do that manually.

Then I wondered, how many other devices do I have deployed here that also do not have BitLocker correctly enabled? My task was to go through the GUI manually and look at each computer object in turn for a BitLocker recovery password.

Or I could query them all at once with PowerShell and only show those needing attention. So below is the script I wrote to do just that.

BitLocker does not store recovery passwords as part of the default properties for a computer object, so running Get-ADComputer on its own is no help.

We need to query the computer object for the field the password is stored in, msFVE-RecoveryInformation, which you can view using ADSI Edit.

To reveal that attribute with PowerShell, we need to use the distinguished name of the computer object and then look for subobjects in the msFVE-RecoveryInformation class.

We can use Get-ChildItem to query subobjects, but we need to point that to the correct location, which is inside the special "Active Directory" drive that PowerShell creates. So running the command below will get the recovery object and store it in the $ldObj variable for us.

$pc = Get-ADComputer PC01
$dn = $pc.DistinguishedName
$ldPath = "AD:\",$dn -join ""
$ldObj = Get-ChildItem $ldPath | where {$_.objectClass -eq "msFVE-RecoveryInformation" }
Get ADComputer

Get ADComputer

This gets us the DistinguishedName (DN) of the recovery object. We can now run another query against that DN to reveal the BitLocker recovery password.

$ldObj = "AD:\",$ldObj.DistinguishedName -join ""
$btPass = Get-Item $ldObj -properties "msFVE-RecoveryPassword"

The $btPass variable stores the entire BitLocker recovery password object from AD, so to get that into a usable format for scripting, we only need to select the password itself.

$btPass.'msFVE-RecoveryPassword'

Entering that at the prompt will show you the recovery password for the selected computer object.

BitLocker password

BitLocker password

You can then put these code examples together—like I have in the example above—to build a tool that can search an entire organizational unit (OU) or just against one particular computer.

My script is in full below. It has parameters defined for a single computer or for you to run against an OU. It will attempt to communicate with an online computer and retrieve some basic information, such as the OS and whether it is a desktop or mobile.

Subscribe to 4sysops newsletter!

<#
      .SYNOPSIS
      Searches Active Directory for stored BitLocker recovery passwords
         
      .EXAMPLE
      Search for BitLocker recovery password for a single computer:
      .\BitLocker-Query.ps1 -computer computer001
    
      .EXAMPLE
      Search for BitLocker recovery passwords for all computers in an OU, active within 30 days:
      .\BitLocker-Query.ps1 -OU "myOU,dc=domain,dc=com" -activeDays 30

      .EXAMPLE
      Search for BitLocker recovery passwords for all computers in an OU, active within 30 days; only show results for online computers:
      .\BitLocker-Query.ps1 -OU "myOU,dc=domain,dc=com" -activeDays 30 | where { $_.Online -eq "Yes" } | ft -AutoSize

      .EXAMPLE
      Search for BitLocker recovery passwords for all computers in an OU, active within 30 days; only show results for computers with passwords stored:
      .\BitLocker-Query.ps1 -OU "myOU,dc=domain,dc=com" -activeDays 30 | where { ($_.Online -eq "Yes") -and ($_.BitLockerKey -ne "none") } | ft -AutoSize
    
  #>
param(
    [parameter(ParameterSetName='pc')]
    [ValidateNotNull()]
    [string]$computer,
    [parameter(ParameterSetName='domain')]
    [ValidateNotNull()]
    [string]$ou,
    [int]$activeDays
)
$date = [datetime]::Now
$lastUsed = $date.AddDays(-$activeDays)
$computerObjs = @()
$padVal = 35
$pcNameLabel = "Computer Name".PadRight($padVal," ")
$dateLabel = "Computers Active Since".PadRight($padVal," ")
$ouLabel = "Computer Accounts".PadRight($padVal," ")
Write-Output "Searching Active Directory Computer Objects for stored BitLocker Recovery Passwords."
Write-Output "v0.1 Robert Pearman, November 2018"
Write-Output ""
if($computer)
{
    # Search PC Only
    Write-Output "$pcNameLabel : $computer"
    $obj = get-adcomputer $computer -properties *
}
if($ou)
{
    Write-Output "$ouLabel : $ou"
    Write-Output "$dateLabel : $lastUsed"
    # Search Domain
    $obj = get-adcomputer -filter {LastLogonDate -ge $lastUsed -and OperatingSystem -eq "Windows 10 Pro" } -Properties OperatingSystem -searchbase $ou
}
Write-Output ""
Write-Output "Searching.."
foreach ($pc in $obj)
{
    # build object
    $pcName = $pc.Name
    $pcObj = New-Object System.Object
    # store os, name, chasis
    # if offline look for key anyway
    $pcObj | Add-Member -Type NoteProperty -Name Name -Value $pcName
    $pcObj | Add-Member -Type NoteProperty -Name OS -Value $pc.OperatingSystem
    # online / offline
    try{
        $onLine = Test-Connection $pcName -Count 1 -ErrorAction Stop
        # mobile / desktop
        $pcObj | Add-Member -Type NoteProperty -Name Online -Value "Yes"
        try{
            $chasisType = (Get-WmiObject Win32_ComputerSystem -ComputerName $pcName -ErrorAction Stop).PCSystemType 
            if(($chasisType) -eq "2")
            {
                $pcObj | Add-Member -Type NoteProperty -Name Type -Value "Mobile"
            }
            else
            {
                $pcObj | Add-Member -Type NoteProperty -Name Type -Value "Desktop"
            }
        }
        catch{
            $pcObj | Add-Member -Type NoteProperty -Name Type -Value "-"
        }
    }
    catch{
        $pcObj | Add-Member -Type NoteProperty -Name Online -Value "No"
        $pcObj | Add-Member -Type NoteProperty -Name Type -Value "-"
    }
    # key stored
    $dn = $pc.DistinguishedName
    $ldPath = "AD:\",$dn -join ""
    $ldObj = Get-ChildItem $ldPath | where {$_.objectClass -eq "msFVE-RecoveryInformation" } | select -First 1
    if($ldObj)
    {
        $ldObj = "AD:\",$ldObj.DistinguishedName -join ""
        $btPass = Get-Item $ldObj -properties "msFVE-RecoveryPassword"
        if($btPass)
        {
            $pcObj | Add-Member -Type NoteProperty -Name BitLockerKey -Value $btPass.'msFVE-RecoveryPassword'
        }
    }
    else
    {
        # no key
        $pcObj | Add-Member -Type NoteProperty -Name BitLockerKey -Value "None"
    }
    $computerObjs += $pcObj
}
$computerObjs
1 Comment
  1. Scott 2 years ago

    Is there a way to run a powershell script that returns all recovery passwords for a computer object? when I run my script, it only returns one recovery password, even though a computer may have four of them. thanks

Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account