Windows Security

Secure Boot/TPM Lab
Lab Objectives:
  • Check the secure boot settings in Windows
  • View the enrolled secure boot keys
  • View the key signatures in boot files
  • View the TPM info
NOTE: You will need a Windows machine with secure boot and TPM enabled to complete this lab. Internet access will also be required to download non-standard Powershell modules. 1.  Open a command prompt as an Administrator

2.  Enter:
 powershell 


3.  Enter:
  Confirm-SecureBootUEFI  

To verify that UEFI Secure Boot is enabled.
True

4.  Make a directory to export UEFI certificates to.
Enter:
 md UEFI_Certs 

Directory: C:\Users\Pete Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2/7/2022 6:17 PM UEFI_Certs

5.  To extract the Platform Key enter:
 Get-SecureBootUEFI -Name PK -OutputFilePath .\UEFI_Certs\PK.esl 

Name Bytes Attributes ---- ----- ---------- PK {161, 89, 192, 165...} NON VOLATILE...

6.  To extract the Key Exchange Key(s) enter:
 Get-SecureBootUEFI -Name KEK -OutputFilePath .\UEFI_Certs\KEK.esl 

Name Bytes Attributes ---- ----- ---------- PK {161, 89, 192, 165...} NON VOLATILE...

7.  To extract the db keys enter:
 Get-SecureBootUEFI -Name db -OutputFilePath .\UEFI_Certs\db.esl 

Name Bytes Attributes ---- ----- ---------- PK {161, 89, 192, 165...} NON VOLATILE...

8.  To extract dbx keys and hashes enter:
 Get-SecureBootUEFI -Name dbx -OutputFilePath .\UEFI_Certs\dbx.esl 

Name Bytes Attributes ---- ----- ---------- PK {161, 89, 192, 165...} NON VOLATILE...

Now that we have the Secure Boot variables saved from NVRAM, we need to extract the certificates and signature hashes from the EFI Signature List (ESL) files. While Linux has an efitools package to help perform this extraction, Windows does not have a equivalent program. (If you want to port sig-list-to-certs to Windows, the source is available here )

We can still manually extract the certificates in Windows, but we will need some additional tools. First we will install the winget package manager.

9.  Enter:
 Add-AppxPackage -Path https://github.com/microsoft/winget-cli/releases/download/v1.2.10271/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle


10.  Enter:
 winget install --id Git.Git -e --source winget

This will install the Microsoft Git package, which includes a number of tools including openssl and the vim editor. Now we update the path variable to include the vim.exe and openssl.exe locations.

11.  Enter:
 $Env:PATH += ";C:\Program Files\Git\usr\bin" 


12.  Enter:
 cd UEFI_Certs  

To go to the cert Directory.

We will now extract the PK certificate from the PK.esl file. First we need to dump the binary file to a hex format with xxd.

13.  Enter:
 xxd PK.esl PK.hex 

Now we can edit the hex dump with vim.

14.  Enter:
 vim PK.hex 


00000000: a159 c0a5 e494 a74a 87b5 ab15 5c2b f072 .Y.....J....\+.r 00000010: cd03 0000 0000 0000 b103 0000 ce4d 5670 .............MVp 00000020: fc9a e34e 85fc 9496 49d7 e45c 3082 039d ...N....I..\0... 00000030: 3082 0285 a003 0201 0202 1050 a1bd 858a 0..........P.... 00000040: e7b6 bc40 2dca 78cd d268 a130 0d06 092a ...@-.x..h.0...* 00000050: 8648 86f7 0d01 010b 0500 3067 310b 3009 .H........0g1.0. 00000060: 0603 5504 0613 0255 5331 0e30 0c06 0355 ..U....US1.0...U 00000070: 0408 0c05 5465 7861 7331 1330 1106 0355 ....Texas1.0...U 00000080: 0407 0c0a 526f 756e 6420 526f 636b 3112 ....Round Rock1. *** REMAINING OUTPUT OMITTED ***

According to page 1717 of the UEFI specification, the GUID identifier for an x509 certificate list is:

 
		#define EFI_CERT_X509_GUID
			{ 0xa5c059a1, 0x94e4, 0x4aa7,
				{ 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 } 
			}; 
	
However, the UEFI documentation is in Big Endian format while the firmware actually stores the data in Little Endian format. This calculator can be helpful to convert the values. To read little endian Hex values, read the bytes from right to left, but read each individual byte from left to right. In little endian format the x509 GUID value is: a159c0a5 e494 a74a 87 b5 ab 15 5c 2b f0 72 which we see on the first line of the file:


00000000: a159 c0a5 e494 a74a 87b5 ab15 5c2b f072 .Y.....J....\+.r

The next value after the x509 GUID is the UINT32 SignatureListSize value, which defines the length of the signature list including headers. We know this value is 4 bytes long because a 32-bit Unsigned Integer (UINT32) is 32 bits, and 32 bits is 4 bytes. The next 4 bytes after the GUID are:

00000010: cd03 0000

However this is little endian, so the big endian value is 0000 03cd. In decimal, this is 973 bytes. Conveniently our hex dump has byte numbers listed in hexadecimal on the side, so we just need to find byte 03cd to find the end of the PK certificate. Scrolling down we see:

*** Remaining output omitted *** 00000370: a3b9 c037 aaf9 e0f1 83e9 5228 923b b837 ...7......R(.;.7 00000380: 0a0f a2ef 7e0b 0031 d7b1 40f6 eaf5 871a ....~..1..@..... 00000390: 8804 83d9 33f2 9979 24c0 2c43 5b42 2c6c ....3..y$.,C[B,l 000003a0: db05 6c48 23bf 1694 383e 551b 4991 39cc ..lH#...8>U.I.9. 000003b0: b265 3ee8 af15 2445 c85b ad28 3aa7 a488 .e>...$E.[.(:... 000003c0: 948d 0ad8 4b8d c36c 1797 8221 fc ....K..l...!.

Byte 0000 03c0 is the first byte on the last line of the file. We can count from that byte to find byte 03cd; remember that every 2 hexadecimal digits are 1 byte, and 0xd in hex is decimal 13. We need to count 13 bytes, or 26 hex digits, from the start of the line. 0xfc is 13 bytes from the start of the line, so it is the last byte in the certificate. It is also also the last byte in the file. This makes sense, because there can only be one PK certificate. To extract the certificate from the file, we just need to remove the ESL header information from the beginning of the file. According to the specification, the next value in the header after UINT32 SignatureListSize is UINT32 SignatureHeaderSize. Scrolling back to the top of the file we see:

00000010: cd03 0000 0000 0000 b103 0000 ce4d 5670 .............MVp

The next 4 bytes after cd03 0000 is 0000 0000, so the signature has no header. (Note this is the signature header not ESL header). After UINT32 SignatureHeaderSize is UINT32 SignatureSize:

00000010: cd03 0000 0000 0000 b103 0000 ce4d 5670 .............MVp

This is b103 0000 which is 0000 03b1 in big endian, so there are 03b1 bytes in the signature. The specification states that SignatureSize may vary but shall always be 16 (size of the SignatureOwner component) + the size of the certificate itself. This means that the next 16 bytes are the SignatureOwner which should not be included in the certificate:

00000010: cd03 0000 0000 0000 b103 0000 ce4d 5670 .............MVp 00000020: fc9a e34e 85fc 9496 49d7 e45c 3082 039d ...N....I..\0...

The next 16 bytes are ce4d 5670 fc9a e34e 85fc 9496 49d7 e45c. This means our certificate should start with 3082 039d. We need to delete all bytes before 0x3082 to extract the x509 certificate for the PK. Unfortunately, we can't delete bytes from a hex dump in this format in vim (with line numbers and ASCII) so we need to reformat the output.