Skip to content

10x faster 'Check UEFI PK, KEK, DB and DBX'#41

Open
jcoester wants to merge 11 commits into
cjee21:mainfrom
jcoester:main
Open

10x faster 'Check UEFI PK, KEK, DB and DBX'#41
jcoester wants to merge 11 commits into
cjee21:mainfrom
jcoester:main

Conversation

@jcoester

@jcoester jcoester commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Proposing to remove the Write-Progress bar entirely.
The improved runtime is faster than most humans should be able to read.

Show-CheckDBX with currently 431 + 278 checks:

Run Before After Difference
1 12.5 s 1.7 s - 10.8 s
2 11.4 s 1.7 s - 9.7 s
3 10.9 s 1.6 s - 9.3 s

- Check against latest DBX revocations (Staged or GitHub)
- Refresh view by looping
- Clarify SVN origin
- Simplify arch check (faster runtime)
- Remove hardcoded bin file names, new expected pattern: "DBXUpdate_{YYYY-MM-DD}_{Version}_{Arch}.bin"

DBXUpdate_2025-02-25_v1.4.0_arm.bin
DBXUpdate_2025-02-25_v1.4.0_arm64.bin
DBXUpdate_2025-10-14_v1.6.0_amd64.bin
DBXUpdate_2025-10-14_v1.6.0_x86.bin
@jcoester

jcoester commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Proposing various changes that improve the runtime from up to 15 s to down to less than 1 s.
Goal to simplify the output, improve usability and avoid confusion.

  • Check against latest DBX revocations only (Staged or GitHub)
  • Refresh view by looping. No script restarting required
  • Clarify SVN field to be FirmwareSVN, not the File SVN
  • Simplify arch check, faster runtime and possibly less error prone
  • Remove hardcoded bin file names, new expected pattern: DBXUpdate_{YYYY-MM-DD}_{Version}_{Arch}.bin

Example: Staged most recent
A

Example: No staged available, or secureboot_objects DBX file most recent
B

Tested with all archs.

amd64 (actual)
v1.6.0 (14 Okt 2025) : FAIL: 154 failures, 277 successes detected
Staged (14 Apr 2026) : SUCCESS: 278 successes detected 
----------------------------------------------------------------------
x86 (emulated)
v1.6.0 (14 Okt 2025) : FAIL: 44 failures, 0 successes detected
----------------------------------------------------------------------
arm64 (emulated)
v1.4.0 (25 Feb 2025) : FAIL: 26 failures, 0 successes detected
----------------------------------------------------------------------
arm (emulated)
v1.4.0 (25 Feb 2025) : FAIL: 110 failures, 0 successes detected

jcoester added 2 commits June 7, 2026 18:34
DBXUpdate_2025-10-14_v1.6.0_amd64.bin to
DBXUpdate_v1.6.0_2025-10-14_amd64.bin
@jcoester jcoester changed the title Improve Show-CheckDBX runtime by 85 % 10x faster 'Check UEFI PK, KEK, DB and DBX' performance Jun 7, 2026
@jcoester jcoester changed the title 10x faster 'Check UEFI PK, KEK, DB and DBX' performance 10x faster 'Check UEFI PK, KEK, DB and DBX' Jun 7, 2026
@cjee21

cjee21 commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Proposing to remove the Write-Progress bar entirely.
The improved runtime is faster than most humans should be able to read.

So the progress bar is actually slowing it. That code is from Microsoft (https://gist.github.com/out0xb2/f8e0bae94214889a89ac67fceb37f8c0).

Check against latest DBX revocations only (Staged or GitHub)

The one on GitHub is the authoritative one and the one picked up by OEMs and other OS for distribution so I would keep that especially that it currently has more hashes. The one shipped in Windows may be faulty seeing how Microsoft still has not clarified the removal of hashes or update the one on GitHub until now.

Refresh view by looping. No script restarting required

This is going to get complaints from people who automate the script.

Clarify SVN field to be FirmwareSVN, not the File SVN

This is not needed as that section is showing the contents of the Current DBX.

$arch = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes").OSArchitecture

Won't this throw an exception if the reg key does not exist?

Anyway, I cannot really review right now since I keep getting "504 Gateway Time-out" on GitHub. Also thinking that since we are going to change so much, maybe we should just abandon the bin files completely and just use the JSON file for everything. Microsoft generates the bin files from the JSON anyway. So the fact that the bin shipped with Windows does not match the JSON means something is wrong. The existing script is from back in the day when there is only CSV but no JSON file of all the contents.

@jcoester

jcoester commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Thinking that since we are going to change so much, maybe we should just abandon the bin files completely and just use the JSON file for everything. Microsoft generates the bin files from the JSON anyway.

Fantastic idea! Ran a benchmark and checking the entire DBX against the JSON is now 50 ms instead of 10.000+ ms.

$arch = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes").OSArchitecture

Won't this throw an exception if the reg key does not exist?

Yes, thanks. Will add -ErrorAction SilentlyContinue to it. The registry value cuts the execution time by more than a second compared to Get-CimInstance -ClassName Win32_Processor, so should probably be the default option.

Will revert the other changes as you suggested - agree with checking both JSON and Staged, SVN labels as you had them and remove the loop.

@cjee21

cjee21 commented Jun 8, 2026

Copy link
Copy Markdown
Owner

and for the JSON, since the JSON on GitHub is updated late usually, there is also a copy of the JSON shipped in Windows that maybe can be used. The issue is the last time I checked, the JSON in Windows has up-to-date hashes but old SVN whereas the one on GitHub now has updated SVN but not updated hash.

@cjee21

cjee21 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Since new monthly update is out and contains new DBX hashes and the new signed bin file is available, I picked the speed improvement commit from this and updated the DBX check. There is no need to check Windows staged anymore since updated bin file contains all up-to-date hashes. For this PR maybe you can make it use JSON for checking instead. I am thinking to make use of the isOptional field in the JSON as well. So only flag the isOptional ones red when missing if the PCA2011 is not revoked. Need to wait for Microsoft to finalize the new updated JSON before the copy here can be updated.

@jcoester

Copy link
Copy Markdown
Contributor Author

there is also a copy of the JSON shipped in Windows that maybe can be used

Is the FilePath known?

There is no need to check Windows staged anymore since updated bin file contains all up-to-date hashes.

Should it be kept, in case it differs in the future again? But only show if it differs.

For this PR maybe you can make it use JSON for checking instead. I am thinking to make use of the isOptional field in the JSON as well. So only flag the isOptional ones red when missing if the PCA2011 is not revoked.

Really like the isOptional idea and have the code ready. Will do a PR within the next days as I'm testing some more conceptual ideas.

@cjee21

cjee21 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Is the FilePath known?

Get-SecureBootUEFI -Name DBX -Decoded can show the info of the hashes so it has to be somewhere in the powershell secureboot module directory. It may not be the same format as the public JSON though. I didn't take note of the path when I found it previously.

Should it be kept, in case it differs in the future again? But only show if it differs.

The issue is how to merge the info. Maybe just parse the JSON shipped in Windows then if there is a new hash not in the other JSON, add/merge to the check but what date.

Will do a PR within the next days as I'm testing some more conceptual ideas.

Can just force push this PR, overwriting the commits with new ones and rename the PR as needed.

@jcoester

Copy link
Copy Markdown
Contributor Author

Get-SecureBootUEFI -Name DBX -Decoded can show the info of the hashes so it has to be somewhere in the powershell secureboot module directory. It may not be the same format as the public JSON though. I didn't take note of the path when I found it previously.

Its Join-Path (Split-Path (Get-Command Get-SecureBootUEFI).DLL -Parent) "hashes.json" then.

Also under found under following. Its the latest SVN 9.0 JSON.
"C:\Windows\System32\WindowsPowerShell\v1.0\Modules\SecureBoot\hashes.json"
"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules\SecureBoot\hashes.json"

The issue is how to merge the info. Maybe just parse the JSON shipped in Windows then if there is a new hash not in the other JSON, add/merge to the check but what date.

Can just do a background comparison of JSON vs STAGED, no? And only if they differ, add a new line with the results. Like:

Current UEFI DBX
Latest revocations  : SUCCESS: 443 successes detected.
Staged revocations  : SUCCESS: 289 successes detected. # Only show line if different
Windows Bootmgr SVN : 9.0
Windows cdboot SVN  : 3.0
Windows wdsmgfw SVN : 3.0

@cjee21

cjee21 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Just that people keep asking what is staged? what's the difference? Is it fine if one of the results are red? etc... also the JSON actually does not matched the staged binaries shipped in Windows so we cannot actually call that staged. Someone probably messed up again. As you see, the staged is only 200+ hashes and that is not correct. Microsoft confirmed that no hashes are supposed to be removed.

jcoester added 2 commits June 12, 2026 16:11
PartitionStyle 'GPT' required for UEFI/Secure Boot. Legacy 'MBR' should indicate a non-compliant system and trigger warning with guidance.
@cjee21

cjee21 commented Jun 12, 2026

Copy link
Copy Markdown
Owner

I think just show warning below secure boot status if the status is disabled. If enabled then sure is GPT, no need check (it's already kinda out of scope for the script that is for checking UEFI variables). MBR disk on UEFI systems should be rare. Only self-installs with user error should end up like that.

- Change two states (Check, Cross) into three states: PRESENT, REVOKED, ABSENT.
- Take latest JSON (GitHub or Local Windows folder) as baseline for all comparisons
- Add expiration date
- Incorportate JSON revocation into
- Add tag to Baseline certs, easier identification
- Remove all binary reads to dramatically improve runtime
- Split DBX revoc. checks into Main and isOptional
- Read UEFI only once
- Add SetupMode and CA2023 Status and Capability.
- Add Default DBX states.
@jcoester

jcoester commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Due to various conceptional changes I created a copy of the script, so it can be executed next to the existing one.
Should be de-duplicated once finalized. Meant as a box of ideas, can certainly be adjusted.

jcoester added 5 commits June 13, 2026 19:06
Due to Microsoft local JSON versioning missing the isOptional tag
Add various minor visual improvements
Further add var. total bytes size and error codes
- Reduce severity of cert disclaimer
- Add version to ComputerSystemProduct info, don't show BaseBoard info if prior available
- Implement arch fallback from main
@jcoester

jcoester commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Adding this as the final conceptual commit. Total runtime for compliant systems about 1 sec.

Core features not yet in main:

  • Check entirely against JSON baseline
  • Vulnerable cert disclaimer
  • Separate isOptional DBX check
  • KEK Update file lookup via PK serial no. against kek_update_map.json
  • PRESENT-REVOKED-ABSENT instead of Y/N (which might be misleading for vulnerable/legacy certs)
  • Show Secure Boot Setup Mode or User Mode
  • Show Secure Boot servicing attributes header (this could be copied or moved to the Windows State cmd)
  • Show cert organization and expiration date
  • Show error code for missing SB variables (taken over from your latest commits)
  • Show total bytes size of all SB variables (update can fail due to lack of NVRAM)
  • Show MBR partition check and MBR2GPT disclaimer as this is a major roadblock for SB to be enabled
  • Remove any checks against staged. (you mentioned you dont consider them necessary anymore (at last currently))

Compliant state (left new, right old)
Screenshot 2026-06-17 231555-success
Uncompliant state (left new, right old)
Screenshot 2026-06-17 220107-fail

@cjee21

cjee21 commented Jul 12, 2026

Copy link
Copy Markdown
Owner

I was not on GitHub much recently. Also waiting to see how Microsoft deals with the various inconsistencies and if the JSON is reliable.

Regarding the vulnerable cert, I plan to put that in DBX section and only after Windows begins automatically revoking PCA 2011 and most bootable media has been migrated to 2023. At the moment it is still needed by some users so do not want to put a red alert there and make the average user concerned.

I am not sure if checking KEK update is needed. Windows should also auto apply if available and linking to a bin file will make users ask many questions regarding if it is needed to do manually and how to do it.

Revocation is independent of whether the cert is present. Even when cert is not present, revoking it or not has a difference. A cert that is not present but revoked will block any dual-signed EFI files from booting even if the other signature is trusted and not revoked.

If you want to change Secure Boot mode check, ensure it still properly shows non-UEFI/no-SecureBoot systems as 'Not supported'. The current script was tested to be detecting this properly and skipping all checks when not in supported state. There is no non-UEFI system available here to test now.

Cert expiration dates are purposely not shown. There was a request previously from user who thinks expiration dates matter. Expiration dates are meaningless to UEFI. It does not care about them. Showing expiration dates will make some users misunderstand that their system will stop working upon expiry or that they are secure without needing to revoke/remove an old cert because it has expired anyway. Also adds unneeded info and clutter. An expired PK can also still be used to sign updates by some OEMs. Can see PR 310 at Microsoft's repo for example. So expired PK does not mean system can no longer be updated too.

Secure Boot servicing attributes header and MBR detection is more suitable in Check Windows state as they are regarding Windows installation and not UEFI variables. We cannot conclude things from AvailableUpdates too. When all updates are completed automatically by Windows, it is 0x0, not 0x4000. 0x4000 also means something else and not completed. Any combination of bits are also possible, not everyone starts with 0x5944.

Will leave this PR here for the time being while seeing what happens with Microsoft's DBX inconsistencies. I may cherry pick some things (like total variable size) when I am free. I also already changed the cert parsing to be proper and checking certs using their fingerprint rather than names.

@jcoester

Copy link
Copy Markdown
Contributor Author

Thanks for the elaborate reply.

Only after Windows begins automatically revoking PCA 2011 and most bootable media has been migrated to 2023. At the moment it is still needed by some users so do not want to put a red alert there and make the average user concerned.

Could maybe gray the PCA2011 vulnerability disclaimer in both cases. SVNs also red when unapplied, which maybe should be white/gray, as it’s also optional hardening. Knowing what exists is always harder than figuring out what to do with given information. Maybe something like:

Main EFI revocations : SUCCESS: 443 successes.
Windows Bootmgr SVN  : Not applied (Optional) 
Windows cdboot SVN   : Not applied (Optional) 
Windows wdsmgfw SVN  : Not applied (Optional) 

I am not sure if checking KEK update is needed. Windows should also auto apply if available and linking to a bin file will make users ask many questions regarding if it is needed to do manually and how to do it.

Some boards seem to have broken "Append KEK" implementations, so not possible for Windows to auto apply the KEK (on my MSI legacy board too). One needs to manually set a new KEK bin file. Implemented currently to only show if a KEK update file is available and when KEK 2023 is not present yet. Maybe should even check if the auto apply failed before, to avoid confusion (will need to look up the EventID, probably 1796.

A cert that is not present but revoked will block any dual-signed EFI files from booting even if the other signature is trusted and not revoked.

To my knowledge there is no difference in on-machine behaviour. Made three observations to back that up:

  • When PCA 2011 is not present in DB, the MS revocation command won’t add it to DBX.
  • Flickdm also said revocations are only needed if the trust-anchor is present
  • https://github.com/microsoft/secureboot_objects/releases/download/v1.6.5/edk2-x64-secureboot-binaries.zip has the packages MicrosoftOnly / MicrosoftAndOptionRoms / MicrosoftAndThirdParty and neither adds a cert to DBX, that was never present in DB.
  • Dual-signed files should pass if any certs is present, in which case absent vs revoked of the other signer should not make a difference.

If you want to change Secure Boot mode check, ensure it still properly shows non-UEFI/no-SecureBoot systems as 'Not supported'. The current script was tested to be detecting this properly and skipping all checks when not in supported state. There is no non-UEFI system available here to test now.

Its Enabled / Disabled only. Switched because it’s much faster runtime. Maybe could only distinct between Disabled and Not supported if it isn’t enabled. Will be much faster for most users (~1s), and slightly slower for few (~50ms).

Cert expiration dates are purposely not shown.

Was thinking its interesting to know when the next KEK update is required, which is 12 years away, so eases the mind a bit. Could maybe only show for KEK 2K CA 2023, the others not so interesting.

Secure Boot servicing attributes header and MBR detection is more suitable in Check Windows state as they are regarding Windows installation and not UEFI variables. We cannot conclude things from AvailableUpdates too. When all updates are completed automatically by Windows, it is 0x0, not 0x4000. 0x4000 also means something else and not completed. Any combination of bits are also possible, not everyone starts with 0x5944.

Definitely makes sense for Check Windows state, though was thinking it could be nice to have an overall script now that the EFI mounting is safe and the DBX check method is blazing fast.

Will leave this PR here for the time being while seeing what happens with Microsoft's DBX inconsistencies. I may cherry pick some things (like total variable size) when I am free. I also already changed the cert parsing to be proper and checking certs using their fingerprint rather than names.

Appreciate your efforts with the tool. Thank you, @cjee21.

@cjee21

cjee21 commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Dual-signed files should pass if any certs is present, in which case absent vs revoked of the other signer should not make a difference.

That is true if none are revoked but if one is revoked, file will always be blocked. DBX always takes priority. As long as a related cert or hash is in DBX, file is blocked before checking DB. That is if the UEFI implementation follows UEFI specifications exactly.

Was thinking its interesting to know when the next KEK update is required, which is 12 years away, so eases the mind a bit.

Well known certs already have known valid periods. Don't really need this script to know.

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

Successfully merging this pull request may close these issues.

2 participants