Archive for the ‘ WMI ’ Category

How to change BitLocker recovery password with vbScript?

Related to my last post about how to change BitLocker recovery password from an elevated command prompt here is how you can achieve the same result with vbScript and WMI. This script is from Microsoft TechNet: BitLocker Drive Encryption Operations Guide: Recovering Encrypted Volumes with AD DS.

' 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 -protectors -get " & strDriveLetter & " -type recoverypassword"" to view existing passwords."

How to access WMI namespaces on remote computers that require encryption?

When you have a look at my vbscript bitlocker post and try to use it on remote machines you may not get any results but an application eventlog entry similar to this one here:

Event Source: WinMgmt
Event ID: 5605
Access to the [...] namespace was denied. The namespace is marked with RequiresEncryption but the client connection was attempted with an authentication level below Pkt_Privacy. Re try the connection using Pkt_Privacy authentication level.

When using security related namespaces on remote machines you need to connect to wmi using a higher authentication level:

strComputer = "remotemachine"
Set objWMIService = GetObject("winmgmts:{authenticationLevel=pktPrivacy}\\" & strComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption")

You can use one of these authentication levels:

Name/value Description
WbemAuthenticationLevelDefault

0

Moniker: Default

WMI uses the default Windows Authentication setting. This is the recommended setting that allows WMI to negotiate to the level required by the server returning data. However, if the namespace requires encryption, use WbemAuthenticationLevelPktPrivacy.

WbemAuthenticationLevelNone

1

Moniker: None

Uses no authentication.

WbemAuthenticationLevelConnect

2

Moniker: Connect

Authenticates the credentials of the client only when the client establishes a relationship with the server.

WbemAuthenticationLevelCall

3

Call

Authenticates only at the beginning of each call when the server receives the request.

WbemAuthenticationLevelPkt

4

Moniker: Pkt

Authenticates that all data received is from the expected client.

WbemAuthenticationLevelPktIntegrity

5

Moniker: PktIntegrity

Authenticates and verifies that none of the data transferred between client and server has been modified.

WbemAuthenticationLevelPktPrivacy

6

Moniker: PktPrivacy

Authenticates all previous impersonation levels and encrypts the argument value of each remote procedure call. Use this setting if the namespace to which you are connecting requires an encrypted connection.

Source: MSDN Library

How to get some information on Bitlocker using VBScript and WMI?

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_EncryptableVolume",,48)

Dim arEncryptionMethod
arEncryptionMethod = Array("None", "AES 128 With Diffuser", "AES 256 With Diffuser", "AES 128", "AES 256")

Dim arProtectionStatus
arProtectionStatus = Array("Protection Off", "Protection On", "Protection Unknown")

Dim arConversionStatus
arConversionStatus = Array("Fully Decrypted", "Fully Encrypted", "Encryption In Progress", "Decryption In Progress", "Encryption Paused", "Decryption Paused")

Dim arLockStatus
arLockStatus = Array("Unlocked", "Locked")

For Each objItem in colItems
  Dim EncryptionMethod
  Dim ProtectionStatus
  Dim ConversionStatus
  Dim EncryptionPercentage 'Percentage of the volume that is encrypted
  Dim VolumeKeyProtectorID
  Dim LockStatus

  objItem.GetEncryptionMethod EncryptionMethod
  objItem.GetProtectionStatus ProtectionStatus
  objItem.GetConversionStatus ConversionStatus, EncryptionPercentage
  objItem.GetKeyProtectors 0,VolumeKeyProtectorID
  objItem.GetLockStatus LockStatus

  WScript.Echo "DeviceID: " & objItem.DeviceID
  Wscript.Echo "DriveLetter: " & objItem.DriveLetter
  Wscript.Echo "EncryptionMethod: " & arEncryptionMethod(EncryptionMethod)
  Wscript.Echo "ProtectionStatus: " & arProtectionStatus(ProtectionStatus)
  Wscript.Echo "ConversionStatus: " & arConversionStatus(ConversionStatus)
  Wscript.Echo "EncryptionPercentage: " & EncryptionPercentage & "%"
  Wscript.Echo "LockStatus: " & arLockStatus(LockStatus)

  For Each objId in VolumeKeyProtectorID
    Dim VolumeKeyProtectorFriendlyName
    objItem.GetKeyProtectorFriendlyName objId, VolumeKeyProtectorFriendlyName
    If VolumeKeyProtectorFriendlyName <> "" Then
      Wscript.Echo "KeyProtectors: " & VolumeKeyProtectorFriendlyName
    End If
  Next
Next

Documentation for functions, methods and properties used in this post: