Skip to content

Instantly share code, notes, and snippets.

@iamacarpet
Forked from out0xb2/Check-Dbx.ps1
Last active May 9, 2022 10:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamacarpet/7030c23033bb045c72a15e3c441aada3 to your computer and use it in GitHub Desktop.
Save iamacarpet/7030c23033bb045c72a15e3c441aada3 to your computer and use it in GitHub Desktop.
Parses signature data from the pk, kek, db, and dbx UEFI variables.
Write-Host "Checking for Administrator permission..."
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Warning "Insufficient permissions to run this script. Open the PowerShell console as administrator and run this script again."
Break
} else {
Write-Host "Running as administrator: continuing execution..." -ForegroundColor Green
}
$patchfile = $args[0]
if ($patchfile -eq $null) {
$patchfile = ".\dbx-2021-April.bin"
Write-Host "Patchfile not specified, using latest $patchfile`n"
}
$patchfile = (gci $patchfile).FullName
Import-Module -Force .\Get-UEFIDatabaseSignatures.ps1
# Print computer info
$computer = gwmi Win32_ComputerSystem
$bios = gwmi Win32_BIOS
"Manufacturer: " + $computer.Manufacturer
"Model: " + $computer.Model
$biosinfo = $bios.Manufacturer , $bios.Name , $bios.SMBIOSBIOSVersion , $bios.Version -join ", "
"BIOS: " + $biosinfo + "`n"
$DbxRaw = Get-SecureBootUEFI dbx
$DbxFound = $DbxRaw | Get-UEFIDatabaseSignatures
$DbxBytesRequired = [IO.File]::ReadAllBytes($patchfile)
$DbxRequired = Get-UEFIDatabaseSignatures -BytesIn $DbxBytesRequired
# Flatten into an array of required EfiSignatureData data objects
$RequiredArray = foreach ($EfiSignatureList in $DbxRequired) {
Write-Verbose $EfiSignatureList
foreach ($RequiredSignatureData in $EfiSignatureList.SignatureList) {
Write-Verbose $RequiredSignatureData
$RequiredSignatureData.SignatureData
}
}
Write-Information "Required `n" $RequiredArray
# Flatten into an array of EfiSignatureData data objects (read from dbx)
$FoundArray = foreach ($EfiSignatureList in $DbxFound) {
Write-Verbose $EfiSignatureList
foreach ($FoundSignatureData in $EfiSignatureList.SignatureList) {
Write-Verbose $FoundSignatureData
$FoundSignatureData.SignatureData
}
}
Write-Information "Found `n" $FoundArray
$successes = 0
$failures = 0
$requiredCount = $RequiredArray.Count
foreach ($RequiredSig in $RequiredArray) {
if ($FoundArray -contains $RequiredSig) {
Write-Information "FOUND: $RequiredSig"
$successes++
} else {
Write-Error "!!! NOT FOUND`n$RequiredSig`n!!!`n"
$failures++
}
$i = $successes + $failures
Write-Progress -Activity 'Checking if all patches applied' -Status "Checking element $i of $requiredCount" -PercentComplete ($i/$requiredCount *100)
}
if ($failures -ne 0) {
Write-Error "!!! FAIL: $failures failures detected!"
exit 4
# $DbxRaw.Bytes | sc -encoding Byte dbx_found.bin
} elseif ($successes -ne $RequiredArray.Count) {
Write-Error "!!! Unexpected: $successes != $requiredCount expected successes!"
exit 5
} elseif ($successes -eq 0) {
Write-Error "!!! Unexpected failure: no successes detected, check command-line usage."
exit 6
} else {
Write-Host "SUCCESS: dbx.bin patch appears to be successfully applied"
}
function Get-UefiDatabaseSignatures {
<#
.SYNOPSIS
Parses UEFI Signature Databases into logical Powershell objects
.DESCRIPTION
Original Author: Matthew Graeber (@mattifestation)
Modified By: Jeremiah Cox (@int0x6)
Additional Source: https://gist.github.com/mattifestation/991a0bea355ec1dc19402cef1b0e3b6f
License: BSD 3-Clause
.PARAMETER Variable
Specifies a UEFI variable, an instance of which is returned by calling the Get-SecureBootUEFI cmdlet. Only 'db' and 'dbx' are supported.
.PARAMETER BytesIn
Specifies a byte array consisting of the PK, KEK, db, or dbx UEFI vairable contents.
.EXAMPLE
$DbxBytes = [IO.File]::ReadAllBytes('.\dbx.bin')
Get-UEFIDatabaseSignatures -BytesIn $DbxBytes
.EXAMPLE
Get-SecureBootUEFI -Name db | Get-UEFIDatabaseSignatures
.EXAMPLE
Get-SecureBootUEFI -Name dbx | Get-UEFIDatabaseSignatures
.EXAMPLE
Get-SecureBootUEFI -Name pk | Get-UEFIDatabaseSignatures
.EXAMPLE
Get-SecureBootUEFI -Name kek | Get-UEFIDatabaseSignatures
.INPUTS
Microsoft.SecureBoot.Commands.UEFIEnvironmentVariable
Accepts the output of Get-SecureBootUEFI over the pipeline.
.OUTPUTS
UefiSignatureDatabase
Outputs an array of custom powershell objects describing a UEFI Signature Database. "77fa9abd-0359-4d32-bd60-28f4e78f784b" refers to Microsoft as the owner.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'UEFIVariable')]
[ValidateScript({ ($_.GetType().Fullname -eq 'Microsoft.SecureBoot.Commands.UEFIEnvironmentVariable') -and (($_.Name -eq 'kek') -or ($_.Name -eq 'pk') -or ($_.Name -eq 'db') -or ($_.Name -eq 'dbx')) })]
$Variable,
[Parameter(Mandatory, ParameterSetName = 'ByteArray')]
[Byte[]]
[ValidateNotNullOrEmpty()]
$BytesIn
)
$SignatureTypeMapping = @{
'C1C41626-504C-4092-ACA9-41F936934328' = 'EFI_CERT_SHA256_GUID' # Most often used for dbx
'A5C059A1-94E4-4AA7-87B5-AB155C2BF072' = 'EFI_CERT_X509_GUID' # Most often used for db
}
$Bytes = $null
if ($Variable) {
$Bytes = $Variable.Bytes
} else {
$Bytes = $BytesIn
}
try {
$MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$Bytes)
$BinaryReader = New-Object -TypeName IO.BinaryReader -ArgumentList $MemoryStream, ([Text.Encoding]::Unicode)
} catch {
throw $_
return
}
# What follows will be an array of EFI_SIGNATURE_LIST structs
while ($BinaryReader.PeekChar() -ne -1) {
$SignatureType = $SignatureTypeMapping[([Guid][Byte[]] $BinaryReader.ReadBytes(16)).Guid]
$SignatureListSize = $BinaryReader.ReadUInt32()
$SignatureHeaderSize = $BinaryReader.ReadUInt32()
$SignatureSize = $BinaryReader.ReadUInt32()
$SignatureHeader = $BinaryReader.ReadBytes($SignatureHeaderSize)
# 0x1C is the size of the EFI_SIGNATURE_LIST header
$SignatureCount = ($SignatureListSize - 0x1C) / $SignatureSize
$SignatureList = 1..$SignatureCount | ForEach-Object {
$SignatureDataBytes = $BinaryReader.ReadBytes($SignatureSize)
$SignatureOwner = [Guid][Byte[]] $SignatureDataBytes[0..15]
switch ($SignatureType) {
'EFI_CERT_SHA256_GUID' {
$SignatureData = ([Byte[]] $SignatureDataBytes[0x10..0x2F] | ForEach-Object { $_.ToString('X2') }) -join ''
}
'EFI_CERT_X509_GUID' {
$SignatureData = New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(,([Byte[]] $SignatureDataBytes[16..($SignatureDataBytes.Count - 1)]))
}
}
[PSCustomObject] @{
PSTypeName = 'EFI.SignatureData'
SignatureOwner = $SignatureOwner
SignatureData = $SignatureData
}
}
[PSCustomObject] @{
PSTypeName = 'EFI.SignatureList'
SignatureType = $SignatureType
SignatureList = $SignatureList
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment