Jump to content
Sign in to follow this  
tlman12

Unlock bitlocker drive with AutoIt/VBScript

Recommended Posts

tlman12

I'm trying to script out the unlocking of a bitlocker drive using a DRA certificate. I'm attempting to use the WMI Method UnlockWithCertificateFile and I can't for the life of me figure out what i'm doing wrong or even find an example.

I know the certificate and pin work because i can manually unlock the drive using manage-bde -unlock....

when i run my script i get a return value of -2146885623 wich i've looked up to be -2146885623, "Cannot find the requested object."

i'm not sure what object its talking about.

here is the code started with (minus the pin), its vbscript but i'm getting the same error whether it's vbscript or autoit so i think theres something wrong with my base vbscript code. i cant find any examples online for this method. i generated this script from "WMI Code Creator

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption") 
' Obtain an instance of the the class 
' using a key property value.
Set objShare = objWMIService.Get("Win32_EncryptableVolume.DeviceID='\\?\Volume{a2965903-4af0-11e2-be65-806e6f6e6963}\'")

' Obtain an InParameters object specific
' to the method.
Set objInParam = objShare.Methods_("UnlockWithCertificateFile"). _
    inParameters.SpawnInstance_()


' Add the input parameters.
objInParam.Properties_.Item("PathWithFileName") =  "D:\BitLocker.pfx"
objInParam.Properties_.Item("Pin") =  "PinCode

' Execute the method and obtain the return status.
' The OutParameters object in objOutParams
' is created by the provider.
Set objOutParams = objWMIService.ExecMethod("Win32_EncryptableVolume.DeviceID='\\?\Volume{a2965903-4af0-11e2-be65-806e6f6e6963}\'", "UnlockWithCertificateFile", objInParam)

' List OutParams
Wscript.Echo "Out Parameters: "
Wscript.echo "ReturnValue: " & objOutParams.ReturnValue

has anyone ever used this method or can anyone see something i may be doing wrong? also i'm using the windows 8 commandline recovery option, i'm not sure if that makes a difference because i have tested calling other methods and wmi and scripting seem to be fully implemented.

i did get it to work in vb.net but vb.net has not been implemented in the recover

Share this post


Link to post
Share on other sites
ripdad

Here's a few things that might help you (Not Tested).

;Ref@MSDN:
;http://msdn.microsoft.com/en-us/library/windows/desktop/aa376483(v=vs.85).aspx

Local $oErrorHandler = ObjEvent('AutoIt.Error', '_ObjErrorHandler')



Func _Example($sPath, $sPinCode, $strComputer = '.')

    Local $objWMI, $objShare, $objInParam, $objOutParams

    $objWMI = ObjGet('winmgmts:{ImpersonationLevel=Impersonate,AuthenticationLevel=PktPrivacy,(Debug,Security)}!\\' & _
            $strComputer & '\root\CIMV2\Security\MicrosoftVolumeEncryption')

    ; Obtain an instance of the the class
    ; using a key property value.
    $objShare = $objWMI.Get('Win32_EncryptableVolume.DeviceID="\\?\Volume{a2965903-4af0-11e2-be65-806e6f6e6963}\"')

    ; Obtain an InParameters object specific
    ; to the method.
    $objInParam = $objShare.Methods_('UnlockWithCertificateFile')
    $objInParam.SpawnInstance_()

    ; Add the input parameters.
    $objInParam.Properties_.Item('PathWithFileName') = $sPath; 'D:\BitLocker.pfx' OR D:\\BitLocker.pfx
    $objInParam.Properties_.Item('Pin') = $sPinCode; 'PinCode'

    ; Execute the method and obtain the return status.
    ; The OutParameters object in objOutParams
    ; is created by the provider.
    $objOutParams = objWMI.ExecMethod( _
            'Win32_EncryptableVolume.DeviceID="\\?\Volume{a2965903-4af0-11e2-be65-806e6f6e6963}\"', _
            'UnlockWithCertificateFile', $objInParam)

    ; List OutParams
    ConsoleWrite('Out Parameters ReturnValue: ' & $objOutParams.ReturnValue)
EndFunc

Func _ObjErrorHandler()
    Local $AOE1 = $oErrorHandler.ScriptLine
    Local $AOE2 = Hex($oErrorHandler.Number, 8)
    Local $AOE3 = $oErrorHandler.Description
    Local $AOE4 = $oErrorHandler.WinDescription
    $oErrorHandler.Clear
    Local $eMsg = ''
    If $AOE1 Then $eMsg &= 'Line:' & $AOE1 & ' '
    If $AOE2 Then $eMsg &= '(0x' & $AOE2 & ') '
    If $AOE3 Then $eMsg &= $AOE3 & ' '
    If $AOE4 Then $eMsg &= $AOE4
    MsgBox(8240, 'Object Error', $eMsg)
    Exit
EndFunc

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites
tlman12

 

Here's a few things that might help you (Not Tested).

 

 

Thank you that was exactly the feed back from my script that i needed. I got it to work and cleaned it up a little bit, here is the finished product if anyone is interested. 

the reason i wrote this is because i wanted to be able to distribute my BitLocker DRA cert without distributing a static password. this script works by generating a hashing a set of data retrieved from the computer (common knowledge) that can be generated with minimal knowledge of the PC by a tech with the proper generator. I removed that feature from the script because i can't release exactly how i was doing it. it was based on a hash with a date salt that way it would change constantly. 

this is tested and working in the Windows 8.1 Command Prompt recovery option.

enjoy 

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

;Ref@MSDN:
;http://msdn.microsoft.com/en-us/library/windows/desktop/aa376483(v=vs.85).aspx

Local $oErrorHandler = ObjEvent('AutoIt.Error', '_ObjErrorHandler')

Const $S_OK = 0
Const $UNKNOWN = 1
Const $ERROR_FILE_NOT_FOUND = 2
Const $BITLOCKER_NOT_ACTIVATED = 80310008
Const $FAILED_AUTHENTICATION = 80310027
Const $BITLOCKE_PROTECTOR_NOT_FOUND = 80310033
Const $CERTIFICATE_PRIVATEKEY_AUTH_FAILED = 80310094
Const $CERTIFICATE_NOT_FOUND = 80070002
Const $CERTIFICATE_PIN_INCORRECT = 80092009


#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <GUIConstantsEx.au3>



;~ Changeable Fields
; Instructions,
; Export the BitLocker Drive Recovery Agent certificate (WITH PRIVATE KEY)
; Place it in the same directory as this script before you compile it.
; Change $sPIN below to reflect the pfx password you exported with.
; $sPassword will set a password to run the script, if left blank unlock will occur automatically without any need for a password.

Dim $sPIN = "Secure_Cert_Password" ;Don't forget to change this
Dim $sPassword = "Password to run script"
Dim $sCertName = "BitLocker.pfx" ;Make sure to name your certificate whatever you put here.
FileInstall("BitLocker.pfx",@TempDir & "\BitLocker.pfx",1) ;and change the cert name here
Dim $strComputer = "." ;Possiblity to add remote computer later
;~ No need to change below here


Dim $sDeviceID
$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_EncryptableVolume")
For $objItem in $colItems
    If $objItem.ProtectionStatus > 0 Then
        ClipPut($objitem.DeviceID)
        $sDeviceID = $sDeviceID & "|" & $objItem.DeviceID
    EndIf
Next



If $sDeviceID = "" Then
    MsgBox(64,"Not Encrypted","No BitLocker encrypted drives were found on this computer")
    Exit
Else
    $sDeviceID = StringTrimLeft($sDeviceID,1)
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 325, 105, -1, -1)
    $Label1 = GUICtrlCreateLabel("Pick the drive you would like to unlock", 64, 8, 192, 17)
    $Combo1 = GUICtrlCreateCombo($sDeviceID, 8, 32, 305, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL))
    $Button1 = GUICtrlCreateButton("Ok", 123, 64, 75, 25)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###


    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                Exit
            Case $Button1
                GUISetState(@SW_HIDE)
                $sDeviceID = GUICtrlRead($Combo1)
                If $sPassword <> "" Then $string = InputBox("Password required","Please type the correct password to advance","")
                If $string = $sPassword Then
                    $ret = _UnlockWithCertificateFile(@TempDir & "\" & $sCertName,$sPIN,$sDeviceID)
                    FileDelete(@TempDir & "\" & $sCertName)
                    Switch $ret
                        Case $S_OK
                            MsgBox(64,"Success","Drive should now be unlocked")
                        Case $UNKNOWN
                            MsgBox(16,"Error","An unknown error has occured")
                        Case $ERROR_FILE_NOT_FOUND
                            MsgBox(16,"Error","File Not Found")
                        Case $BITLOCKER_NOT_ACTIVATED
                            MsgBox(16,"Error","BitLocker is not activated on the specified drive")
                        Case $FAILED_AUTHENTICATION
                            MsgBox(16,"Error","Failed Authentication")
                        Case $BITLOCKE_PROTECTOR_NOT_FOUND
                            MsgBox(16,"Error","Specified BitLocker Protector not found")
                        Case $CERTIFICATE_PRIVATEKEY_AUTH_FAILED
                            MsgBox(16,"Error","Certificate Private Key authentication failed")
                        Case $CERTIFICATE_NOT_FOUND
                            MsgBox(16,"Error","Certificate path must be incorrect")
                        Case $CERTIFICATE_PIN_INCORRECT
                            MsgBox(16,"Error","Certificate PIN is incorrect")
                        Case Else
                            MsgBox(16,"Error","An unknown error has occured")
                    EndSwitch
                Else
                    MsgBox(16,"Error","Password is incorrect")
                EndIf
                Exit
        EndSwitch
    WEnd

EndIf




Func _UnlockWithCertificateFile($inPath, $inPinCode, $inDeviceID, $strComputer = '.')

    Local $objWMI, $objShare, $objInParam, $objOutParams

    $objWMI = ObjGet('winmgmts:{ImpersonationLevel=Impersonate,AuthenticationLevel=PktPrivacy,(Debug,Security)}!\\' & _
            $strComputer & '\root\CIMV2\Security\MicrosoftVolumeEncryption')

    ; Obtain an instance of the the class
    ; using a key property value.
    $objShare = $objWMI.Get("Win32_EncryptableVolume.DeviceID='" & $inDeviceID &"'")

    ; Obtain an InParameters object specific
    ; to the method.
    $objInParam = $objShare.Methods_("UnlockWithCertificateFile").inParameters.SpawnInstance_()

    ; Add the input parameters.
    $objInParam.PathWithFileName = $inPath
    $objInParam.Pin = $inPinCode

    ; Execute the method and obtain the return status.
    ; The OutParameters object in objOutParams
    ; is created by the provider.
    $objOutParams = $objShare.ExecMethod_('UnlockWithCertificateFile', $objInParam)

    ; Return OutParams
    Return Hex($objOutParams.ReturnValue)

EndFunc

Func _ObjErrorHandler()
    Local $AOE1 = $oErrorHandler.ScriptLine
    Local $AOE2 = Hex($oErrorHandler.Number, 8)
    Local $AOE3 = $oErrorHandler.Description
    Local $AOE4 = $oErrorHandler.WinDescription
    $oErrorHandler.Clear
    Local $eMsg = ''
    If $AOE1 Then $eMsg &= 'Line:' & $AOE1 & ' '
    If $AOE2 Then $eMsg &= '(0x' & $AOE2 & ') '
    If $AOE3 Then $eMsg &= $AOE3 & ' '
    If $AOE4 Then $eMsg &= $AOE4
    MsgBox(8240, 'Object Error', $eMsg)
    Exit
EndFunc
Edited by tlman12

Share this post


Link to post
Share on other sites
ripdad

Glad you got it working.


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×