Disabling Bitlocker Encryption using undocumented COM objects
This requires administrative privileges. However, it is still interesting. It should also be noted that this API uses FVEUI.DLL, which internally calls FVEAPI.DLL, which eventually boils down to NtDeviceIoControl. It would be cool if someone implemented this using nothing but IO controls.
Earlier I posted I thought I could achieve this without requiring administrative privileges. I was incorrect.
There is some pretty interesting stuff in this API set. I think some cool stuff can be done with this.
#include <Windows.h>
#include <objbase.h>
#include <objidl.h>
enum FveMethodId
{
DoGetProcessId = 779,
DoFveDisableAuthentication = 259,
DoCheckForAdminRights = 519,
DoImplicitPauseConversion = 784,
DoPauseConversion = 521,
DoResumeConversion = 528,
DoHasAutoUnlockedVolumes = 523,
DoEnableAutoUnlock = 768,
DoDisableAutoUnlock = 786,
DoAttemptAutoUnlock = 777,
DoUnlockWithPassword = 769,
DoUnlockWithKey = 770,
DoUnlockWithPassphrase = 776,
DoUnlockWithSmartCard = 778,
DoIsAutoUnlockEnabled = 771,
DoGetVolumeDescription = 772,
DoGetVolumePasswordId = 773,
DoDecrypt = 775,
DoLaunchWizard = 780,
DoLaunchUpdate = 781,
DoServiceDiscoveryVolume = 782,
DoNeedsDiscoveryVolumeUpdate = 783,
DoRemovePassphrase = 785,
DoAddSmartCard = 787,
DoRemoveSmartCard = 788,
DoUpgradeVolume = 789,
DoTurnOnDeviceEncryption = 790,
DoTurnOffDeviceEncryption = 791,
DoGetPasswordBackupTypes = 792
};
VOID ImplZeroMemory2(_Inout_ PVOID Destination, _In_ SIZE_T Size)
{
PCHAR Pointer = (PCHAR)Destination;
PCHAR End = Pointer + Size;
for (;;)
{
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
}
}
DWORD Win32FromHResult(_In_ HRESULT Result)
{
if ((Result & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
return HRESULT_CODE(Result);
if (Result == S_OK)
return ERROR_SUCCESS;
return ERROR_CAN_NOT_COMPLETE;
}
HRESULT FveComTurnOffDeviceEncryption(IDispatch* Dispatch, HRESULT* DisableResult)
{
HRESULT Result = S_OK;
DISPPARAMS Parameters = { 0 };
Parameters.cArgs = 0;
Parameters.cNamedArgs = 0;
Parameters.rgdispidNamedArgs = NULL;
Parameters.rgvarg = NULL;
VARIANT Variant; VariantInit(&Variant);
Result = Dispatch->Invoke(DoTurnOffDeviceEncryption, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &Variant, NULL, NULL);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
if (Variant.vt == VT_UI4)
*DisableResult = (DWORD)Variant.ulVal;
else
Result = E_FAIL;
EXIT_ROUTINE:
VariantClear(&Variant);
return Result;
}
INT main(VOID)
{
HRESULT Result = S_OK;
HRESULT DisableResult = 0;
WCHAR ElevationMonikerString[77] = L"Elevation:Administrator!new:{A7A63E5C-3877-4840-8727-C1EA9D7A4D50}";
BIND_OPTS3 BindOptions;
#pragma warning( push )
#pragma warning( disable : 6001 )
ImplZeroMemory2(&BindOptions, sizeof(BindOptions));
#pragma warning( pop )
BindOptions.cbStruct = sizeof(BIND_OPTS3);
BindOptions.dwClassContext = CLSCTX_LOCAL_SERVER;
IDispatch* Dispatch = NULL;
Result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(Result))
return Win32FromHResult(Result);
Result = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CoGetObject(ElevationMonikerString, &BindOptions, IID_IDispatch, (PVOID*)&Dispatch);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = FveComTurnOffDeviceEncryption(Dispatch, &DisableResult);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
EXIT_ROUTINE:
if (Dispatch)
Dispatch->Release();
CoUninitialize();
return ERROR_SUCCESS;
}Last updated