❌

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNVISO Labs

Detecting BCD Changes To Inhibit System Recovery

30 May 2022 at 08:00

Introduction

Earlier this year, we observed a rise in malware that inhibits system recovery. This tactic is mostly used by ransomware and wiper malware. One notable example of such malware is “Hermetic wiper”. To inhibit recovery an attacker has many possibilities, one of which is changing the Boot Configuration Database (BCD). This post will dive into the effects of BCD changes applied by such malware, and cover:

  • What is BCD?
  • Effect of changing boot entries.
  • Gather related Telemetry.
  • Derive possible detection opportunities.

What is BCD?

To understand BCD, we need to address the Windows 10 boot process. A detailed description of the entire boot process is provided by Microsoft.

Figure 1: BCD Location In Boot Sequence.

When the host receives power, the firmware loads the Unified Extensible Firmware Interface (UEFI) environment which in turn launches the Windows Boot Manager (WBM) and later hands over execution to the operating system (OS). At some point in the execution chain, the WBM reads the BCD to determine which boot applications need to run and in which order to run them.

The BCD contains “boot entries” that are adjustable. This allows the user to indirectly control the actions of the WBM and as such the boot procedure of the host itself.

Targeted boot entries

As described by MITRE ATT&CK, The following boot entries are most often changed to inhibit system recovery:

  • Bootstatuspolicy
  • Recovery Enabled

BootStatusPolicy and Recovery Enabled

During startup, when a computer with the Windows OS fails to boot twice consecutively, it automatically fails over to the Windows Recovery Environment (WinRE). The OS is aware of the failure, during the boot, as a status flag is set to indicate the OS is booting. The flag gets cleared on successful startup, meaning if the OS fails to boot the flag isn’t reset and when booted once more, the WBM will start WinRE instead of the main OS. The BootStatusPolicy and “Recovery enabled” boot entries determine when/if the boot manager is allowed to transfer control to WinRE.

One of the effects of disabling WinRE is the removal of the “Automatic Repair” function.

Figure 2: Automatic Repair

“Automatic Repair” attempts to diagnose and repair the source of the boot failure. A detailed view of the performed checks is available at “C:\Windows\System32\LogFiles\Srt\Srt Trail. txt”, a summary of the tests is visible below:

Test Performed

Check for updates Event log diagnosis Bugcheck analysis
System disk test Internal state check Setup state check
Disk failure diagnosis Check for installed LCU Registry hives test
Disk metadata test Check for installed driver updates Volume content check
Target OS test Check for pending package install Boot manager diagnosis
Windows boot log diagnosis Boot status test System boot log diagnosis

When the “Automatic Repair” feature repairs the OS, it can remove objects or revert changes related to the issue. Figure 3, shows a Windows user notification stating the recovery feature reverted the recent updates to resolve booting failure.

Figure 3: Windows Prompts The User Of Recovery Actions Performed.

Applying boot entry changes.

Boot entry changes are commonly applied via BCDedit.exe. The boot entries that are relevant to this post are changed via the commands below:

bcdedit.exe /set  bootstatuspolicy ignoreallfailures
bcdedit /set  recoveryenabled no

To modify the BCD via BCDedit, administrative privileges are required as seen below:

Figure 4: Error Prompt UnderPrivileged User.

Telemetry Gathering

To gather relevant telemetry, scenarios are executed in a controlled space. This telemetry will be used to validate claims and leveraged to provide detection logic later in this post.

Setup

A single clean Windows 10 enterprise, non-domain-joined, host was created in a virtualized environment. To monitor system interactions the Sysinternals tools Sysmon and Procmon got installed. Sysmon is running with the standard Olaf Harthong configuration unless indicated otherwise. Further, two agents forward the Sysmon-and MDE logs to a Sentinel environment. Kusto Query Language(KQL) is used to query the forwarded data. When Procmon data is inspected, it’s exported into a CSV file and loaded into an Excel pivot table.

The sysmon events get parsed by a stored function in MDE, called “sysmon_parsed”. All exported data and used configurations are available on the following GitHub link.

Scenario

Scenario 1: Apply BCD changes via BCDedit.exe.

As malware changes specific BCD entries via BCDedit, the same behavior is performed via an elevated PowerShell prompt.

bcdedit.exe /set  bootstatuspolicy ignoreallfailures
bcdedit /set  recoveryenabled no

First, we investigate the detection capabilities of the standard Sysmon configuration.

Figure 5: Sysmon output when adjusting BCD with the standard configuration file.

In both figures, the BCDedit process creation (Event ID 1) is highlighted. After process creation, we only observe irrelevant file creation events (Event ID 11) of the BCDedit prefetch file. Meaning, that no detectable events get generated or the standard configuration doesn’t monitor the effects of the BCD changes made by BCDedit.

Next Procmon is utilized to provide a more detailed overview of BCDedit’s system interactions.

Figure 6: Pivot Table Overview Boot Entry Changes

The pivot table shows the details of successful system operations performed by BCDedit. The right column “Type” is divided into three subcolumns. Every column Represents all operations related to a single boot entry change. The “none” subcolumn is “the baseline“, here BCDedit is run without any arguments. This is used to see if the telemetry is inherent to the BCDedit executable or to the boot entry changes performed by BCDedit.

There are two “Registry set value” operations highlighted in the pivot table above.

Registry key Value Boot entry
HKLM\BCD00000000\Objects\{60e96da1-5243-11ec-a250-810052a36a7f}\Elements\16000009\Element Type: REG_BINARY, Length: 1, Data: 00 recoveryenabled
HKLM\BCD00000000\Objects\{60e96da1-5243-11ec-a250-810052a36a7f}\Elements\250000e0\Element Type: REG_BINARY, Length: 8, Data: 01 00 00 00 00 00 00 00 bootstatuspolicy

These operations don’t occur in the baseline and are unique to its respected boot entry change. Remarkable is that the registry keys contain something resembling a unique identifier for a BCD object and something called an Element.

Microsoft states:

Each BCD element represents a specific boot option.

…

BCD object, which is a collection of elements that describes the settings for the object that are used during the boot process.

This information looks promising. To justify the use of these registry keys, for detection purposes, the following questions need to be answered:

  • As the BCD object has a unique ID, does it change across host systems?
  • Are the same registry elements changed across host systems?
  • When the value supplied to BCDedit and the related registry key holds the same value, is a “registry set value” event still created?
  • Are the registry entries one-to-one related to the BCD or are the registry keys only a visualization of the BCD?

To satisfy the first and second questions, we run the same scenario on another copy of our environment. On the new copy, we perform all previous steps and apply the same analysis steps.

Figure 7: Machine 2 Pivot Table Overview Boot Entry Changes

For convenience sake, the relevant telemetry is placed side-by-side in the table below:

Machine 1 Machine 2
Path Details Path Details
HKLM\BCD00000000\Objects\{60e96da1-5243-11ec-a250-810052a36a7f}\Elements\16000009\Element Type: REG_BINARY, Length: 1, Data: 00 HKLM\BCD00000000\Objects\{fcda0303-b063-11ec-a39e-d00df54d50c1}\Elements\16000009\Element Type: REG_BINARY, Length: 1, Data: 00
HKLM\BCD00000000\Objects\{60e96da1-5243-11ec-a250-810052a36a7f}\Elements\250000e0\Element Type: REG_BINARY, Length: 8, Data: 01 00 00 00 00 00 00 00 HKLM\BCD00000000\Objects\{fcda0303-b063-11ec-a39e-d00df54d50c1}\Elements\250000e0\Element Type: REG_BINARY, Length: 8, Data: 01 00 00 00 00 00 00 00

We can conclude that the same registry values are changed identically on the two different systems under a different object ID. In other words, these keys can be used for detection purposes, but we must exclude the object ID in the detection logic.

To determine the consistency of monitoring registry key value changes, the 3rd question needs to be answered: “When the value supplied to BCDedit and the related registry key holds the same value, is a registry set value event created?“

Via BCDedit, the same argument is run multiple times to see if a registry change occurs for every iteration.

Figure 8: Multiple Same Value Registry Changes

As seen above, a registry set event occurs even if the attribute is already configured with the same value.

Scenario 2: Apply BCD changes via direct registry manipulation.

In this scenario, the earlier determined keys are manually adjusted without the use of BCDedit. To confirm if the changes took effect, the recovery sequence is triggered.

To see if this scenario is even possible, the last question needs to be addressed: “Are the registry entries one-to-one related to the BCD, or are the registry keys only a visualization of the BCD?“

To apply changes to the registry directly, an elevated Powershell prompt is used:

Figure 9: Direct Registry Manipulation Failure With Elevated Prompt

It seems that even with an elevated PowerShell instance, direct registry manipulation isn’t possible. Elevating the prompt to system-level fixes this issue:

Figure 10: Successful Direct Registry Manipulation With System Prompt.

For convenience, the following PowerShell code was written. This code looks for registry objects with all the subkeys in our $pack variable. This is needed as the element names can be reused within the BCD hive. We simply enumerate the keys, filter on the objects that hold both keys, and respectively added the new values to the keys.  

$pack [email protected]{ '16000009'=([byte[]](0x01)); '250000e0'=([byte[]](0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00))} 
cd 'HKLM:\BCD00000000\Objects\' 
$items = $pack.keys|%{(ls -path $_ -Recurse)} $summary=$items|%{$_.Name.trim($_.PSChildName)}| group 
$CorrectHive=($summary|Where-Object {$_.count -eq $subkeys.length}).Name $correctitems= $items |Where-Object {$_.Name.contains($CorrectHive)} $correctitems|%{$_|Set-ItemProperty -Name Element -value  $pack[$_.PSChildName]}
Figure 11: Registry Changes Via Powershell Script

To confirm the changes took effect, attempts were made to trigger the recovery sequence. This test was performed multiple times on different machines. We observed that these changes do disable the recovery feature. As a good measure, the settings were reversed, and the “Auto Repair” feature functioned as expected. In other words, it’s possible to change boot entries by changing the registry directly.

Detection.

As this is a known attack, that primarily uses BCDedit, detection rules are available that look for suspicious BCD arguments. Below KQL examples are provided for both MDE and Sysmon:

Sysmon_Parsed 
| where EventID == 1 
| where OriginalFileName =~"bcdedit.exe" 
| where CommandLine has "set" | where CommandLine has_all ("recoveryenabled", "no") or CommandLine has_all ("bootstatuspolicy", "ignoreallfailures")
DeviceProcessEvents 
| where FileName =~ "bcdedit.exe" 
| where ProcessCommandLine has "set" 
| where ProcessCommandLine has_all ("recoveryenabled", "no") or ProcessCommandLine has_all ("bootstatuspolicy", "ignoreallfailures") 
| project DeviceName,ActionType,TimeGenerated,ProcessCommandLine
Figure 12: KQL Output BCDedit Arguments Checks.

In the above output, only BCD changes via BCDedit are logged and direct registry manipulations aren’t detected. Next, we monitor for registry manipulation of the elements “16000009”and “250000e0”. Again KQL examples are provided for both MDE and Sysmon:

DeviceRegistryEvents 
| where TimeGenerated > ago (60d) 
| where not(InitiatingProcessFolderPath in~ (@"c:\$windows.~bt\sources\setuphost.exe", @"c:\windows\system32\bitlockerwizardelev.exe")) 
| where ActionType == "RegistryValueSet" 
| where RegistryKey has "elements" and RegistryKey has_any("16000009", "250000e0") 
| summarize by DeviceId, InitiatingProcessFolderPath, RegistryKey, RegistryValueData, ActionType, InitiatingProcessCommandLine, RegistryValueType
Sysmon_Parsed 
| where EventID == 13 
| where TargetObject has "elements" 
| where TargetObject has_any( "16000009","250000e0") 
| project TargetObject,Details,Image

Note: that for the systems running Sysmon, the following lines need to be added to the <RegistryEvent onmatch=”include”> group in the Sysmon XML file.

<TargetObject name="technique_id=T1490,technique_name=Disable Automatic Windows recovery" condition="contains all">HKLM\BCD;\Elements\16000009\Element</TargetObject> 
<TargetObject name="technique_id=T1490,technique_name=Disable Automatic Windows recovery" condition="contains all">HKLM\BCD;\Elements\250000e0\Element</TargetObject>
Figure 13: KQL Output Registry Value Monitoring

As expected, both the BCDedit manipulating BCD and direct registry manipulation are detected. However, the registry values only indicate “binary data” and not the actual binary value. This has a negative effect on the detection rule as it’s impossible to determine what information was written into the registry key.

The rules got tested in several environments with 5000+ endpoints, the largest of which was 10000. Overall it functions well with a low false positive(FP) rating.

One possible FP is WMI initiating BCD changes, the below command line was seen on multiple occasions manipulating the 250000e0 registry key:

wmiprvse.exe -secured -Embedding

As WMI causes ancestry chain break, there is no easy way to deduce what process initiated the registry change. The only investigation you can perform is a timeline analysis on the machine, looking for WMI-related activity.

Final Conclusions

In this post, we analyzed the effect of changing commonly abused BCD attributes via:

  • BCDedit.exe
  • Direct Registry Manipulation.

The Telemetry showed:

  1. Direct registry manipulation has a one-to-one effect on the BCD.
  2. Registry set event occurs even if the attribute is already configured with the same value.
  3. Binary Data values aren’t visible in MDE and Sysmon.

We provided:

  • A more resilient detection rule for both MDE and Sysmon systems.

Although the detection rule is more resilient, due to the limitation of the logs and tools, we aren’t able to distinguish between enabling and disabling boot entries. However, these queries were run against a vast amount of endpoints with a low FP outcome.

Red Team Nuggets

It’s only possible for MDE and Sysmon systems to detect registry binary changes. The registry content itself is not visible to the analyst. This provides an opportunity for attackers to drop a payload in a binary registry key, with a low chance of being detected.

Mentions

Special thanks to our senior intrusion analyst member Remco Hofman for assisting in fine-tuning the detection logic.

Also a special thanks to Bart Parys for proofreading the post.

References

https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/boot-and-uefi
https://attack.mitre.org/techniques/T1490/
https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-re-troubleshooting-features?view=windows-11
https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit–set
https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcd-boot-options-reference
https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/
https://github.com/NVISOsecurity/blogposts/tree/master/Detecting-BCD-Changes-To-Inhibit-System-Recovery
❌
❌