-
Notifications
You must be signed in to change notification settings - Fork 13
Added capability to audit ESP partition for revoked files #24
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
Open
sei-vsarvepalli
wants to merge
15
commits into
cjee21:main
Choose a base branch
from
sei-vsarvepalli:audit_efis
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+293
−0
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
362aa7d
Added old files
sei-vsarvepalli 4090bf8
Updated sigs match
sei-vsarvepalli 33059e1
Updates to README.md
sei-vsarvepalli 1e7d6d6
More notes after internal feedback
sei-vsarvepalli 83bc5a4
Updates to use only authenticode hash in comments
sei-vsarvepalli 2cabc00
Added SHA1 fingerprint of cert to compare - not working yet
sei-vsarvepalli a3019c7
Trying tumbprints natively
sei-vsarvepalli 3cb4aae
Thumbprint is available
sei-vsarvepalli e839467
Found the right Thumbprints to compare
sei-vsarvepalli 891cdbc
UpperVariant instead of LowerVariant
sei-vsarvepalli 5870669
Updated to specific with command line options
sei-vsarvepalli 681dfde
Updated.Screenshot
sei-vsarvepalli c5380f0
Updated README section
sei-vsarvepalli bd52975
Updated a little more after student's feedback
sei-vsarvepalli 8513e4d
SBAT check is also missing
sei-vsarvepalli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| :: Created for cjee21/Check-UEFISecureBootVariables | ||
| @echo off | ||
| title Scan EFI files against Microsoft DBX JSON | ||
|
|
||
| :: NOTE: Replace URL with a raw URL or use -MsftJsonPath to a local file. | ||
| set MSFT_JSON_URL=https://raw.githubusercontent.com/microsoft/secureboot_objects/main/PreSignedObjects/DBX/dbx_info_msft_latest.json | ||
|
|
||
| powershell -ExecutionPolicy Bypass -Command "& '%~dp0ps\Find-EfiFilesRevokedByDbx.ps1' -ScanESP -ScanDefaultPaths -MatchMode MsftJson -MsftJsonUrl '%MSFT_JSON_URL%'" | ||
|
|
||
| echo. | ||
| pause |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,258 @@ | ||
| # Created for cjee21/Check-UEFISecureBootVariables | ||
| # Purpose: Walk EFI binaries and warn if they match revocations via: | ||
| # - file hash (Authenticode hash if you wire it in later) | ||
| # - signer certificate match (X509 DER match) against current DBX (EFI_CERT_X509_GUID) | ||
| # Also supports checking against microsoft/secureboot_objects dbx_info_msft_latest.json. | ||
|
|
||
| [CmdletBinding()] | ||
| param( | ||
| # Root directories to scan for .efi files (optional) | ||
| [string[]] $Paths, | ||
|
|
||
| # If set, will mount ESP to S: (mountvol s: /s) and scan it (default: true) | ||
| [switch] $ScanESP = $true, | ||
|
|
||
| # Helper flag: scan common OS paths too (default: false) | ||
| [switch] $ScanDefaultPaths = $false, | ||
|
|
||
| # Which revocation source(s) to match against | ||
| [ValidateSet('CurrentDbx','MsftJson','Both')] | ||
| [string] $MatchMode = 'CurrentDbx', | ||
|
|
||
| # Optional: local path to dbx_info_msft_latest.json | ||
| [string] $MsftJsonPath, | ||
|
|
||
| # Optional: URL to download dbx_info_msft_latest.json | ||
| [string] $MsftJsonUrl | ||
| ) | ||
|
|
||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| Import-Module "$PSScriptRoot\Get-UEFIDatabaseSignatures.ps1" -Force | ||
| Import-Module "$PSScriptRoot\Get-EfiSignatures.ps1" -Force | ||
|
|
||
| function Get-FileSha256Hex { | ||
| param([Parameter(Mandatory)][string] $FilePath) | ||
| (Get-FileHash -Algorithm SHA256 -LiteralPath $FilePath).Hash.ToUpperInvariant() | ||
| } | ||
|
|
||
| function Get-CertDerHex { | ||
| param([Parameter(Mandatory)][System.Security.Cryptography.X509Certificates.X509Certificate2] $Cert) | ||
| ([System.BitConverter]::ToString($Cert.RawData) -replace '-', '').ToUpperInvariant() | ||
| } | ||
|
|
||
| function Get-DbxSetsFromCurrentDbx { | ||
| # Returns: | ||
| # - HashSet of SHA256 hex strings (EFI_CERT_SHA256_GUID) | ||
| # - HashSet of X509 DER hex strings (EFI_CERT_X509_GUID) | ||
| $dbx = Get-SecureBootUEFI -Name dbx | ||
| $parsed = $dbx | Get-UEFIDatabaseSignatures | ||
|
|
||
| $sha256Set = New-Object 'System.Collections.Generic.HashSet[string]' | ||
| $x509DerSet = New-Object 'System.Collections.Generic.HashSet[string]' | ||
|
|
||
| foreach ($list in $parsed) { | ||
| foreach ($entry in $list.SignatureList) { | ||
| if ($list.SignatureType -eq 'EFI_CERT_SHA256_GUID') { | ||
| [void]$sha256Set.Add(($entry.SignatureData.ToString().ToUpperInvariant())) | ||
| } elseif ($list.SignatureType -eq 'EFI_CERT_X509_GUID') { | ||
| $derHex = Get-CertDerHex -Cert $entry.SignatureData | ||
| [void]$x509DerSet.Add($derHex) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [PSCustomObject]@{ | ||
| Name = 'CurrentDbx' | ||
| Sha256Set = $sha256Set | ||
| X509DerSet = $x509DerSet | ||
| } | ||
| } | ||
|
|
||
| function Get-DbxSetsFromMsftJson { | ||
| param( | ||
| [string] $Path, | ||
| [string] $Url | ||
| ) | ||
|
|
||
| $jsonText = $null | ||
| if ($Path) { | ||
| if (-not (Test-Path -LiteralPath $Path)) { | ||
| throw "MsftJsonPath not found: $Path" | ||
| } | ||
| $jsonText = Get-Content -LiteralPath $Path -Raw | ||
| } elseif ($Url) { | ||
| # Download to memory | ||
| $jsonText = (Invoke-WebRequest -UseBasicParsing -Uri $Url).Content | ||
| } else { | ||
| throw "MatchMode requires -MsftJsonPath or -MsftJsonUrl." | ||
| } | ||
|
|
||
| $j = $jsonText | ConvertFrom-Json | ||
|
|
||
| # MSFT JSON structure: { "images": { "x64": [ { authenticodeHash, flatHash, ... }, ... ], "arm64": [ ... ] } } | ||
| $sha256Set = New-Object 'System.Collections.Generic.HashSet[string]' | ||
|
|
||
| foreach ($archProp in $j.images.PSObject.Properties) { | ||
| $archName = $archProp.Name | ||
| $items = $archProp.Value | ||
| foreach ($img in $items) { | ||
| if ($img.authenticodeHash -and $img.authenticodeHash.Trim()) { | ||
| #Focus on authenticodeHash for matches as most reliable | ||
| [void]$sha256Set.Add($img.authenticodeHash.Trim().ToUpperInvariant()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| # MSFT JSON does not directly provide DER blobs for revoked cert entries (at least in the snippet provided), | ||
| # so in MsftJson mode we can only do hash-based checks unless you add a mapping of signer certs separately. | ||
sei-vsarvepalli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| $x509DerSet = New-Object 'System.Collections.Generic.HashSet[string]' | ||
| if ($j.PSObject.Properties.Name -contains 'certificates' -and $j.certificates) { | ||
| foreach ($cert in $j.certificates) { | ||
| $tp = $cert.thumbprint | ||
| if ($tp -and $tp.Trim()) { | ||
| # normalize: remove separators/spaces just in case, and normalize case | ||
| $norm = ($tp.Trim() -replace '[^0-9a-fA-F]', '').ToUpperInvariant() | ||
|
|
||
| # optional sanity check: SHA1 thumbprints are 20 bytes => 40 hex chars | ||
| if ($norm.Length -eq 40) { | ||
| [void]$x509DerSet.Add($norm) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [PSCustomObject]@{ | ||
| Name = 'MsftJson' | ||
| Sha256Set = $sha256Set | ||
| X509DerSet = $x509DerSet | ||
| } | ||
| } | ||
|
|
||
| function Get-EfiFilesUnderPaths { | ||
| param([Parameter(Mandatory)][string[]] $RootPaths) | ||
|
|
||
| $all = New-Object System.Collections.Generic.List[string] | ||
| foreach ($root in $RootPaths) { | ||
| if (-not (Test-Path -LiteralPath $root)) { continue } | ||
| Get-ChildItem -LiteralPath $root -Recurse -File -ErrorAction SilentlyContinue | | ||
| Where-Object { $_.Extension -ieq '.efi' } | | ||
| ForEach-Object { $all.Add($_.FullName) | Out-Null } | ||
| } | ||
| $all | ||
| } | ||
|
|
||
| # Build scan roots | ||
| $scanRoots = New-Object System.Collections.Generic.List[string] | ||
|
|
||
| $didMountEsp = $false | ||
| if ($ScanESP) { | ||
| try { | ||
| mountvol s: /s | Out-Null | ||
| $didMountEsp = $true | ||
| $scanRoots.Add('S:\') | Out-Null | ||
| } catch { | ||
| Write-Warning "Could not mount ESP to S:. Run as Administrator? Continuing..." | ||
| } | ||
| } | ||
|
|
||
| if ($ScanDefaultPaths) { | ||
| # Common locations where EFI binaries may exist on the OS volume. | ||
| $scanRoots.Add("$env:SystemRoot\Boot\EFI") | Out-Null | ||
| $scanRoots.Add("$env:SystemDrive\EFI") | Out-Null | ||
| $scanRoots.Add("$env:SystemDrive\Boot") | Out-Null | ||
| } | ||
|
|
||
| if ($Paths) { | ||
| foreach ($p in $Paths) { $scanRoots.Add($p) | Out-Null } | ||
| } | ||
|
|
||
| if ($scanRoots.Count -eq 0) { | ||
| throw "No scan roots specified and ESP mount failed. Provide -Paths or run elevated." | ||
| } | ||
|
|
||
| # Load revocation sets | ||
| $revocationSets = New-Object System.Collections.Generic.List[object] | ||
|
|
||
| if ($MatchMode -eq 'CurrentDbx' -or $MatchMode -eq 'Both') { | ||
| Write-Host "Loading current DBX..." -ForegroundColor Cyan | ||
| $revocationSets.Add((Get-DbxSetsFromCurrentDbx)) | Out-Null | ||
| } | ||
|
|
||
| if ($MatchMode -eq 'MsftJson' -or $MatchMode -eq 'Both') { | ||
| Write-Host "Loading Microsoft DBX JSON..." -ForegroundColor Cyan | ||
| $revocationSets.Add((Get-DbxSetsFromMsftJson -Path $MsftJsonPath -Url $MsftJsonUrl)) | Out-Null | ||
| } | ||
|
|
||
| foreach ($s in $revocationSets) { | ||
| Write-Host ("Loaded {0}: SHA256-like={1}, X509={2}" -f $s.Name, $s.Sha256Set.Count, $s.X509DerSet.Count) | ||
| } | ||
|
|
||
| Write-Host "Scanning for EFI binaries..." -ForegroundColor Cyan | ||
| $efiFiles = Get-EfiFilesUnderPaths -RootPaths $scanRoots.ToArray() | ||
| Write-Host ("Found {0} EFI file(s)." -f $efiFiles.Count) | ||
|
|
||
| $warnCount = 0 | ||
| $idx = 0 | ||
|
|
||
| foreach ($file in $efiFiles) { | ||
| $idx++ | ||
| Write-Progress -Activity "Checking EFI files" -Status $file -PercentComplete (($idx / [Math]::Max(1, $efiFiles.Count)) * 100) | ||
|
|
||
| $fileSha = $null | ||
|
|
||
| # Signer cert DER hexes (may be empty) | ||
| $signerThumbprints = @() | ||
| try { | ||
| $sigs = Get-EfiSignatures -FilePath $file | ||
| $fileSha = $sigs.Authentihash | ||
| foreach ($sig in $sigs.Signatures) { | ||
| foreach ($c in $sig.Certificates) { | ||
sei-vsarvepalli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if ($c -and $c.Thumbprint) { | ||
| $signerThumbprints += $c.Thumbprint.ToUpperInvariant() | ||
| } | ||
| } | ||
| } | ||
| } catch {} | ||
|
|
||
| $matches = @() | ||
|
|
||
| foreach ($set in $revocationSets) { | ||
| # Hash match | ||
| if ($fileSha -and $set.Sha256Set.Contains($fileSha)) { | ||
| $matches += [PSCustomObject]@{ Source=$set.Name; Type='Hash'; Detail='SHA256(Authenticode) matches revocation list' } | ||
| } | ||
|
|
||
| # Cert match (only meaningful for CurrentDbx unless you add cert data to MsftJson mode) | ||
sei-vsarvepalli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if ($signerThumbprints.Count -gt 0 -$set.X509DerSet.Count -gt 0) { | ||
| foreach ($derHex in $signerThumbprints) { | ||
| if ($set.X509DerSet.Contains($derHex)) { | ||
| $matches += [PSCustomObject]@{ Source=$set.Name; Type='SignerCert'; Detail='Signer certificate DER matches DBX X509 revocation' } | ||
| break | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ($matches.Count -gt 0) { | ||
| $warnCount++ | ||
| Write-Host "" | ||
| Write-Host "WARNING: EFI file matches revocation list(s)" -ForegroundColor Yellow | ||
| Write-Host (" Path: {0}" -f $file) | ||
| if ($fileSha) { Write-Host (" SHA256 (Authenticode): {0}" -f $fileSha) } | ||
| if ($signerThumbprints.Count -gt 0) { | ||
| Write-Host (" Signer thumbprint(s): {0}" -f ($signerThumbprints -join ', ')) | ||
| } | ||
|
|
||
| foreach ($m in $matches) { | ||
| Write-Host (" Match: [{0}] {1} - {2}" -f $m.Source, $m.Type, $m.Detail) -ForegroundColor Yellow | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Write-Host "" | ||
| Write-Host ("Scan complete. Warnings: {0}" -f $warnCount) -ForegroundColor Cyan | ||
|
|
||
| if ($didMountEsp) { | ||
| try { mountvol s: /d | Out-Null } catch {} | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.