Recovering BitLocker Keys on Windows 8.1 and 10
A brief touch on how the changes to BitLocker after Windows 7 affect master key recovery and where to look when recovering keys.
This article is not intended to be an in-depth look at the inner workings of BitLocker, but is instead focussed on retrieval of the Full Volume Encryption Key (FVEK) from memory.
Key recovery on Windows 7 is a fairly simple exercise (see references at the end of this article for further reading). When dealing with a Windows 7 memory image we can simply search for the FVEc
pool tag as an indicator of exactly where the FVEK lies in memory. From there, we can proceed to extract the key.
Starting with Windows 8, however, it seems that the cryptographic operations for BitLocker have been outsourced to Microsoft’s CNG (Cryptography Next Generation) Module, which is the long-term replacement for CryptoAPI, rather than being performed internally within the fvevol
driver.
What this means for us is that searching for the FVEc
pool tag on Windows 8 and above will no longer yield anything useful.
AESKeyFind still works, of course, though depending on your memory image you may need to tweak your threshold settings.
Key Recovery via Live kernel debugging
I’m not entirely sure where you would find yourself in a situation with a debugger attached to the kernel, yet not be able to disable BitLocker, retrieve the recovery password or add your own key protector, but hey, stranger things have happened. On the other hand, perhaps you want the FVEK for other reasons – such as persistence across key protector changes (Even then retrieval from memory is arguably less effort and less intrusive than kernel debugging).
However I used windbg to investigate the changes to BitLocker on Windows 8 / 10 and it is certainly possible to retrieve the FVEK using this method as well as demonstrating the use of CNG.
To get started, this is an example of the call stack on a Windows 7 box – The encrypt / decrypt functions are all handled within fvevol
. This example is using the default encryption method, which is AES 128-bit with the Elephant Diffuser.
On the other hand, in this Windows 8.1 example, CNG starts to get involved with the encrypt / decrypt functions:
Now, we can actually retrieve the FVEK at this point from the second argument passed to SymCryptEcbDecrypt
, which contains a pointer to the location of the key in memory. The rdx
register (64-bit machine) contains a pointer to the location of the FVEK in memory, so, by setting a breakpoint on cng!SymCryptEcbDecrypt
then obtaining the value of rdx
we can extract the FVEK (Note that this is a 256-bit key, the default 128-bit will be half the size):
That was a Windows 8.1 Example. When dealing with Windows 10 in XTS-AES mode, break on cng!SymCryptXtsAesDecrypt
and check the rcx
register (During my testing the key was passed as the first argument to the XTS Decrypt function):
By moving backwards through the memory image slightly we can see that this section of memory is likely tagged with a Cngb
pool tag. As expected, checking the pool tag definitions reveals that Cngb
is used for CNG allocations:
...
Cngb – ksecdd.sys – CNG kmode crypto pool tag
...
Which brings us to the next (much more practical) stage.
Key Recovery using memory pool allocations
As previously mentioned most of the cryptographic work appears to have been farmed out to the CNG driver, whereas in previous versions of windows the fvevol
driver contained its own implementations. Searching for the Cngb
pool tag will yield a lot of results as CNG is a complex beast and is not solely used for BitLocker, however, the pool sizes for BitLocker allocations seem to be fairly consistent which means we can use them as an indicator of key locations.
The pool size for Cngb appears to be consistent at 672, regardless of encryption type – Volatility can find these pools for you with the poolpeek
plugin.
Whilst I have not yet identified a method of differentiating between BitLocker modes from the contents of the Cngb
pool alone, there is a marker which appears to reliably identify a key length of either 128-bit or 256-bit at an offset of 0x68
within the pool. A value of ’10’ seems to indicate a key length of 128-bit to follow, and ’20’ indicates a key length of 256-bit.
Interestingly enough, keys other than the FVEK exist with the same format (In a Cngb
pool of size 672), but only after Bitlocker is enabled on the system. It’s possible this could be one of the other keys used in Bitlocker, such as the Volume Master Key (VMK), however at the time of writing I have not identified the function of these keys.
Volatility Plugin
This plugin is very much an experimental work-in-progress.
With this information on hand, I have put together a Volatility plugin which can extract BitLocker keys from Windows 7, and in theory versions of Windows above 7. The plugin isn’t entirely reliable for Windows 8 – 10 but works in most cases with a few quirks:
- Returns AES Keys other than the FVEK (See above, these keys only exist on Bitlocker protected systems).
- Doesn’t always work with Windows 10 XTS-AES encryption (Though works with CBC).
- Cannot identify the BitLocker mode of operation above Windows 7.
The plugin operates as follows:
- Obtains Windows version from profile metadata.
- If the version is lower than Windows 8: - Searches for FVEc pool tag
- Identifies BitLocker mode
- Extracts FVEK of appropriate length and TWEAK key if applicable
- If the version is higher than Windows 8: - Searches for Cngb pool tag with a pool size of 672
- Attempts to identify key length (Does not work properly for XTS-AES in Win10)
- Extracts either 128-bit or 256-bit key
- Is unable to guarantee it is a BitLocker FVEK.
- Prints the results.
Example of a Windows 7 image:
Example of a Windows 8.1 Image:
Example of a Windows 10 image (CBC):
And this is a screenshot of mounting the above Windows 8.1 protected volume using the FVEK data:
The excellent libbde library can be used to mount BitLocker protected volumes in Linux using the FVEK and TWEAK data.
I make no promises that the plugin is complete and works perfectly, but will hopefully at least be a starting point for further development of a complete BitLocker plugin.
Plugin is on GitHub here: https://github.com/tribalchicken/volatility-bitlocker
As usual feedback, corrections, criticism (preferably constructive) or further discussion are all welcome. Feel free to contact me.