Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recovering the recovery-key once drive is decrypted with dislocker #294

Open
pascal-gujer opened this issue Oct 28, 2022 · 1 comment
Open

Comments

@pascal-gujer
Copy link

I am looking for a way to decrypt(?) the recovery key, if the drive can be decrypted? Microsoft can do this easily, I wonder how this could be done when having the FVEK.

It would be a very handy feature, as many other tools cannot use FVEK or VMK but only recovery passwords.
Any idea / hints are appreciated!

@pascal-gujer
Copy link
Author

pascal-gujer commented Nov 1, 2022

ok, digged in hard and finally found a paper giving me the necessary information:
[0] Implementing BitLocker Drive Encryption for forensic analysis https://pdf4pro.com/cdn/implementing-bitlocker-drive-encryption-for-19a515.pdf

In Section 5.0 the author states:

As noted earlier, each of these key protectors contains a nonce used in the encryption and decryption process. Those nonces increase monotonically for each key generation performed by BitLocker. The two nonces in the key protectors in each metadata entry differ by one and can be represented as j and j+1.
The author has found that the nonce used when the system encrypts the key in question with the VMK, E(ki, VMK), is the nonce j, and the nonce used when the system encrypts the VMK with the key in question, E(VMK, ki), is the nonce j + 1. This suggests
that when BitLocker creates a new metadata entry for a key, the system first encrypts the new key with the VMK and then encrypts the VMK with the new key. The timestamps are identical in both key protectors.

So next to a Recovery Key entry in Bitlocker Metadata, we should find a recovery key encrypted by the VMK, besides the normally used and needed VMK encrypted by the recovery key:

[DEBUG] Total datum size: 0x013c (316) bytes
[DEBUG] Datum entry type: 2
[DEBUG]    --> ENTRY TYPE VMK
[DEBUG] Datum value type: 8
[DEBUG]    --> VMK -- Total size header: 36 -- Nested datum: yes
[DEBUG] Status: 0x1
[DEBUG] Recovery Key GUID: 'B4D58F66-98B4-4E2E-8FC3-1F4D16F1F91C'
[DEBUG] Nonce: 
[DEBUG] 30 b4 b6 d8 e1 84 d8 01 00 00 00 08 
[DEBUG]    ------ Nested datum(s) ------
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG] Total datum size: 0x00ac (172) bytes
[DEBUG] Datum entry type: 0
[DEBUG]    --> ENTRY TYPE UNKNOWN 1
[DEBUG] Datum value type: 3
[DEBUG]    --> STRETCH KEY -- Total size header: 28 -- Nested datum: yes
[DEBUG] Status: 0x1
[DEBUG] Unknown: 
[DEBUG] 0x00000000 00 00 
[DEBUG] Algo: 0x1000
[DEBUG] Salt: 
[DEBUG] 4a 80 73 f0 6c f4 a9 df e5 e3 bd d9 b4 2f 41 3d 
[DEBUG]    ------ Nested datum ------
[DEBUG] Total datum size: 0x0040 (64) bytes
[DEBUG] Datum entry type: 18
[DEBUG] Datum value type: 5
[DEBUG]    --> AES-CCM -- Total size header: 36 -- Nested datum: no
[DEBUG] Status: 0x1
[DEBUG] Nonce: 
[DEBUG] e0 ec 9e d5 e1 84 d8 01 03 00 00 00 
[DEBUG] MAC: 
[DEBUG] e0 3b 0c 4e 34 bc 03 c2 12 12 1a f7 f9 61 94 5a 
[DEBUG] Payload:
[DEBUG] 0x00000000 5e 49 a1 75 7a 27 ea ab-aa 05 94 31 df a9 87 82 
[DEBUG] 0x00000010 f0 b8 b1 67 78 40 56 b4-28 07 47 28 
[DEBUG]    ---------------------------
[DEBUG] Header safe: 0xac, 0, 0x3, 0x1
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG] Total datum size: 0x0050 (80) bytes
[DEBUG] Datum entry type: 0
[DEBUG]    --> ENTRY TYPE UNKNOWN 1
[DEBUG] Datum value type: 5
[DEBUG]    --> AES-CCM -- Total size header: 36 -- Nested datum: no
[DEBUG] Status: 0x1
[DEBUG] Nonce: 
[DEBUG] e0 ec 9e d5 e1 84 d8 01 05 00 00 00 
[DEBUG] MAC: 
[DEBUG] 3b 26 2a e2 21 50 d2 e1 b5 e5 1c 8e 4f e3 5e ff 
[DEBUG] Payload:
[DEBUG] 0x00000000 71 92 5d 0e c7 24 bd 22-03 3d 15 4e 74 a3 ee d2 
[DEBUG] 0x00000010 a9 d7 7e 9e 00 77 6d 09-a8 89 6d 99 6c 65 90 12 
[DEBUG] 0x00000020 f3 9e 32 e9 9d 48 fb 41-63 df d8 73 
[DEBUG] Header safe: 0x50, 0, 0x5, 0x1
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG] Total datum size: 0x001c (28) bytes
[DEBUG] Datum entry type: 0
[DEBUG]    --> ENTRY TYPE UNKNOWN 1
[DEBUG] Datum value type: 21
[DEBUG]    --> ERROR -- Total size header: 1676 -- Nested datum: no
[DEBUG] Status: 0x1
[DEBUG] Generic datum:
[DEBUG] 0x00000000 80 25 47 e6 e1 84 d8 01-80 25 47 e6 e1 84 d8 01 
[DEBUG] 0x00000010 10 00 02 00 
[DEBUG] Header safe: 0x1c, 0, 0x15, 0x1
[DEBUG] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DEBUG]    ------------------------------
[DEBUG] =========================================
[DEBUG] Header safe: 0x8, 0x4, 0x7, 0x1

When I mount this drive with the recovery key, the material with the nonce
e0 ec 9e d5 e1 84 d8 01 05 00 00 00
gets decrypted and results a VMK, as I see in the dislocker debug log.

When I then take this VMK and decrypt the material with the lower nonce as stated in [0], I get a proper decrypt (MAC match) and the following bytes result:

[DEBUG] }--------[ Data passed to aes_ccm_encrypt_decrypt ]--------{
[DEBUG] -- Nonce:
[DEBUG] 0x00000000 e0 ec 9e d5 e1 84 d8 01-03 00 00 00 
[DEBUG] -- Input buffer:
[DEBUG] 0x00000000 5e 49 a1 75 7a 27 ea ab-aa 05 94 31 df a9 87 82 
[DEBUG] 0x00000010 f0 b8 b1 67 78 40 56 b4-28 07 47 28 
[DEBUG] -- MAC:
[DEBUG] 0x00000000 e0 3b 0c 4e 34 bc 03 c2-12 12 1a f7 f9 61 94 5a 
[DEBUG] }----------------------------------------------------------{
[DEBUG] Entering aes_ccm_encrypt_decrypt...
[DEBUG] 	Tmp buffer:
[DEBUG] 0x00000000 27 f6 12 24 94 51 08 bc-66 9e 78 e4 a7 65 5a 1c 
[DEBUG] 	Input:
[DEBUG] 0x00000000 e0 3b 0c 4e 34 bc 03 c2-12 12 1a f7 f9 61 94 5a 
[DEBUG] 	Output:
[DEBUG] 0x00000000 c7 cd 1e 6a a0 ed 0b 7e-74 8c 62 13 5e 04 ce 46 
[DEBUG] Input length: 28, loop: 1
[DEBUG] Input length remain: 12
[DEBUG] Ending aes_ccm_encrypt_decrypt successfully!
[DEBUG] Entering aes_ccm_compute_unencrypted_tag...
[DEBUG] 	Buffer:
[DEBUG] 0x00000000 1c 00 00 00 01 00 00 00-00 10 00 00 fc 2f 86 ef 
[DEBUG] 	Internal IV:
[DEBUG] 0x00000000 69 6c a7 c2 f5 96 1b 5b-91 cf 0a 40 3b 78 72 96 
[DEBUG] Ending aes_ccm_compute_unencrypted_tag successfully!
[DEBUG] Looking if MACs match...
[DEBUG] They are just below:
[DEBUG] 0x00000000 c7 cd 1e 6a a0 ed 0b 7e-74 8c 62 13 5e 04 ce 46 
[DEBUG] 0x00000000 c7 cd 1e 6a a0 ed 0b 7e-74 8c 62 13 5e 04 ce 46 
[DEBUG] Ok, they match!
[DEBUG] 0x00000000 1c 00 00 00 01 00 00 00-00 10 00 00 fc 2f 86 ef 
[DEBUG] 0x00000010 46 9d 99 02 22 1a f8 6b-56 82 d0 4b fd 55 00 00 
[DEBUG] 0x00000020 4d 33 2e 35 2e 30 2c 4d-51 0b 00 00

In Section 5.4 of [0] the conversion process of the human readable recovery key into the bitlocker needed byte stream is outlined, this conversion is already implemented by dislocker, as the decryption with the recovery key is already implemented. Doing this conversion with my test system recovery key yields to the following:

135124-674498-442882-007315-073590-304040-367026-213488
12284 61318 40262 665 6690 27640 33366 19408    // divided by 11
2ffc ef86 9d46 0299 1a22 6bf8 8256 4bd0 // Dec to Hex conversion
fc 2f 86 ef 46 9d 99 02 22 1a f8 6b 56 82 d0 4b // swapped endianness

and looking at the bytes in the decrypted Stretch key above, we see, that the * marked bytes match the recovery key:

[DEBUG] 0x00000000 1c 00 00 00 01 00 00 00-00 10 00 00 *fc *2f *86 *ef 
[DEBUG] 0x00000010 *46 *9d *99 *02 *22 *1a *f8 *6b-*56 *82 d0 4b fd 55 00 00 
[DEBUG] 0x00000020 4d 33 2e 35 2e 30 2c 4d-51 0b 00 00

The steps involved to create the recovery key when knowing a protector yielding to a VMK are:

  1. decrypt recovery key by using the (nonce, mac, payload) from the entry with "Datum value type: 3"
  2. extract bytes from decrypted recovery key
  3. change endianness
  4. convert to decimal number
  5. multiply by 11
  6. print nice little string :)

looking for someone who can code nicer C than I do sigh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant