299 lines
9.1 KiB
C
299 lines
9.1 KiB
C
/**
|
|
* @file bcdutil.c
|
|
* @author Paul L. (@am0nsec)
|
|
* @version 1.0
|
|
* @brief Modify boot configuration to enable safe mode, disable recovery and ignore all failure.
|
|
* @details
|
|
* @link https://github.com/am0nsec/vx
|
|
* @copyright This project has been released under the GNU Public License v3 license.
|
|
*/
|
|
#ifndef __BCDUTIL_H_GUARD__
|
|
#define __BCDUTIL_H_GUARD__
|
|
|
|
#pragma comment(lib, "ntdll")
|
|
|
|
#include <Windows.h>
|
|
#include <winternl.h>
|
|
#include <stdio.h>
|
|
|
|
/**
|
|
* @brief GUID of the Windows Boot Manager Configuration within the Windows Registry: 9DEA862C-5CDD-4E70-ACC1-F32B344D4795
|
|
*/
|
|
static CONST GUID GUID_WINDOWS_BOOTMGR = { 0x9DEA862C, 0x5CDD, 0x4E70, {0xAC, 0xC1, 0xF3, 0x2B, 0x34, 0x4D, 0x47, 0x95} };
|
|
|
|
// Taken from https://www.geoffchappell.com/notes/windows/boot/bcd/elements.htm?tx=27
|
|
|
|
#define GUID_WINDOWS_BOOTMGR L"{9DEA862C-5CDD-4E70-ACC1-F32B344D4795}"
|
|
#define BCD_ELEMENTS L"Elements"
|
|
#define BCD_ELEMENT L"Element"
|
|
|
|
#define BCDE_BOOTMGR_TYPE_DEFAULT_OBJECT L"23000003"
|
|
#define BCDE_OSLOADER_TYPE_SAFEBOOT L"25000080"
|
|
#define BCDE_LIBRARY_TYPE_AUTO_RECOVERY_ENABLED L"16000009"
|
|
#define BCDE_OSLOADER_TYPE_BOOT_STATUS_POLICY L"250000E0"
|
|
|
|
#define STATUS_SUCCESS 0x00000000
|
|
#define STATUS_UNSUCCESSFUL 0xC0000001
|
|
#define STATUS_INTERNAL_ERROR 0xC00000E5
|
|
#define STATUS_BUFFER_TOO_SMALL 0xC0000023
|
|
#define STATUS_NO_MORE_ENTRIES 0x8000001A
|
|
#define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034
|
|
|
|
#define RETURN_ON_ERROR(ex) \
|
|
if (!NT_SUCCESS(ex)) { return STATUS_UNSUCCESSFUL; }
|
|
|
|
#define EXIT_ON_ERROR(ex) \
|
|
if (!NT_SUCCESS(ex)) { return EXIT_FAILURE; }
|
|
|
|
#define EXIT_ON_ERROREX(ex, code) \
|
|
if (ex != code) { return EXIT_FAILURE; }
|
|
|
|
typedef enum _KEY_INFORMATION_CLASS {
|
|
KeyBasicInformation,
|
|
KeyNodeInformation,
|
|
KeyFullInformation,
|
|
KeyNameInformation,
|
|
KeyCachedInformation,
|
|
KeyFlagsInformation,
|
|
KeyVirtualizationInformation,
|
|
KeyHandleTagsInformation,
|
|
KeyTrustInformation,
|
|
KeyLayerInformation,
|
|
MaxKeyInfoClass
|
|
} KEY_INFORMATION_CLASS;
|
|
|
|
typedef enum _KEY_VALUE_INFORMATION_CLASS {
|
|
KeyValueBasicInformation,
|
|
KeyValueFullInformation,
|
|
KeyValuePartialInformation,
|
|
KeyValueFullInformationAlign64,
|
|
KeyValuePartialInformationAlign64,
|
|
KeyValueLayerInformation,
|
|
MaxKeyValueInfoClass
|
|
} KEY_VALUE_INFORMATION_CLASS;
|
|
|
|
typedef struct _KEY_BASIC_INFORMATION {
|
|
LARGE_INTEGER LastWriteTime;
|
|
ULONG TitleIndex;
|
|
ULONG NameLength;
|
|
WCHAR Name[1];
|
|
} KEY_BASIC_INFORMATION, * PKEY_BASIC_INFORMATION;
|
|
|
|
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
|
|
ULONG TitleIndex;
|
|
ULONG Type;
|
|
ULONG DataLength;
|
|
UCHAR Data[1];
|
|
} KEY_VALUE_PARTIAL_INFORMATION, * PKEY_VALUE_PARTIAL_INFORMATION;
|
|
|
|
typedef struct _SECURITY_DESCRIPTOREX {
|
|
UCHAR Revision;
|
|
UCHAR Sbz1;
|
|
WORD Control;
|
|
PVOID Owner;
|
|
PVOID Group;
|
|
PACL Sacl;
|
|
PACL Dacl;
|
|
} SECURITY_DESCRIPTOREX, * PSECURITY_DESCRIPTOREX;
|
|
|
|
|
|
extern NTSTATUS NtOpenKey(
|
|
_Out_ PHANDLE KeyHandle,
|
|
_In_ ACCESS_MASK DesiredAccess,
|
|
_In_ POBJECT_ATTRIBUTES ObjectAttributes
|
|
);
|
|
|
|
|
|
extern NTSTATUS NtQueryValueKey(
|
|
_In_ HANDLE KeyHandle,
|
|
_In_ PUNICODE_STRING ValueName,
|
|
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
_Out_ PVOID KeyValueInformation,
|
|
_In_ ULONG Length,
|
|
_Out_ PULONG ResultLength
|
|
);
|
|
|
|
|
|
extern NTSTATUS NtCreateKey(
|
|
_Out_ PHANDLE KeyHandle,
|
|
_In_ ACCESS_MASK DesiredAccess,
|
|
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
|
|
_Out_ ULONG TitleIndex,
|
|
_In_opt_ PUNICODE_STRING Class,
|
|
_In_ ULONG CreateOptions,
|
|
_Out_opt_ PULONG Disposition
|
|
);
|
|
|
|
|
|
extern NTSTATUS NtEnumerateKey(
|
|
_In_ HANDLE KeyHandle,
|
|
_In_ ULONG Index,
|
|
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
|
|
_Out_ PVOID KeyInformation,
|
|
_In_ ULONG Length,
|
|
_Out_ PULONG ResultLength
|
|
);
|
|
|
|
|
|
extern NTSTATUS NtOpenMutant(
|
|
_Out_ PHANDLE MutantHandle,
|
|
_In_ ACCESS_MASK DesiredAccess,
|
|
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
|
|
_In_ BOOLEAN InitialOwner
|
|
);
|
|
|
|
|
|
extern NTSTATUS NtSetValueKey(
|
|
_In_ HANDLE KeyHandle,
|
|
_In_ PUNICODE_STRING ValueName,
|
|
_In_opt_ ULONG TitleIndex,
|
|
_In_ ULONG Type,
|
|
_In_ PVOID Data,
|
|
_In_ ULONG DataSize
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Get handle to the default Windows Boot Object.
|
|
* @param phWindowsBootMgrDefaultObj Pointer to an handle.
|
|
* @return Whether an handle has been successfully retrieved.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdGetDefaultBootObject(
|
|
_Out_ PHKEY phWindowsBootMgrDefaultObj
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Modify boot configuration.
|
|
* @param phKey Pointer to an handle of the Windows default boot object.
|
|
* @param wszKey Name of the configuration to change.
|
|
* @param pData Pointer to the data of the value.
|
|
* @param ulData Size of the data for the value.
|
|
* @return Whether boot configuration has been modified.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdModifyBootConfiguration(
|
|
_In_ CONST PHKEY phKey,
|
|
_In_ CONST LPWSTR wszKey,
|
|
_In_ LPVOID pData,
|
|
_In_ ULONG ulData
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Acquire an handle to the BCD synchronisation mutant.
|
|
* @param phHandle Pointer to an handle.
|
|
* @return Whether an handle to the BCD synchronisation mutant has been acquired.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdAcquireSyncMutant(
|
|
_Out_ PHANDLE phHandle
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Open an HANDLE to a registry object by name.
|
|
* @param wszKeyName The Unicode name of the registry object.
|
|
* @param AccessMask The desired access mask.
|
|
* @param phDirectory Pointer to a parent object within the object manager namespace.
|
|
* @param phKey Pointer to the HANDLE if found and successfully opened.
|
|
* @return Whether the HANDLE has been open.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdOpenKeyByName(
|
|
_In_ CONST LPWSTR wszKeyName,
|
|
_In_ ACCESS_MASK AccessMask,
|
|
_In_ PHANDLE phDirectory,
|
|
_Out_ PHKEY phKey
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Find a sub key for a given pattern.
|
|
* @param phKey Pointer to the key to search from.
|
|
* @param wszPattern The pattern to find (e.g., BCD).
|
|
* @param dwPatternLength Length of the pattern (e.g., 3).
|
|
* @param wszSubKeyName Pointer to the name of the sub-key once found.
|
|
* @param pdwSubKeyNameLength Pointer to the length of the sub-key once found.
|
|
* @return Whether the sub-key has been found.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdpGetSubKeyByPattern(
|
|
_In_ CONST PHKEY phKey,
|
|
_In_ CONST LPWSTR wszPattern,
|
|
_In_ CONST DWORD dwPatternLength,
|
|
_Out_ LPWSTR * wszSubKeyName,
|
|
_Out_ PDWORD pdwSubKeyNameLength
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Get the value of a Windows registry key by name.
|
|
* @param wszValueName The Unicode name of the value to retrieve.
|
|
* @param phKey Pointer to an handle of a Windows Registry key.
|
|
* @param dwType Type of data to retreive.
|
|
* @param ppData Pointer to a buffer.
|
|
* @param pdwData Poitner to the size of the buffer that will be returned.
|
|
* @return Whether the value has been successfully retrieved.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdpQueryValueByName(
|
|
_In_ CONST LPWSTR wszValueName,
|
|
_In_ PHKEY phKey,
|
|
_In_ DWORD dwType,
|
|
_Out_ LPVOID * ppData,
|
|
_Out_ DWORD * pdwData
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Create a new windows registry key.
|
|
* @param wszKeyName The Unicode name of the key to create.
|
|
* @param DesiredAccess Desired access.
|
|
* @param dwType Type of data to retreive.
|
|
* @param phDirectory Pointer to a parent object within the object manager namespace.
|
|
* @param phKey Pointer to an handle of the newly created key.
|
|
* @return Whether the key has been created.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdpCreateKey(
|
|
_In_ CONST LPWSTR wszKeyName,
|
|
_In_ ACCESS_MASK DesiredAccess,
|
|
_In_ PHANDLE phDirectory,
|
|
_Out_ PHANDLE phKey
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Set a new value to a windows registry key
|
|
* @param wszKeyName The Unicode name of the value to create/modify.
|
|
* @param phKey Handle to a windows registry key.
|
|
* @param pData Pointer to the data of the value.
|
|
* @param ulData Size of the data of the value.
|
|
* @return Whether the value has been successfully created or modified.
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdpSetValue(
|
|
_In_ CONST LPWSTR wszValue,
|
|
_In_ PHANDLE phKey,
|
|
_In_ PVOID pData,
|
|
_In_ ULONG ulData
|
|
);
|
|
|
|
|
|
/**
|
|
* @brief Set a new value to a windows registry key
|
|
* @param phKey Handle to a windows registry key.
|
|
* @param dwPrivileges Desried new privileges.
|
|
* @return Whether the new privileges have been assigned
|
|
*/
|
|
_Success_(return == S_OK) _Must_inspect_result_ NTSTATUS
|
|
BcdpChangeObjectPermission(
|
|
_In_ CONST PHANDLE phKey,
|
|
_In_ DWORD dwPrivileges
|
|
);
|
|
|
|
|
|
#endif // !__BCDUTIL_H_GUARD__
|