mirror of
https://github.com/MicrosoftDocs/windows-itpro-docs.git
synced 2025-05-13 05:47:23 +00:00
updates
This commit is contained in:
parent
1fdbf32810
commit
76f92579d1
@ -1,16 +1,16 @@
|
|||||||
---
|
---
|
||||||
title: BitLocker recovery guide
|
title: BitLocker recovery guide
|
||||||
description: This article for IT professionals describes how to recover BitLocker keys from Active Directory Domain Services (AD DS).
|
description: Learn how to recover BitLocker keys from Microsoft Entra ID and Active Directory Domain Services (AD DS).
|
||||||
ms.collection:
|
ms.collection:
|
||||||
- highpri
|
- highpri
|
||||||
- tier1
|
- tier1
|
||||||
ms.topic: conceptual
|
ms.topic: howto
|
||||||
ms.date: 11/08/2022
|
ms.date: 09/29/2023
|
||||||
---
|
---
|
||||||
|
|
||||||
# BitLocker recovery guide
|
# BitLocker recovery guide
|
||||||
|
|
||||||
This article describes how to recover BitLocker keys from AD DS.
|
This article describes how to recover BitLocker keys from Microsoft Entra ID and Active Directory Domain Services (AD DS).
|
||||||
|
|
||||||
Organizations can use BitLocker recovery information saved in Active Directory Domain Services (AD DS) to access BitLocker-protected data. It's recommended to create a recovery model for BitLocker while planning for BitLocker deployment.
|
Organizations can use BitLocker recovery information saved in Active Directory Domain Services (AD DS) to access BitLocker-protected data. It's recommended to create a recovery model for BitLocker while planning for BitLocker deployment.
|
||||||
|
|
||||||
@ -368,13 +368,13 @@ There are rules governing which hint is shown during the recovery (in the order
|
|||||||
|
|
||||||
#### Example 1 (single recovery key with single backup)
|
#### Example 1 (single recovery key with single backup)
|
||||||
|
|
||||||
| Custom URL | Yes |
|
| Custom URL | Yes |
|
||||||
|----------------------|------------|
|
|----------------------------|-----|
|
||||||
| Saved to Microsoft Account | Yes |
|
| Saved to Microsoft Account | Yes |
|
||||||
| Saved to Azure AD | No |
|
| Saved to Azure AD | No |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | No |
|
| Saved to file | No |
|
||||||
|
|
||||||
**Result:** The hints for the Microsoft account and custom URL are displayed.
|
**Result:** The hints for the Microsoft account and custom URL are displayed.
|
||||||
|
|
||||||
@ -382,13 +382,13 @@ There are rules governing which hint is shown during the recovery (in the order
|
|||||||
|
|
||||||
#### Example 2 (single recovery key with single backup)
|
#### Example 2 (single recovery key with single backup)
|
||||||
|
|
||||||
| Custom URL | Yes |
|
| Custom URL | Yes |
|
||||||
|----------------------|------------|
|
|----------------------------|-----|
|
||||||
| Saved to Microsoft Account | No |
|
| Saved to Microsoft Account | No |
|
||||||
| Saved to Azure AD | No |
|
| Saved to Azure AD | No |
|
||||||
| Saved to Active Directory | Yes |
|
| Saved to Active Directory | Yes |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | No |
|
| Saved to file | No |
|
||||||
|
|
||||||
**Result:** Only the custom URL is displayed.
|
**Result:** Only the custom URL is displayed.
|
||||||
|
|
||||||
@ -396,13 +396,13 @@ There are rules governing which hint is shown during the recovery (in the order
|
|||||||
|
|
||||||
#### Example 3 (single recovery key with multiple backups)
|
#### Example 3 (single recovery key with multiple backups)
|
||||||
|
|
||||||
| Custom URL | No |
|
| Custom URL | No |
|
||||||
|----------------------|------------|
|
|----------------------------|-----|
|
||||||
| Saved to Microsoft Account | Yes |
|
| Saved to Microsoft Account | Yes |
|
||||||
| Saved to Azure AD | Yes |
|
| Saved to Azure AD | Yes |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | Yes |
|
| Printed | Yes |
|
||||||
| Saved to file | Yes |
|
| Saved to file | Yes |
|
||||||
|
|
||||||
**Result:** Only the Microsoft Account hint is displayed.
|
**Result:** Only the Microsoft Account hint is displayed.
|
||||||
|
|
||||||
@ -410,28 +410,26 @@ There are rules governing which hint is shown during the recovery (in the order
|
|||||||
|
|
||||||
#### Example 4 (multiple recovery passwords)
|
#### Example 4 (multiple recovery passwords)
|
||||||
|
|
||||||
| Custom URL | No |
|
| Custom URL | No |
|
||||||
|----------------------|-----------------|
|
|----------------------------|----------|
|
||||||
| Saved to Microsoft Account | No |
|
| Saved to Microsoft Account | No |
|
||||||
| Saved to Azure AD | No |
|
| Saved to Azure AD | No |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | Yes |
|
| Saved to file | Yes |
|
||||||
| Creation time | **1PM** |
|
| Creation time | **1PM** |
|
||||||
| Key ID | A564F193 |
|
| Key ID | A564F193 |
|
||||||
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
| Custom URL | No |
|
| Custom URL | No |
|
||||||
|----------------------|-----------------|
|
|----------------------------|----------|
|
||||||
| Saved to Microsoft Account | No |
|
| Saved to Microsoft Account | No |
|
||||||
| Saved to Azure AD | No |
|
| Saved to Azure AD | No |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | No |
|
| Saved to file | No |
|
||||||
| Creation time | **3PM** |
|
| Creation time | **3PM** |
|
||||||
| Key ID | T4521ER5 |
|
| Key ID | T4521ER5 |
|
||||||
|
|
||||||
**Result:** Only the hint for a successfully backed up key is displayed, even if it isn't the most recent key.
|
**Result:** Only the hint for a successfully backed up key is displayed, even if it isn't the most recent key.
|
||||||
|
|
||||||
@ -439,25 +437,25 @@ There are rules governing which hint is shown during the recovery (in the order
|
|||||||
|
|
||||||
#### Example 5 (multiple recovery passwords)
|
#### Example 5 (multiple recovery passwords)
|
||||||
|
|
||||||
| Custom URL | No |
|
| Custom URL | No |
|
||||||
|----------------------|-----------------|
|
|----------------------------|----------|
|
||||||
| Saved to Microsoft Account | Yes |
|
| Saved to Microsoft Account | Yes |
|
||||||
| Saved to Azure AD | Yes |
|
| Saved to Azure AD | Yes |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | No |
|
| Saved to file | No |
|
||||||
| Creation time | **1PM** |
|
| Creation time | **1PM** |
|
||||||
| Key ID | 99631A34 |
|
| Key ID | 99631A34 |
|
||||||
|
|
||||||
| Custom URL | No |
|
| Custom URL | No |
|
||||||
|----------------------|-----------------|
|
|----------------------------|----------|
|
||||||
| Saved to Microsoft Account | No |
|
| Saved to Microsoft Account | No |
|
||||||
| Saved to Azure AD | Yes |
|
| Saved to Azure AD | Yes |
|
||||||
| Saved to Active Directory | No |
|
| Saved to Active Directory | No |
|
||||||
| Printed | No |
|
| Printed | No |
|
||||||
| Saved to file | No |
|
| Saved to file | No |
|
||||||
| Creation time | **3PM** |
|
| Creation time | **3PM** |
|
||||||
| Key ID | 9DF70931 |
|
| Key ID | 9DF70931 |
|
||||||
|
|
||||||
**Result:** The hint for the most recent key is displayed.
|
**Result:** The hint for the most recent key is displayed.
|
||||||
|
|
||||||
@ -484,8 +482,6 @@ The recovery password and be invalidated and reset in two ways:
|
|||||||
|
|
||||||
- **Use `manage-bde.exe`**: `manage-bde.exe` can be used to remove the old recovery password and add a new recovery password. The procedure identifies the command and the syntax for this method.
|
- **Use `manage-bde.exe`**: `manage-bde.exe` can be used to remove the old recovery password and add a new recovery password. The procedure identifies the command and the syntax for this method.
|
||||||
|
|
||||||
- **Run a script**: A script can be run to reset the password without decrypting the volume. The sample script in the procedure illustrates this functionality. The sample script creates a new recovery password and invalidates all other passwords.
|
|
||||||
|
|
||||||
### Resetting a recovery password using `manage-bde.exe`
|
### Resetting a recovery password using `manage-bde.exe`
|
||||||
|
|
||||||
1. Remove the previous recovery password.
|
1. Remove the previous recovery password.
|
||||||
@ -514,466 +510,3 @@ The recovery password and be invalidated and reset in two ways:
|
|||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> The braces `{}` must be included in the ID string.
|
> The braces `{}` must be included in the ID string.
|
||||||
|
|
||||||
### Running the sample recovery password script to reset the recovery passwords
|
|
||||||
|
|
||||||
1. Save the following sample script in a VBScript file. For example:
|
|
||||||
|
|
||||||
`ResetPassword.vbs`.
|
|
||||||
|
|
||||||
2. At the command prompt, enter the following command::
|
|
||||||
|
|
||||||
```cmd
|
|
||||||
cscript.exe ResetPassword.vbs
|
|
||||||
```
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> This sample script is configured to work only for the C volume. If necessary, customize the script to match the volume where the password reset needs to be tested.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> To manage a remote computer, specify the remote computer name rather than the local computer name.
|
|
||||||
|
|
||||||
The following sample VBScript can be used to reset the recovery passwords:
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<details>
|
|
||||||
<summary>Expand to view sample recovery password VBscript to reset the recovery passwords</summary>
|
|
||||||
|
|
||||||
```vb
|
|
||||||
' Target drive letter
|
|
||||||
strDriveLetter = "c:"
|
|
||||||
' Target computer name
|
|
||||||
' Use "." to connect to the local computer
|
|
||||||
strComputerName = "."
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Connect to the BitLocker WMI provider class
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
strConnectionStr = "winmgmts:" _
|
|
||||||
& "{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" _
|
|
||||||
& strComputerName _
|
|
||||||
& "\root\cimv2\Security\MicrosoftVolumeEncryption"
|
|
||||||
|
|
||||||
|
|
||||||
On Error Resume Next 'handle permission errors
|
|
||||||
Set objWMIService = GetObject(strConnectionStr)
|
|
||||||
If Err.Number <> 0 Then
|
|
||||||
WScript.Echo "Failed to connect to the BitLocker interface (Error 0x" & Hex(Err.Number) & ")."
|
|
||||||
Wscript.Echo "Ensure that you are running with administrative privileges."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
On Error GoTo 0
|
|
||||||
strQuery = "Select * from Win32_EncryptableVolume where DriveLetter='" & strDriveLetter & "'"
|
|
||||||
Set colTargetVolumes = objWMIService.ExecQuery(strQuery)
|
|
||||||
If colTargetVolumes.Count = 0 Then
|
|
||||||
WScript.Echo "FAILURE: Unable to find BitLocker-capable drive " & strDriveLetter & " on computer " & strComputerName & "."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' there should only be one volume found
|
|
||||||
For Each objFoundVolume in colTargetVolumes
|
|
||||||
set objVolume = objFoundVolume
|
|
||||||
Next
|
|
||||||
' objVolume is now our found BitLocker-capable disk volume
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Perform BitLocker WMI provider functionality
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Add a new recovery password, keeping the ID around so it doesn't get deleted later
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
nRC = objVolume.ProtectKeyWithNumericalPassword("Recovery Password Refreshed By Script", , sNewKeyProtectorID)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: ProtectKeyWithNumericalPassword failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' Removes the other, "stale", recovery passwords
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
nKeyProtectorTypeIn = 3 ' type associated with "Numerical Password" protector
|
|
||||||
nRC = objVolume.GetKeyProtectors(nKeyProtectorTypeIn, aKeyProtectorIDs)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyProtectors failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' Delete those key protectors other than the one we just added.
|
|
||||||
For Each sKeyProtectorID In aKeyProtectorIDs
|
|
||||||
If sKeyProtectorID <> sNewKeyProtectorID Then
|
|
||||||
nRC = objVolume.DeleteKeyProtector(sKeyProtectorID)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: DeleteKeyProtector on ID " & sKeyProtectorID & " failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
Else
|
|
||||||
' no output
|
|
||||||
'WScript.Echo "SUCCESS: Key protector with ID " & sKeyProtectorID & " deleted"
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
WScript.Echo "A new recovery password has been added. Old passwords have been removed."
|
|
||||||
' - some advanced output (hidden)
|
|
||||||
'WScript.Echo ""
|
|
||||||
'WScript.Echo "Type ""manage-bde.exe -protectors -get " & strDriveLetter & " -type recoverypassword"" to view existing passwords."
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Retrieving the BitLocker key package
|
|
||||||
|
|
||||||
Two methods can be used to retrieve the key package as described in [Using Additional Recovery Information](#using-additional-recovery-information):
|
|
||||||
|
|
||||||
- **Export a previously saved key package from AD DS.** Read access is required to BitLocker recovery passwords that are stored in AD DS.
|
|
||||||
|
|
||||||
- **Export a new key package from an unlocked, BitLocker-protected volume.** Local administrator access to the working volume is required before any damage occurred to the volume.
|
|
||||||
|
|
||||||
### Running the sample key package retrieval script that exports all previously saved key packages from AD DS
|
|
||||||
|
|
||||||
The following steps and sample script exports all previously saved key packages from AD DS.
|
|
||||||
|
|
||||||
1. Save the following sample script in a VBScript file. For example: `GetBitLockerKeyPackageADDS.vbs`.
|
|
||||||
|
|
||||||
2. At the command prompt, enter a command similar to the following sample script:
|
|
||||||
|
|
||||||
```cmd
|
|
||||||
cscript.exe GetBitLockerKeyPackageADDS.vbs -?
|
|
||||||
```
|
|
||||||
|
|
||||||
The following sample script can be used to create a VBScript file to retrieve the BitLocker key package from AD DS:
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<details>
|
|
||||||
<summary>Expand to view sample key package retrieval VBscript that exports all previously saved key packages from AD DS</summary>
|
|
||||||
|
|
||||||
```vb
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Usage
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Sub ShowUsage
|
|
||||||
Wscript.Echo "USAGE: GetBitLockerKeyPackageADDS [Path To Save Key Package] [Optional Computer Name]"
|
|
||||||
Wscript.Echo "If no computer name is specified, the local computer is assumed."
|
|
||||||
Wscript.Echo
|
|
||||||
Wscript.Echo "Example: GetBitLockerKeyPackageADDS E:\bitlocker-ad-key-package mycomputer"
|
|
||||||
WScript.Quit
|
|
||||||
End Sub
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Parse Arguments
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Set args = WScript.Arguments
|
|
||||||
Select Case args.Count
|
|
||||||
Case 1
|
|
||||||
If args(0) = "/?" Or args(0) = "-?" Then
|
|
||||||
ShowUsage
|
|
||||||
Else
|
|
||||||
strFilePath = args(0)
|
|
||||||
' Get the name of the local computer
|
|
||||||
Set objNetwork = CreateObject("WScript.Network")
|
|
||||||
strComputerName = objNetwork.ComputerName
|
|
||||||
End If
|
|
||||||
|
|
||||||
Case 2
|
|
||||||
If args(0) = "/?" Or args(0) = "-?" Then
|
|
||||||
ShowUsage
|
|
||||||
Else
|
|
||||||
strFilePath = args(0)
|
|
||||||
strComputerName = args(1)
|
|
||||||
End If
|
|
||||||
Case Else
|
|
||||||
ShowUsage
|
|
||||||
End Select
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Get path to Active Directory computer object associated with the computer name
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Function GetStrPathToComputer(strComputerName)
|
|
||||||
' Uses the global catalog to find the computer in the forest
|
|
||||||
' Search also includes deleted computers in the tombstone
|
|
||||||
Set objRootLDAP = GetObject("LDAP://rootDSE")
|
|
||||||
namingContext = objRootLDAP.Get("defaultNamingContext") ' e.g. string dc=fabrikam,dc=com
|
|
||||||
strBase = "<GC://" & namingContext & ">"
|
|
||||||
|
|
||||||
Set objConnection = CreateObject("ADODB.Connection")
|
|
||||||
Set objCommand = CreateObject("ADODB.Command")
|
|
||||||
objConnection.Provider = "ADsDSOOBject"
|
|
||||||
objConnection.Open "Active Directory Provider"
|
|
||||||
Set objCommand.ActiveConnection = objConnection
|
|
||||||
strFilter = "(&(objectCategory=Computer)(cn=" & strComputerName & "))"
|
|
||||||
strQuery = strBase & ";" & strFilter & ";distinguishedName;subtree"
|
|
||||||
objCommand.CommandText = strQuery
|
|
||||||
objCommand.Properties("Page Size") = 100
|
|
||||||
objCommand.Properties("Timeout") = 100
|
|
||||||
objCommand.Properties("Cache Results") = False
|
|
||||||
' Enumerate all objects found.
|
|
||||||
Set objRecordSet = objCommand.Execute
|
|
||||||
If objRecordSet.EOF Then
|
|
||||||
WScript.echo "The computer name '" & strComputerName & "' cannot be found."
|
|
||||||
WScript.Quit 1
|
|
||||||
End If
|
|
||||||
' Found object matching name
|
|
||||||
Do Until objRecordSet.EOF
|
|
||||||
dnFound = objRecordSet.Fields("distinguishedName")
|
|
||||||
GetStrPathToComputer = "LDAP://" & dnFound
|
|
||||||
objRecordSet.MoveNext
|
|
||||||
Loop
|
|
||||||
' Clean up.
|
|
||||||
Set objConnection = Nothing
|
|
||||||
Set objCommand = Nothing
|
|
||||||
Set objRecordSet = Nothing
|
|
||||||
End Function
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Securely access the Active Directory computer object using Kerberos
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Set objDSO = GetObject("LDAP:")
|
|
||||||
strPathToComputer = GetStrPathToComputer(strComputerName)
|
|
||||||
WScript.Echo "Accessing object: " + strPathToComputer
|
|
||||||
Const ADS_SECURE_AUTHENTICATION = 1
|
|
||||||
Const ADS_USE_SEALING = 64 '0x40
|
|
||||||
Const ADS_USE_SIGNING = 128 '0x80
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Get all BitLocker recovery information from the Active Directory computer object
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Get all the recovery information child objects of the computer object
|
|
||||||
Set objFveInfos = objDSO.OpenDSObject(strPathToComputer, vbNullString, vbNullString, _
|
|
||||||
ADS_SECURE_AUTHENTICATION + ADS_USE_SEALING + ADS_USE_SIGNING)
|
|
||||||
objFveInfos.Filter = Array("msFVE-RecoveryInformation")
|
|
||||||
' Iterate through each recovery information object and saves any existing key packages
|
|
||||||
nCount = 1
|
|
||||||
strFilePathCurrent = strFilePath & nCount
|
|
||||||
For Each objFveInfo in objFveInfos
|
|
||||||
strName = objFveInfo.Get("name")
|
|
||||||
strRecoveryPassword = objFveInfo.Get("msFVE-RecoveryPassword")
|
|
||||||
strKeyPackage = objFveInfo.Get("msFVE-KeyPackage")
|
|
||||||
WScript.echo
|
|
||||||
WScript.echo "Recovery Object Name: " + strName
|
|
||||||
WScript.echo "Recovery Password: " + strRecoveryPassword
|
|
||||||
' Validate file path
|
|
||||||
Set fso = CreateObject("Scripting.FileSystemObject")
|
|
||||||
If (fso.FileExists(strFilePathCurrent)) Then
|
|
||||||
WScript.Echo "The file " & strFilePathCurrent & " already exists. Please use a different path."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' Save binary data to the file
|
|
||||||
SaveBinaryDataText strFilePathCurrent, strKeyPackage
|
|
||||||
|
|
||||||
WScript.echo "Related key package successfully saved to " + strFilePathCurrent
|
|
||||||
' Update next file path using base name
|
|
||||||
nCount = nCount + 1
|
|
||||||
strFilePathCurrent = strFilePath & nCount
|
|
||||||
Next
|
|
||||||
'----------------------------------------------------------------------------------------
|
|
||||||
' Utility functions to save binary data
|
|
||||||
'----------------------------------------------------------------------------------------
|
|
||||||
Function SaveBinaryDataText(FileName, ByteArray)
|
|
||||||
'Create FileSystemObject object
|
|
||||||
Dim FS: Set FS = CreateObject("Scripting.FileSystemObject")
|
|
||||||
|
|
||||||
'Create text stream object
|
|
||||||
Dim TextStream
|
|
||||||
Set TextStream = FS.CreateTextFile(FileName)
|
|
||||||
|
|
||||||
'Convert binary data To text And write them To the file
|
|
||||||
TextStream.Write BinaryToString(ByteArray)
|
|
||||||
End Function
|
|
||||||
Function BinaryToString(Binary)
|
|
||||||
Dim I, S
|
|
||||||
For I = 1 To LenB(Binary)
|
|
||||||
S = S & Chr(AscB(MidB(Binary, I, 1)))
|
|
||||||
Next
|
|
||||||
BinaryToString = S
|
|
||||||
End Function
|
|
||||||
WScript.Quit
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Running the sample key package retrieval script that exports a new key package from an unlocked, encrypted volume
|
|
||||||
|
|
||||||
The following steps and sample script exports a new key package from an unlocked, encrypted volume.
|
|
||||||
|
|
||||||
1. Save the following sample script in a VBScript file. For example: `GetBitLockerKeyPackage.vbs`
|
|
||||||
|
|
||||||
2. Open an administrator command prompt, and then enter a command similar to the following sample script:
|
|
||||||
|
|
||||||
```cmd
|
|
||||||
cscript.exe GetBitLockerKeyPackage.vbs -?
|
|
||||||
```
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<details>
|
|
||||||
<summary>Expand to view sample VBscript that exports a new key package from an unlocked, encrypted volume</summary>
|
|
||||||
|
|
||||||
```vb
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Usage
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Sub ShowUsage
|
|
||||||
Wscript.Echo "USAGE: GetBitLockerKeyPackage [VolumeLetter/DriveLetter:] [Path To Save Key Package]"
|
|
||||||
Wscript.Echo
|
|
||||||
Wscript.Echo "Example: GetBitLockerKeyPackage C: E:\bitlocker-backup-key-package"
|
|
||||||
WScript.Quit
|
|
||||||
End Sub
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Parse Arguments
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
Set args = WScript.Arguments
|
|
||||||
Select Case args.Count
|
|
||||||
Case 2
|
|
||||||
If args(0) = "/?" Or args(0) = "-?" Then
|
|
||||||
ShowUsage
|
|
||||||
Else
|
|
||||||
strDriveLetter = args(0)
|
|
||||||
strFilePath = args(1)
|
|
||||||
End If
|
|
||||||
Case Else
|
|
||||||
ShowUsage
|
|
||||||
End Select
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Other Inputs
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Target computer name
|
|
||||||
' Use "." to connect to the local computer
|
|
||||||
strComputerName = "."
|
|
||||||
' Default key protector ID to use. Specify "" to let the script choose.
|
|
||||||
strDefaultKeyProtectorID = ""
|
|
||||||
' strDefaultKeyProtectorID = "{001298E0-870E-4BA0-A2FF-FC74758D5720}" ' sample
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Connect to the BitLocker WMI provider class
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
strConnectionStr = "winmgmts:" _
|
|
||||||
& "{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" _
|
|
||||||
& strComputerName _
|
|
||||||
& "\root\cimv2\Security\MicrosoftVolumeEncryption"
|
|
||||||
|
|
||||||
|
|
||||||
On Error Resume Next 'handle permission errors
|
|
||||||
Set objWMIService = GetObject(strConnectionStr)
|
|
||||||
If Err.Number <> 0 Then
|
|
||||||
WScript.Echo "Failed to connect to the BitLocker interface (Error 0x" & Hex(Err.Number) & ")."
|
|
||||||
Wscript.Echo "Ensure that you are running with administrative privileges."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
On Error GoTo 0
|
|
||||||
strQuery = "Select * from Win32_EncryptableVolume where DriveLetter='" & strDriveLetter & "'"
|
|
||||||
Set colTargetVolumes = objWMIService.ExecQuery(strQuery)
|
|
||||||
If colTargetVolumes.Count = 0 Then
|
|
||||||
WScript.Echo "FAILURE: Unable to find BitLocker-capable drive " & strDriveLetter & " on computer " & strComputerName & "."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' there should only be one volume found
|
|
||||||
For Each objFoundVolume in colTargetVolumes
|
|
||||||
set objVolume = objFoundVolume
|
|
||||||
Next
|
|
||||||
' objVolume is now our found BitLocker-capable disk volume
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Perform BitLocker WMI provider functionality
|
|
||||||
' --------------------------------------------------------------------------------
|
|
||||||
' Collect all possible valid key protector ID's that can be used to get the package
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
nNumericalKeyProtectorType = 3 ' type associated with "Numerical Password" protector
|
|
||||||
nRC = objVolume.GetKeyProtectors(nNumericalKeyProtectorType, aNumericalKeyProtectorIDs)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyProtectors failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
nExternalKeyProtectorType = 2 ' type associated with "External Key" protector
|
|
||||||
nRC = objVolume.GetKeyProtectors(nExternalKeyProtectorType, aExternalKeyProtectorIDs)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyProtectors failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' Get first key protector of the type "Numerical Password" or "External Key", if any
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
if strDefaultKeyProtectorID = "" Then
|
|
||||||
' Save first numerical password, if exists
|
|
||||||
If UBound(aNumericalKeyProtectorIDs) <> -1 Then
|
|
||||||
strDefaultKeyProtectorID = aNumericalKeyProtectorIDs(0)
|
|
||||||
End If
|
|
||||||
' No numerical passwords exist, save the first external key
|
|
||||||
If strDefaultKeyProtectorID = "" and UBound(aExternalKeyProtectorIDs) <> -1 Then
|
|
||||||
strDefaultKeyProtectorID = aExternalKeyProtectorIDs(0)
|
|
||||||
End If
|
|
||||||
' Fail case: no recovery key protectors exist.
|
|
||||||
If strDefaultKeyProtectorID = "" Then
|
|
||||||
WScript.Echo "FAILURE: Cannot create backup key package because no recovery passwords or recovery keys exist. Check that BitLocker protection is on for this drive."
|
|
||||||
WScript.Echo "For help adding recovery passwords or recovery keys, enter ""manage-bde.exe -protectors -add -?""."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
' Get some information about the chosen key protector ID
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
' is the type valid?
|
|
||||||
nRC = objVolume.GetKeyProtectorType(strDefaultKeyProtectorID, nDefaultKeyProtectorType)
|
|
||||||
If Hex(nRC) = "80070057" Then
|
|
||||||
WScript.Echo "The key protector ID " & strDefaultKeyProtectorID & " is not valid."
|
|
||||||
WScript.Echo "This ID value may have been provided by the script writer."
|
|
||||||
ElseIf nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyProtectorType failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' what's a string that can be used to describe it?
|
|
||||||
strDefaultKeyProtectorType = ""
|
|
||||||
Select Case nDefaultKeyProtectorType
|
|
||||||
Case nNumericalKeyProtectorType
|
|
||||||
strDefaultKeyProtectorType = "recovery password"
|
|
||||||
Case nExternalKeyProtectorType
|
|
||||||
strDefaultKeyProtectorType = "recovery key"
|
|
||||||
Case Else
|
|
||||||
WScript.Echo "The key protector ID " & strDefaultKeyProtectorID & " does not refer to a valid recovery password or recovery key."
|
|
||||||
WScript.Echo "This ID value may have been provided by the script writer."
|
|
||||||
End Select
|
|
||||||
' Save the backup key package using the chosen key protector ID
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
nRC = objVolume.GetKeyPackage(strDefaultKeyProtectorID, oKeyPackage)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyPackage failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
' Validate file path
|
|
||||||
Set fso = CreateObject("Scripting.FileSystemObject")
|
|
||||||
If (fso.FileExists(strFilePath)) Then
|
|
||||||
WScript.Echo "The file " & strFilePath & " already exists. Please use a different path."
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
Dim oKeyPackageByte, bKeyPackage
|
|
||||||
For Each oKeyPackageByte in oKeyPackage
|
|
||||||
'WScript.echo "key package byte: " & oKeyPackageByte
|
|
||||||
bKeyPackage = bKeyPackage & ChrB(oKeyPackageByte)
|
|
||||||
Next
|
|
||||||
' Save binary data to the file
|
|
||||||
SaveBinaryDataText strFilePath, bKeyPackage
|
|
||||||
' Display helpful information
|
|
||||||
' ----------------------------------------------------------------------------------
|
|
||||||
WScript.Echo "The backup key package has been saved to " & strFilePath & "."
|
|
||||||
WScript.Echo "IMPORTANT: To use this key package, the " & strDefaultKeyProtectorType & " must also be saved."
|
|
||||||
' Display the recovery password or a note about saving the recovery key file
|
|
||||||
If nDefaultKeyProtectorType = nNumericalKeyProtectorType Then
|
|
||||||
nRC = objVolume.GetKeyProtectorNumericalPassword(strDefaultKeyProtectorID, sNumericalPassword)
|
|
||||||
If nRC <> 0 Then
|
|
||||||
WScript.Echo "FAILURE: GetKeyProtectorNumericalPassword failed with return code 0x" & Hex(nRC)
|
|
||||||
WScript.Quit -1
|
|
||||||
End If
|
|
||||||
WScript.Echo "Save this recovery password: " & sNumericalPassword
|
|
||||||
ElseIf nDefaultKeyProtectorType = nExternalKeyProtectorType Then
|
|
||||||
WScript.Echo "The saved key file is named " & strDefaultKeyProtectorID & ".BEK"
|
|
||||||
WScript.Echo "For help re-saving this external key file, enter ""manage-bde.exe -protectors -get -?"""
|
|
||||||
End If
|
|
||||||
'----------------------------------------------------------------------------------------
|
|
||||||
' Utility functions to save binary data
|
|
||||||
'----------------------------------------------------------------------------------------
|
|
||||||
Function SaveBinaryDataText(FileName, ByteArray)
|
|
||||||
'Create FileSystemObject object
|
|
||||||
Dim FS: Set FS = CreateObject("Scripting.FileSystemObject")
|
|
||||||
|
|
||||||
'Create text stream object
|
|
||||||
Dim TextStream
|
|
||||||
Set TextStream = FS.CreateTextFile(FileName)
|
|
||||||
|
|
||||||
'Convert binary data To text And write them To the file
|
|
||||||
TextStream.Write BinaryToString(ByteArray)
|
|
||||||
End Function
|
|
||||||
Function BinaryToString(Binary)
|
|
||||||
Dim I, S
|
|
||||||
For I = 1 To LenB(Binary)
|
|
||||||
S = S & Chr(AscB(MidB(Binary, I, 1)))
|
|
||||||
Next
|
|
||||||
BinaryToString = S
|
|
||||||
End Function
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Related articles
|
|
||||||
|
|
||||||
- [BitLocker overview](index.md)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user