Get BitLocker Recovery From Active Directory with Powershell

At the company I currently work for we’ve been using BitLocker since Vista (although Vista install base was rather small). Having moved from another “Pretty Good” Disk encryption technology, one thing we struggled with was Recovery information. While the previous solution had its own server to store all recovery keys, BitLocker links these to the Computer Object. When that computer object is deleted, so is the key. This was a battle for us at first since we have automation in place to remove stale AD Accounts, but–at the time–did not have any method to backup that information. We immediately added a table to a database and as part of our cleanup would backup these Keys.

First: Why not MBAM?

I loosely touched on this in another post regarding TPM Backup information in AD and i’ll give the quick summary again. By the time MBAM cam around, we already had our backup system in place. This was added into a global utility that allowed our technicians to perform AD tasks without AD permissions (Create computer, reset, move ou, etc…). MBAM would have just been “another thing” for us to maintain and manage. With our custom tool and SCCM already in place, MBAM did not provide us any additional benefits. For those of you using MBAM, This may not be for you, however this still provides a great way to quickly grab the information for those ad-hoc requests.

As we move to upgrade our various automation from the tried-and-true VBScript to the ever-so-loved Powershell, Obtaining the BitLocker Recovery Information was an odd one. If you use the RSAT tools and pull up details of a computer object there is a “BitLocker Recovery tab”.


Each BitLocker Recovery password is an object of the computer account object. The odd thing is that by doing a Get-ADComputer, Recovery information is not returned as a “property” like other items–and where I expected it. As usual, first step was to use a search engine and see what others had done. I found a few results that gave me what i wanted (notably this post) but didn’t like the way it was scripted. The snippet that does the work is here:

$objADObject = get-adobject -Filter * | Where-Object {$_.DistinguishedName -match $objComputer.Name -and $_.ObjectClass -eq "msFVE-RecoveryInformation"}

While this gets the job done it is slow and by slow i mean the combination of “-Filter *” and piping to “Where-Object” is looking at everything before seeing if its the item (droid) that I’m looking for. Recovery Key look-up for my system took approximately 15 seconds for the first result, and didnt finish processing until a few seconds after that.

Let’s step back and look at a BitLocker Recovery object (msFVE-RecoveryInformation); really lets justify the filter “$_.DistinguishedName -match $objComputer.Name”.

Each BitLocker Recovery object is of the Object Class: msFVE-RecoveryInformation. If you look at the DistinguishedName of an object we can see it stems from the Distinguished name of the computer object it is attached to:

DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swComputers,DC=swansonglab,DC=com

Unfortunately this is the best way (I’ve found) to tie a recovery object back to the computer account. For those curious, here is what’s contained in a msFVE-RecoveryInformation object:

CanonicalName :{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
CN : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
Created : 10/20/2014 1:10:55 PM
createTimeStamp : 10/20/2014 1:10:55 PM
Deleted :
Description :
DisplayName :
DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swComputers,DC=swansonglab,DC=com
dSCorePropagationData : {12/31/1600 6:00:00 PM}
instanceType : 4
isDeleted :
LastKnownParent :
Modified : 10/20/2014 1:10:55 PM
modifyTimeStamp : 10/20/2014 1:10:55 PM
msFVE-KeyPackage : {136, 1, 0, 0...}
msFVE-RecoveryGuid : {255, 105, 157, 229...}
msFVE-RecoveryPassword : 465762-121880-049797-598411-533643-549890-128436-549736
msFVE-VolumeGuid : {146, 36, 120, 28...}
Name : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity
ObjectCategory : CN=ms-FVE-RecoveryInformation,CN=Schema,CN=Configuration,DC=swansonglab,DC=com
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : d0a15cc8-5f86-42ed-8942-633cec25b6b1
ProtectedFromAccidentalDeletion : False
sDRightsEffective : 15
showInAdvancedViewOnly : True
uSNChanged : 99936
uSNCreated : 99936
whenChanged : 10/20/2014 1:10:55 PM
whenCreated : 10/20/2014 1:10:55 PM

Remember in most cases getting recovery is searched by the GUID. This can be filtered on using Powershell with no problems or computer object linking. The example I’m looking at is getting all recovery objects attached to a computer account.

So my issues with the snippet above (using “-Filter *” and “Where-Object”), again, was time consuming. Since the Recovery Information objects are attached to a computer object we can simply use the computer account’s Distinguished Name as the search base for the command:

# Get Computer Object
> $computer = Get-ADComputer -Filter {Name -eq 'WIN7X86PC01'}

# Get all BitLocker Recovery Keys for that Computer. Note the 'SearchBase' parameter
> $BitLockerObjects = Get-ADObject -Filter {objectclass -eq 'msFVE-RecoveryInformation'} -SearchBase $computer.DistinguishedName -Properties 'msFVE-RecoveryPassword'

# Output the results!
> $BitLockerObjects
DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swCompute
msFVE-RecoveryPassword : 465762-121880-049797-598411-533643-549890-128436-549736
Name : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : d0a15cc8-5f86-42ed-8942-633cec25b6b1

DistinguishedName : CN=2014-10-20T13:11:29-06:00{450547C6-675C-4A61-B276-17CC620D3885},CN=WIN7X86PC01,OU=swCompute
msFVE-RecoveryPassword : 632126-201135-053504-485045-151657-139986-094820-137687
Name : 2014-10-20T13:11:29-06:00{450547C6-675C-4A61-B276-17CC620D3885}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : 8c3963ea-89ec-4b41-934b-ee6023d9d1e9

DistinguishedName : CN=2014-10-20T13:12:03-06:00{A29D2D47-89D6-4459-B106-40B1F62A04EF},CN=WIN7X86PC01,OU=swCompute
msFVE-RecoveryPassword : 497178-478654-023111-302291-606034-162855-504163-720698
Name : 2014-10-20T13:12:03-06:00{A29D2D47-89D6-4459-B106-40B1F62A04EF}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : 4a72004e-e76e-4cb3-a828-152011b8b541

Hopefully this has provided some additional information on BitLocker Recovery keys and how to obtain them should you ever need to!


Using TPM Backups with Powershell

Backing up TPM information may not be a complete necessity for all, but certainly has its advantages. Understanding why we do this and what we can do with it.

Why not MBAM? : I’ll be brief about this…by the time MBAM came around, we had already built out all that it had to offer. We had key backup and retention and a web portal to access Recovery information for our support staff to use (Along with auditing of who accessed what). Anything else was just extra “stuff”. We didn’t need it. If you have MBAM and are happy with it: Great!

AD Schema Extensions/Updates

I won’t go into too much detail here other than pointing out a few things:

Group Policy Settings

In order to have your TPM information backed up to Active Directory there’s one Policy to set. As read in the description, this policy will require ADDS connectivity to backup this information whenever a TPM owner password is set or changed. With this setting enabled we’ll see TPM information backup to Active Directory.

This is the policy that is required for AD backup to work:

Location: Computer Configuration> Administrative Templates> System> Trusted Platform Module Services

Policy: Turn on TPM Backup to Active Directory Domain Services

Setting: Enabled

Some other notable settings that correspond with this and may benefit you (depending on your BitLocker configuration). You can set the TPM Lockout duration and Lockout threshold. For more information on those policies:

What the Backup Looks Like

Depending on if you’re running Windows 7 or Windows 8/8.1 the TPM information will backup differently.

Windows 7

With Windows 7, the TPM information is added to the “msTPM-OwnerInformation” attribute of the AD Computer object.

Windows 8+

With Windows 8+ things get a bit more complex. The 2012 Schema update mentioned above adds a new container at the root of your domain “TPM Device”. Inside of this is (you guessed it!) TPM objects along with their TPM Recovery passwords. The AD Computer Object is linked to the TPM object through the Computer’s Attribute “msTPM-TpmInformationForComputer”.

For example, my Computer object will have the msTPM-TpmInformationForComputer attribute who’s value will reference the TPM object in the “TPM Devices” container. The TPM Object contains the recovery information in the “msTPM-OwnerInformation” attribute. This will be much clearer further on.

Back Together

In both instances the TPM Recovery information is a 20-byte binary value encoded to a 28-byte base64 null-terminated string. Basically, it’ll be a string of gibberish/rubbish/balderdash that you can’t read, but will find is very useful!

Using TPM Recovery Information

Organizations who utilize a TPM + PIN configuration for BitLocker will benefit the greatest from this information. Having a PIN for users means one more password for a user, which means one more password for someone to forget, which means they’ll mash and mash the wrong password convincing themselves they typed it correctly. In doing this, the TPM will identify this as an intrusion, and will eventually go into a lockout status. We are then forced to boot with our recovery password (hopefully backed up to Active Directory) and can at least get into the system. Just because we used BitLocker Recovery, doesn’t mean that our TPM lockout issue was resolved.

Now let’s say I reboot my system before the TPM lockout has reset itself. Recovery again but now what? There’s not exactly a countdown saying “your TPM will reset in XX minutes” otherwise you’d be telling whoever’s trying to break into your system “Wait 5 minutes to try again”. To reset the TPM lockout, we have an option to “Reset TPM Lockout” which requires the TPM Owner information that we’ve backed up to Active Directory. We pass in the TPM password to the system and the lockout state is reset and we can use our PIN like normal again.
Script it, Automate it, Any Way You Want It

So let’s put this information and scenario to good use. The above link for “Preparing Active Directory” includes some sample vbscripts that can help pull down this information. However, we have Powershell and we want to exercise its greatness.

We can grab the Information from Active Directory (Powershell or vbscript) and then pass that recovery into the ResetTPMLockout Method of the Win32_TPM class. With Powershell we’ll need the Active Directory modules (included with the RSAT tools).


Import-Module ActiveDirectory

# you can also setup the computer name as an argument to do this remotely 
$computerName = $env:COMPUTERNAME
$tpmPassword = ""

# Gets the AD Object of the computer
# We'll grab the Property for Windows 7 and Windows 8+
$computerAdObject = Get-ADComputer -Filter 'Name -eq $computerName' -Properties Name, OperatingSystem, 'msTPM-TpmInformationForComputer', 'msTPM-OwnerInformation'

# Evaluating the OS
if (($computerAdObject.OperatingSystem) -like "Windows 7" )
     $tpmPassword = $computerAdObject.'msTPM-OwnerInformation'

if (($computerAdObject.OperatingSystem) -like "Windows 8")
     # Gets the TPM object
     $tpmAdObject = Get-ADObject -Filter 'distinguishedName -eq $($computerAdObject.'msTPM-TpmInformationForComputer')' -Properties CN, Name, msTPM-OwnerInformation -Credential $authCreds

     # Stores the TPM password
     $tpmPassword = $tpmAdObject.'msTPM-OwnerInformation'

# Reset TPM Lockout
if (-Not ($tpmPassword = ""))
     # Get local TPM object
     $tpmObject = Get-WmiObject Win32_TPM -Namespace root/cimv2/security/MicrosoftTpm -ComputerName $computerName

     $return = $tpmObject.ResetAuthLockout($tpmPassword)

One Step Further…

Let’s say we want to change the TPM Owners password. We’ll still need to do the above to get the backed up password from Active Directory. Once we have that we can use the Win32_TPM WMI class to do this. However, we can’t just pass a string of text, we need to convert to that “gibberish” format we saw above. Just a couple quick lines in Powershell and we’ve successfully changed the TPM Owner Password:


$newEncodedPassword = ($tpmObject.ConvertToOwnerAuth("NewPassword")).OwnerAuth

Hopefully this gives you a better understanding of how to use the TPM Passwords that you’ve been backing up to Active Directory.

Thanks for reading!