VXUG-Papers/Win64.VirTool.BCDEdit/bcdutil.h

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__