Skip to content

Instantly share code, notes, and snippets.

@p0w3rsh3ll
Forked from mattifestation/UEFISecDatabaseParser.ps1
Last active September 21, 2025 17:14
Show Gist options
  • Save p0w3rsh3ll/16512ce589aa6e40c6ec854f651edb26 to your computer and use it in GitHub Desktop.
Save p0w3rsh3ll/16512ce589aa6e40c6ec854f651edb26 to your computer and use it in GitHub Desktop.
Parses signature data from the pk, kek, db, and dbx UEFI variables.
Function Get-UEFIDatabaseSigner {
<#
.SYNOPSIS
Dumps signature or hash information for whitelisted ('db' variable) or blacklisted ('dbx' variable) UEFI bootloaders.
.DESCRIPTION
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
.PARAMETER Variable
Specifies a UEFI variable name or a list of variable names.
The default variable name used is 'dbx'.
.PARAMETER File
Specifies the path to a binary file.
.PARAMETER InputObject
Specifies an instance or a list of instances of the Get-SecureBootUEFI cmdlet output
.EXAMPLE
Get-SecureBootUEFI -Name db | Get-UEFIDatabaseSigner
.EXAMPLE
Get-SecureBootUEFI -Name dbx | Get-UEFIDatabaseSigner
.EXAMPLE
Get-SecureBootUEFI -Name pk | Get-UEFIDatabaseSigner
.EXAMPLE
(Get-SecureBootUEFI -Name kek),(Get-SecureBootUEFI -Name db) | Get-UEFIDatabaseSigner
.EXAMPLE
Get-UEFIDatabaseSigner -Variable dbx
.EXAMPLE
Get-UEFIDatabaseSigner -Variable kek,pk,db
.EXAMPLE
Get-UEFIDatabaseSigner -File .\DBXUpdate.bin
.INPUTS
System.String
Microsoft.SecureBoot.Commands.UEFIEnvironmentVariable
Accepts the output of Get-SecureBootUEFI over the pipeline.
.OUTPUTS
Outputs a custom object consisting of banned SHA256 hashes and the respective "owner" of each hash.
"77fa9abd-0359-4d32-bd60-28f4e78f784b" refers to Microsoft as the owner.
.NOTES
Modified by @p0w3rsh3ll
Split-DbxAuthInfo is from https://www.powershellgallery.com/packages/SplitDbxContent/1.0/Content/SplitDbxContent.ps1
DBX Bin files can be found on these 2 sites:
https://github.com/microsoft/secureboot_objects/releases/
https://github.com/fwupd/dbx-firmware
#>
[CmdletBinding(DefaultParameterSetName='Name')]
Param (
[Parameter(ParameterSetName = 'Name')]
[Parameter()]
[ValidateSet('kek','pk','db','dbx')]
[string[]]$Variable='dbx',
[Parameter(ParameterSetName = 'FilePath')]
[Parameter()]
[ValidateScript({Test-Path -Path $_ -PathType Leaf})]
[string]$File,
[Parameter(ParameterSetName = 'Input')]
[Parameter(ValueFromPipeline)]
[ValidateScript({ ($_.GetType().Fullname -eq 'Microsoft.SecureBoot.Commands.UEFIEnvironmentVariable')})]
$InputObject
)
Begin {
$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
}
$Var = New-Object System.Collections.ArrayList
Function Split-DbxAuthInfo {
[CmdletBinding()]
[OutputType([System.Byte[]])]
Param(
[Parameter(Mandatory)]
[string]$FilePath
)
Begin {
Switch ($PSVersionTable.PSEdition) {
'Core' { $HT = @{ AsByteStream = [switch]::Present }}
'Desktop'{ $HT = @{ Encoding = 'Byte' }}
}
}
Process {
Try {
$rawfile = (Get-Content -Path "$($FilePath)" @HT -ErrorAction Stop)
} catch {
throw $_
return
}
$chop = $rawfile[40..($rawfile.Length - 1)]
if ($chop[0] -eq 0x30 -and $chop[1] -eq 0x82) {
# Signature is known to be ASN size plus header of 4 bytes
$sig_length = ($chop[2] * 256) + $chop[3] + 4
$sig = $chop[0..($sig_length - 1)]
if ($sig_length -gt ($rawfile.Length + 40)) {
throw 'Signature longer than file size!'
return
}
[Byte[]]($chop[$sig_length..($chop.Length - 1)])
} else {
$rawfile
}
}
End {}
}
}
Process {
Switch ($PSCmdlet.ParameterSetName) {
'Name' {
$Variable |
Foreach-Object {
$null = $Var.Add(
[PSCustomObject]@{
Name = $_
Object = (Get-SecureBootUEFI -Name $_)
}
)
}
break
}
'FilePath' {
$null = $Var.Add(
[PSCustomObject]@{
Name = "$($File)"
Object = [PSCustomObject]@{
Name = 'File'
Bytes = (Split-DbxAuthInfo -FilePath "$($File)")
Attribute = [string]::Empty
}
}
)
break
}
'Input' {
$InputObject |
Foreach-Object {
$null = $Var.Add(
[PSCustomObject]@{
Name = $_.Name
Object = $_
}
)
}
break
}
default {}
}
$Var |
Foreach-Object -Process {
$n = $_.Name
$v = $_.Object
try {
$MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$v.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
$Signature = 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] @{
SecureBootDBName = $n
PSTypeName = 'EFI.SignatureData'
SignatureOwner = $SignatureOwner
SignatureData = $SignatureData
}
}
[PSCustomObject] @{
SecureBootDBName = $n
PSTypeName = 'EFI.SignatureList'
SignatureType = $SignatureType
Signature = $Signature
}
} #endof while
} #enof %
}
End {}
}
Export-ModuleMember -Function 'Get-UEFIDatabaseSigner'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment