Repository navigation
Expand file tree
/
Copy pathInvoke-SecureBootCertUpdate_simple.ps1
More file actions
242 lines (223 loc) Β· 12.8 KB
/
Copy pathInvoke-SecureBootCertUpdate_simple.ps1
File metadata and controls
242 lines (223 loc) Β· 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
ο»Ώ#Requires -RunAsAdministrator
<#
.SYNOPSIS
Einmaliges Einleiten des Secure Boot 2023-Zertifikat-Updates (einfache Variante).
.DESCRIPTION
PrΓΌft zunΓ€chst ob das Windows UEFI CA 2023 Zertifikat bereits in der UEFI-DB vorhanden ist.
Falls nicht: Registry-Wert setzen, Scheduled Task starten, Ergebnis zurΓΌckgeben.
Auf neueren Systemen (COM-Handler TpmTasks.dll) wird das Zertifikat direkt eingetragen.
Auf Γ€lteren Systemen (SecureBootEncodeUEFI.exe) ist ein Neustart erforderlich.
FΓΌr den vollstΓ€ndigen phasengesteuerten Update-Prozess mit State-Tracking:
β Invoke-SecureBootCertUpdate.ps1
.PARAMETER AutoConfirm
UnterdrΓΌckt die interaktive Neustart-Abfrage. FΓΌr Remote-Betrieb via Invoke-Command
immer angeben, da Read-Host in Remote-Sessions hΓ€ngt.
.EXAMPLE
.\Invoke-SecureBootCertUpdate_simple.ps1
.\Invoke-SecureBootCertUpdate_simple.ps1 -AutoConfirm
Invoke-Command -ComputerName SERVER01 -ScriptBlock { & $using:script -AutoConfirm }
#>
[CmdletBinding()]
param(
[switch]$AutoConfirm
)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Konstanten
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
$REG_PATH = "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot"
$REG_NAME = "AvailableUpdates"
# Zusammensetzung 0x5944:
# 0x0004 = KEK: Microsoft Corporation KEK 2K CA 2023 eintragen
# 0x0040 = DB: Windows UEFI CA 2023 eintragen β PrimΓ€rziel
# 0x0100 = Bootmgr: Boot Manager mit 2023-Signatur aktualisieren
# 0x0800 = DB: Microsoft Option ROM UEFI CA 2023 (konditional via 0x4000)
# 0x1000 = DB: Microsoft UEFI CA 2023 (konditional via 0x4000)
# 0x4000 = Modifier: 0x0800/0x1000 nur eintragen wenn UEFI CA 2011 bereits in DB
$REG_VALUE = 0x5944
$TASK_PATH = "\Microsoft\Windows\PI\"
$TASK_NAME = "Secure-Boot-Update"
$CERT_SUBJECT = 'Windows UEFI CA 2023'
$COM_CLSID = "{5014B7C8-934E-4262-9816-887FA745A6C4}"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# X.509-Zertifikat korrekt aus EFI_SIGNATURE_LIST parsen
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
function Test-UEFICA2023InDb {
param([byte[]]$DbBytes)
if (-not $DbBytes -or $DbBytes.Length -lt 28) { return $false }
$x509Guid = [System.Guid]::new('a5c059a1-94e4-4aa7-87b5-ab155c2bf072')
$pos = 0
while ($pos + 28 -le $DbBytes.Length) {
$listGuid = [System.Guid]::new([byte[]]$DbBytes[$pos..($pos + 15)])
$listSize = [BitConverter]::ToUInt32($DbBytes, $pos + 16)
$hdrSize = [BitConverter]::ToUInt32($DbBytes, $pos + 20)
$sigSize = [BitConverter]::ToUInt32($DbBytes, $pos + 24)
if ($listSize -eq 0 -or $sigSize -le 16) { break }
if ($listGuid -eq $x509Guid) {
$entry = $pos + 28 + [int]$hdrSize
$end = $pos + [int]$listSize
while ($entry + [int]$sigSize -le $end) {
try {
$certBytes = $DbBytes[($entry + 16)..($entry + [int]$sigSize - 1)]
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([byte[]]$certBytes)
if ($cert.Subject -match [regex]::Escape($CERT_SUBJECT)) { return $true }
}
catch { }
$entry += [int]$sigSize
}
}
$pos += [int]$listSize
}
return $false
}
function Suspend-BitLockerForUpdate {
$result = @{ Suspended = $false; Volumes = @(); Message = '' }
try {
$activeVols = Get-BitLockerVolume -ErrorAction Stop |
Where-Object { $_.ProtectionStatus -eq 'On' }
if (-not $activeVols) {
$result.Message = 'Kein aktives BitLocker-Volume gefunden.'
return $result
}
foreach ($vol in $activeVols) {
Suspend-BitLocker -MountPoint $vol.MountPoint -RebootCount 2 -ErrorAction Stop
$result.Volumes += $vol.MountPoint
}
$result.Suspended = $true
$result.Message = "BitLocker ausgesetzt (RebootCount=2) auf: $($result.Volumes -join ', ')"
}
catch {
$result.Message = "BitLocker-Suspend fehlgeschlagen: $_"
}
return $result
}
function New-Result {
param(
[string]$Status,
[string]$Action,
[string]$Message,
[bool]$RebootRequired = $false,
[bool]$BitLockerSuspended = $false
)
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
Timestamp = Get-Date
Status = $Status
Action = $Action
Message = $Message
RebootRequired = $RebootRequired
BitLockerSuspended = $BitLockerSuspended
}
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 1. Secure Boot Status prΓΌfen
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
$secureBootEnabled = $false
try {
$secureBootEnabled = Confirm-SecureBootUEFI
}
catch { }
if (-not $secureBootEnabled) {
New-Result -Status 'SKIPPED' -Action 'Keine Aktion' `
-Message 'Secure Boot ist nicht aktiv oder nicht erkennbar. Update hΓ€tte keinen Effekt.'
return
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 2. Pre-Check: Zertifikat bereits vorhanden?
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
try {
$db = Get-SecureBootUEFI -Name db -ErrorAction Stop
if (Test-UEFICA2023InDb -DbBytes $db.bytes) {
New-Result -Status 'OK' -Action 'Keine Aktion' `
-Message "'$CERT_SUBJECT' ist bereits in der Secure Boot DB. Kein Update erforderlich."
return
}
}
catch {
New-Result -Status 'FEHLER' -Action 'Abgebrochen' `
-Message "Secure Boot DB konnte nicht gelesen werden: $_"
return
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 3. Task-Existenz prΓΌfen
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
$task = Get-ScheduledTask -TaskName $TASK_NAME -TaskPath $TASK_PATH -ErrorAction SilentlyContinue
if (-not $task) {
New-Result -Status 'FEHLER' -Action 'Abgebrochen' `
-Message "Scheduled Task '$TASK_NAME' nicht gefunden. Aktuelle Windows Updates einspielen und erneut versuchen."
return
}
# COM-Handler vorhanden? Entscheidet ΓΌber Wartezeit und Sofortverifikation
$comHandlerRegistered = $false
try {
$dll = Get-ItemProperty "HKLM:\SOFTWARE\Classes\CLSID\$COM_CLSID\InprocServer32" -ErrorAction SilentlyContinue
if ($dll -and $dll.'(Default)' -and (Test-Path $dll.'(Default)')) {
$comHandlerRegistered = $true
}
}
catch { }
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 4. BitLocker aussetzen (PCR 7 Γ€ndert sich durch DB-Update β sonst Recovery)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
$blResult = Suspend-BitLockerForUpdate
if ($blResult.Suspended) {
Write-Verbose "BitLocker: $($blResult.Message)"
} else {
Write-Warning "BitLocker-Suspend: $($blResult.Message) β Recovery-Key bereithalten falls BitLocker aktiv ist!"
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 5. Registry setzen
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Write-Verbose "Setze $REG_NAME = 0x$("{0:X4}" -f $REG_VALUE)"
try {
if (-not (Test-Path $REG_PATH)) { New-Item -Path $REG_PATH -Force | Out-Null }
Set-ItemProperty -Path $REG_PATH -Name $REG_NAME -Value $REG_VALUE -Type DWord -ErrorAction Stop
}
catch {
New-Result -Status 'FEHLER' -Action 'Registry-Fehler' `
-Message "Fehler beim Schreiben der Registry: $_" `
-BitLockerSuspended $blResult.Suspended
return
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 6. Task starten
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Write-Verbose "Starte Task '$TASK_NAME'..."
try {
Start-ScheduledTask -TaskName $TASK_NAME -TaskPath $TASK_PATH -ErrorAction Stop
}
catch {
New-Result -Status 'FEHLER' -Action 'Task-Fehler' `
-Message "Fehler beim Starten des Scheduled Tasks: $_" `
-BitLockerSuspended $blResult.Suspended
return
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 7. Sofortverifikation (nur COM-Handler schreibt direkt ins UEFI-NVRAM)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
if ($comHandlerRegistered) {
Write-Verbose "COM-Handler erkannt β warte 60 Sekunden auf NVRAM-Commit..."
Start-Sleep -Seconds 60
try {
$dbAfter = Get-SecureBootUEFI -Name db -ErrorAction SilentlyContinue
if ($dbAfter -and (Test-UEFICA2023InDb -DbBytes $dbAfter.bytes)) {
New-Result -Status 'OK' -Action 'Direkt eingetragen' `
-Message "'$CERT_SUBJECT' wurde direkt in die DB eingetragen. Power Off + Power On empfohlen um NVRAM dauerhaft zu verankern." `
-RebootRequired $true -BitLockerSuspended $blResult.Suspended
return
}
}
catch { }
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 8. Reboot erforderlich (Γ€lterer SecureBootEncodeUEFI.exe Mechanismus)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
$rebootMsg = "Registry gesetzt und Task gestartet. Neustart erforderlich damit die UEFI-Firmware das Zertifikat beim Booten eintrΓ€gt. " +
"In manchen FΓ€llen ist ein zweiter Neustart nΓΆtig. Danach mit Test-SecureBootCert2023.ps1 prΓΌfen."
if (-not $AutoConfirm) {
$response = Read-Host "`nSystem jetzt neu starten? (J/N)"
if ($response -match '^[JjYy]') {
Restart-Computer -Force
return
}
}
New-Result -Status 'REBOOT_REQUIRED' -Action 'Update eingeleitet' -Message $rebootMsg -RebootRequired $true -BitLockerSuspended $blResult.Suspended