| Server IP : 209.209.40.120 / Your IP : 216.73.217.112 Web Server : Microsoft-IIS/10.0 System : Windows NT NEWWWW 10.0 build 17763 (Windows Server 2019) i586 User : NEWWWW$ ( 0) PHP Version : 8.3.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Windows/SecureBoot/ExampleRolloutScripts/ |
Upload File : |
<#
.SYNOPSIS
Detects Secure Boot certificate update status for fleet-wide monitoring.
.DESCRIPTION
This detection script collects Secure Boot status, certificate update registry values,
and device information. It outputs a JSON string for monitoring and reporting.
Compatible with Intune Remediations, GPO-based collection, and other management tools.
No remediation script is needed — this is monitoring only.
Exit 0 = "Without issue" (certificates updated)
Exit 1 = "With issue" (certificates not updated — informational only)
.PARAMETER OutputPath
Optional. Path to a folder where the JSON file will be saved.
If provided, saves HOSTNAME_latest.json to this folder.
If not provided, outputs JSON to stdout (original behavior).
.EXAMPLE
# Output to stdout (Intune/SCCM detection)
.\Detect-SecureBootCertUpdateStatus.ps1
.EXAMPLE
# Save to network share (GPO deployment)
.\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"
.NOTES
Registry paths per https://aka.ms/securebootplaybook:
HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot
HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#>
param(
[Parameter(Mandatory = $false)]
[string]$OutputPath
)
# Download URL: https://aka.ms/getsecureboot -> "Deployment and Monitoring Samples"
# Note: This script runs on endpoints to collect Secure Boot status data.
# 1. HostName
# PS Version: All | Admin: No | System Requirements: None
try {
$hostname = $env:COMPUTERNAME
if ([string]::IsNullOrEmpty($hostname)) {
Write-Warning "Hostname could not be determined"
$hostname = "Unknown"
}
Write-Host "Hostname: $hostname"
} catch {
Write-Warning "Error retrieving hostname: $_"
$hostname = "Error"
Write-Host "Hostname: $hostname"
}
# 2. CollectionTime
# PS Version: All | Admin: No | System Requirements: None
try {
$collectionTime = Get-Date
if ($null -eq $collectionTime) {
Write-Warning "Could not retrieve current date/time"
$collectionTime = "Unknown"
}
Write-Host "Collection Time: $collectionTime"
} catch {
Write-Warning "Error retrieving date/time: $_"
$collectionTime = "Error"
Write-Host "Collection Time: $collectionTime"
}
# Registry: Secure Boot Main Key (3 values)
# 3. SecureBootEnabled
# PS Version: 3.0+ | Admin: May be required | System Requirements: UEFI/Secure Boot capable system
try {
$secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop
Write-Host "Secure Boot Enabled: $secureBootEnabled"
} catch {
Write-Warning "Unable to determine Secure Boot status via cmdlet: $_"
# Try registry fallback
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop
$secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled
Write-Host "Secure Boot Enabled: $secureBootEnabled"
} catch {
Write-Warning "Unable to determine Secure Boot status via registry. System may not support UEFI/Secure Boot."
$secureBootEnabled = $null
Write-Host "Secure Boot Enabled: Not Available"
}
}
# 4. HighConfidenceOptOut
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop
$highConfidenceOptOut = $regValue.HighConfidenceOptOut
Write-Host "High Confidence Opt Out: $highConfidenceOptOut"
} catch {
# HighConfidenceOptOut is optional - not present on most systems
$highConfidenceOptOut = $null
Write-Host "High Confidence Opt Out: Not Set"
}
# 4b. MicrosoftUpdateManagedOptIn
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop
$microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn
Write-Host "Microsoft Update Managed Opt In: $microsoftUpdateManagedOptIn"
} catch {
# MicrosoftUpdateManagedOptIn is optional - not present on most systems
$microsoftUpdateManagedOptIn = $null
Write-Host "Microsoft Update Managed Opt In: Not Set"
}
# 5. AvailableUpdates
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop
$availableUpdates = $regValue.AvailableUpdates
if ($null -ne $availableUpdates) {
# Convert to hexadecimal format
$availableUpdatesHex = "0x{0:X}" -f $availableUpdates
Write-Host "Available Updates: $availableUpdatesHex"
} else {
Write-Host "Available Updates: Not Available"
}
} catch {
Write-Warning "AvailableUpdates registry key not found or inaccessible"
$availableUpdates = $null
Write-Host "Available Updates: Not Available"
}
# 5b. AvailableUpdatesPolicy (GPO-controlled persistent value)
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop
$availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy
if ($null -ne $availableUpdatesPolicy) {
# Convert to hexadecimal format
$availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy
Write-Host "Available Updates Policy: $availableUpdatesPolicyHex"
} else {
Write-Host "Available Updates Policy: Not Set"
}
} catch {
# AvailableUpdatesPolicy is optional - only set when GPO is applied
$availableUpdatesPolicy = $null
Write-Host "Available Updates Policy: Not Set"
}
# Registry: Servicing Key (3 values)
# 6. UEFICA2023Status
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop
$uefica2023Status = $regValue.UEFICA2023Status
Write-Host "Windows UEFI CA 2023 Status: $uefica2023Status"
} catch {
Write-Warning "Windows UEFI CA 2023 Status registry key not found or inaccessible"
$uefica2023Status = $null
Write-Host "Windows UEFI CA 2023 Status: Not Available"
}
# 7. UEFICA2023Error
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop
$uefica2023Error = $regValue.UEFICA2023Error
Write-Host "UEFI CA 2023 Error: $uefica2023Error"
} catch {
# UEFICA2023Error only exists if there was an error - absence is good
$uefica2023Error = $null
Write-Host "UEFI CA 2023 Error: None"
}
# 8. UEFICA2023ErrorEvent
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop
$uefica2023ErrorEvent = $regValue.UEFICA2023ErrorEvent
Write-Host "UEFI CA 2023 Error Event: $uefica2023ErrorEvent"
} catch {
$uefica2023ErrorEvent = $null
Write-Host "UEFI CA 2023 Error Event: Not Available"
}
# Registry: Device Attributes (7 values: 9-15)
# 9. OEMManufacturerName
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMManufacturerName -ErrorAction Stop
$oemManufacturerName = $regValue.OEMManufacturerName
if ([string]::IsNullOrEmpty($oemManufacturerName)) {
Write-Warning "OEMManufacturerName is empty"
$oemManufacturerName = "Unknown"
}
Write-Host "OEM Manufacturer Name: $oemManufacturerName"
} catch {
Write-Warning "OEMManufacturerName registry key not found or inaccessible"
$oemManufacturerName = $null
Write-Host "OEM Manufacturer Name: Not Available"
}
# 10. OEMModelSystemFamily
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelSystemFamily -ErrorAction Stop
$oemModelSystemFamily = $regValue.OEMModelSystemFamily
if ([string]::IsNullOrEmpty($oemModelSystemFamily)) {
Write-Warning "OEMModelSystemFamily is empty"
$oemModelSystemFamily = "Unknown"
}
Write-Host "OEM Model System Family: $oemModelSystemFamily"
} catch {
Write-Warning "OEMModelSystemFamily registry key not found or inaccessible"
$oemModelSystemFamily = $null
Write-Host "OEM Model System Family: Not Available"
}
# 11. OEMModelNumber
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop
$oemModelNumber = $regValue.OEMModelNumber
if ([string]::IsNullOrEmpty($oemModelNumber)) {
Write-Warning "OEMModelNumber is empty"
$oemModelNumber = "Unknown"
}
Write-Host "OEM Model Number: $oemModelNumber"
} catch {
Write-Warning "OEMModelNumber registry key not found or inaccessible"
$oemModelNumber = $null
Write-Host "OEM Model Number: Not Available"
}
# 12. FirmwareVersion
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop
$firmwareVersion = $regValue.FirmwareVersion
if ([string]::IsNullOrEmpty($firmwareVersion)) {
Write-Warning "FirmwareVersion is empty"
$firmwareVersion = "Unknown"
}
Write-Host "Firmware Version: $firmwareVersion"
} catch {
Write-Warning "FirmwareVersion registry key not found or inaccessible"
$firmwareVersion = $null
Write-Host "Firmware Version: Not Available"
}
# 13. FirmwareReleaseDate
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareReleaseDate -ErrorAction Stop
$firmwareReleaseDate = $regValue.FirmwareReleaseDate
if ([string]::IsNullOrEmpty($firmwareReleaseDate)) {
Write-Warning "FirmwareReleaseDate is empty"
$firmwareReleaseDate = "Unknown"
}
Write-Host "Firmware Release Date: $firmwareReleaseDate"
} catch {
Write-Warning "FirmwareReleaseDate registry key not found or inaccessible"
$firmwareReleaseDate = $null
Write-Host "Firmware Release Date: Not Available"
}
# 14. OSArchitecture
# PS Version: All | Admin: No | System Requirements: None
try {
$osArchitecture = $env:PROCESSOR_ARCHITECTURE
if ([string]::IsNullOrEmpty($osArchitecture)) {
# Try registry fallback
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop
$osArchitecture = $regValue.OSArchitecture
}
if ([string]::IsNullOrEmpty($osArchitecture)) {
Write-Warning "OSArchitecture could not be determined"
$osArchitecture = "Unknown"
}
Write-Host "OS Architecture: $osArchitecture"
} catch {
Write-Warning "Error retrieving OSArchitecture: $_"
$osArchitecture = "Unknown"
Write-Host "OS Architecture: $osArchitecture"
}
# 15. CanAttemptUpdateAfter (FILETIME)
# PS Version: All | Admin: May be required | System Requirements: None
try {
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop
$canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter
# Convert FILETIME to UTC DateTime — registry stores as REG_BINARY (byte[]) or REG_QWORD (long)
if ($null -ne $canAttemptUpdateAfter) {
try {
if ($canAttemptUpdateAfter -is [byte[]]) {
$fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter, 0)
$canAttemptUpdateAfter = [DateTime]::FromFileTime($fileTime).ToUniversalTime()
} elseif ($canAttemptUpdateAfter -is [long]) {
$canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter).ToUniversalTime()
}
} catch {
Write-Warning "Could not convert CanAttemptUpdateAfter FILETIME to DateTime"
}
}
Write-Host "Can Attempt Update After: $canAttemptUpdateAfter"
} catch {
Write-Warning "CanAttemptUpdateAfter registry key not found or inaccessible"
$canAttemptUpdateAfter = $null
Write-Host "Can Attempt Update After: Not Available"
}
# Event Logs: System Log (10 values: 16-25)
# 16-25. Event Log queries
# Event IDs:
# 1801 - Update initiated, reboot required
# 1808 - Update completed successfully
# 1795 - Firmware returned error (capture error code)
# 1796 - Error logged with error code (capture code)
# 1800 - Reboot needed (NOT an error - update will proceed after reboot)
# 1802 - Known firmware issue blocked update (capture KI_<number> from SkipReason)
# 1803 - Matching KEK update not found (OEM needs to supply PK signed KEK)
# PS Version: 3.0+ | Admin: May be required for System log | System Requirements: None
try {
# Query all relevant Secure Boot event IDs
$allEventIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808)
$events = @(Get-WinEvent -FilterHashtable @{LogName='System'; ID=$allEventIds} -MaxEvents 50 -ErrorAction Stop)
if ($events.Count -eq 0) {
Write-Warning "No Secure Boot events found in System log"
$latestEventId = $null
$bucketId = $null
$confidence = $null
$skipReasonKnownIssue = $null
$event1801Count = 0
$event1808Count = 0
$event1795Count = 0
$event1795ErrorCode = $null
$event1796Count = 0
$event1796ErrorCode = $null
$event1800Count = 0
$rebootPending = $false
$event1802Count = 0
$knownIssueId = $null
$event1803Count = 0
$missingKEK = $false
Write-Host "Latest Event ID: Not Available"
Write-Host "Bucket ID: Not Available"
Write-Host "Confidence: Not Available"
Write-Host "Event 1801 Count: 0"
Write-Host "Event 1808 Count: 0"
} else {
# 16. LatestEventId
$latestEvent = $events | Sort-Object TimeCreated -Descending | Select-Object -First 1
if ($null -eq $latestEvent) {
Write-Warning "Could not determine latest event"
$latestEventId = $null
Write-Host "Latest Event ID: Not Available"
} else {
$latestEventId = $latestEvent.Id
Write-Host "Latest Event ID: $latestEventId"
}
# 17. BucketID - Extracted from Event 1801/1808
if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {
if ($latestEvent.Message -match 'BucketId:\s*(.+)') {
$bucketId = $matches[1].Trim()
Write-Host "Bucket ID: $bucketId"
} else {
Write-Warning "BucketId not found in event message"
$bucketId = $null
Write-Host "Bucket ID: Not Found in Event"
}
} else {
Write-Warning "Latest event or message is null, cannot extract BucketId"
$bucketId = $null
Write-Host "Bucket ID: Not Available"
}
# 18. Confidence - Extracted from Event 1801/1808
if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {
if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') {
$confidence = $matches[1].Trim()
Write-Host "Confidence: $confidence"
} else {
Write-Warning "Confidence level not found in event message"
$confidence = $null
Write-Host "Confidence: Not Found in Event"
}
} else {
Write-Warning "Latest event or message is null, cannot extract Confidence"
$confidence = $null
Write-Host "Confidence: Not Available"
}
# 18b. SkipReason - Extract KI_<number> from SkipReason in the same event as BucketId
# This captures Known Issue IDs that appear alongside BucketId/Confidence (not just Event 1802)
$skipReasonKnownIssue = $null
if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {
if ($latestEvent.Message -match 'SkipReason:\s*(KI_\d+)') {
$skipReasonKnownIssue = $matches[1]
Write-Host "SkipReason Known Issue: $skipReasonKnownIssue" -ForegroundColor Yellow
}
}
# 19. Event1801Count
$event1801Array = @($events | Where-Object {$_.Id -eq 1801})
$event1801Count = $event1801Array.Count
Write-Host "Event 1801 Count: $event1801Count"
# 20. Event1808Count
$event1808Array = @($events | Where-Object {$_.Id -eq 1808})
$event1808Count = $event1808Array.Count
Write-Host "Event 1808 Count: $event1808Count"
# Initialize error event variables
$event1795Count = 0
$event1795ErrorCode = $null
$event1796Count = 0
$event1796ErrorCode = $null
$event1800Count = 0
$rebootPending = $false
$event1802Count = 0
$knownIssueId = $null
$event1803Count = 0
$missingKEK = $false
# Only check for error events if update is NOT complete
# Skip error analysis if: 1808 is latest event OR UEFICA2023Status is "Updated"
$updateComplete = ($latestEventId -eq 1808) -or ($uefica2023Status -eq "Updated")
if (-not $updateComplete) {
Write-Host "Update not complete - checking for error events..." -ForegroundColor Yellow
# 21. Event1795 - Firmware Error (capture error code)
$event1795Array = @($events | Where-Object {$_.Id -eq 1795})
$event1795Count = $event1795Array.Count
if ($event1795Count -gt 0) {
$latestEvent1795 = $event1795Array | Sort-Object TimeCreated -Descending | Select-Object -First 1
if ($latestEvent1795.Message -match '(?:error|code|status)[:\s]*(?:0x)?([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {
$event1795ErrorCode = $matches[1]
}
Write-Host "Event 1795 (Firmware Error) Count: $event1795Count" $(if ($event1795ErrorCode) { "Code: $event1795ErrorCode" })
}
# 22. Event1796 - Error Code Logged (capture error code)
$event1796Array = @($events | Where-Object {$_.Id -eq 1796})
$event1796Count = $event1796Array.Count
if ($event1796Count -gt 0) {
$latestEvent1796 = $event1796Array | Sort-Object TimeCreated -Descending | Select-Object -First 1
if ($latestEvent1796.Message -match '(?:error|code|status)[:\s]*(?:0x)?([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {
$event1796ErrorCode = $matches[1]
}
Write-Host "Event 1796 (Error Logged) Count: $event1796Count" $(if ($event1796ErrorCode) { "Code: $event1796ErrorCode" })
}
# 23. Event1800 - Reboot Needed (NOT an error - update will proceed after reboot)
$event1800Array = @($events | Where-Object {$_.Id -eq 1800})
$event1800Count = $event1800Array.Count
$rebootPending = $event1800Count -gt 0
if ($rebootPending) {
Write-Host "Event 1800 (Reboot Pending): Update will proceed after reboot" -ForegroundColor Cyan
}
# 24. Event1802 - Known Firmware Issue (capture KI_<number> from SkipReason)
$event1802Array = @($events | Where-Object {$_.Id -eq 1802})
$event1802Count = $event1802Array.Count
if ($event1802Count -gt 0) {
$latestEvent1802 = $event1802Array | Sort-Object TimeCreated -Descending | Select-Object -First 1
if ($latestEvent1802.Message -match 'SkipReason:\s*(KI_\d+)') {
$knownIssueId = $matches[1]
}
Write-Host "Event 1802 (Known Firmware Issue) Count: $event1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" })
}
# 25. Event1803 - Missing KEK Update (OEM needs to supply PK signed KEK)
$event1803Array = @($events | Where-Object {$_.Id -eq 1803})
$event1803Count = $event1803Array.Count
$missingKEK = $event1803Count -gt 0
if ($missingKEK) {
Write-Host "Event 1803 (Missing KEK): OEM needs to supply PK signed KEK" -ForegroundColor Yellow
}
} else {
Write-Host "Update complete (Event 1808 or Status=Updated) - skipping error analysis" -ForegroundColor Green
}
}
} catch {
Write-Warning "Error retrieving event logs. May require administrator privileges: $_"
$latestEventId = $null
$bucketId = $null
$confidence = $null
$skipReasonKnownIssue = $null
$event1801Count = 0
$event1808Count = 0
$event1795Count = 0
$event1795ErrorCode = $null
$event1796Count = 0
$event1796ErrorCode = $null
$event1800Count = 0
$rebootPending = $false
$event1802Count = 0
$knownIssueId = $null
$event1803Count = 0
$missingKEK = $false
Write-Host "Latest Event ID: Error"
Write-Host "Bucket ID: Error"
Write-Host "Confidence: Error"
Write-Host "Event 1801 Count: 0"
Write-Host "Event 1808 Count: 0"
}
# WMI/CIM Queries (5 values)
# 26. OSVersion
# PS Version: 3.0+ (use Get-WmiObject for 2.0) | Admin: No | System Requirements: None
try {
$osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop
if ($null -eq $osInfo -or [string]::IsNullOrEmpty($osInfo.Version)) {
Write-Warning "Could not retrieve OS version"
$osVersion = "Unknown"
} else {
$osVersion = $osInfo.Version
}
Write-Host "OS Version: $osVersion"
} catch {
# CIM may fail in some environments - use fallback
$osVersion = [System.Environment]::OSVersion.Version.ToString()
if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" }
Write-Host "OS Version: $osVersion"
}
# 27. LastBootTime
# PS Version: 3.0+ (use Get-WmiObject for 2.0) | Admin: No | System Requirements: None
try {
$osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop
if ($null -eq $osInfo -or $null -eq $osInfo.LastBootUpTime) {
Write-Warning "Could not retrieve last boot time"
$lastBootTime = $null
Write-Host "Last Boot Time: Not Available"
} else {
$lastBootTime = $osInfo.LastBootUpTime
Write-Host "Last Boot Time: $lastBootTime"
}
} catch {
# CIM may fail in some environments - use fallback
try {
$lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue).StartTime
} catch {
$lastBootTime = $null
}
if ($lastBootTime) { Write-Host "Last Boot Time: $lastBootTime" } else { Write-Host "Last Boot Time: Not Available" }
}
# 28. BaseBoardManufacturer
# PS Version: 3.0+ (use Get-WmiObject for 2.0) | Admin: No | System Requirements: None
try {
$baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop
if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Manufacturer)) {
Write-Warning "Could not retrieve baseboard manufacturer"
$baseBoardManufacturer = "Unknown"
} else {
$baseBoardManufacturer = $baseBoard.Manufacturer
}
Write-Host "Baseboard Manufacturer: $baseBoardManufacturer"
} catch {
# CIM may fail - baseboard info is supplementary
$baseBoardManufacturer = "Unknown"
Write-Host "Baseboard Manufacturer: $baseBoardManufacturer"
}
# 29. BaseBoardProduct
# PS Version: 3.0+ (use Get-WmiObject for 2.0) | Admin: No | System Requirements: None
try {
$baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop
if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Product)) {
Write-Warning "Could not retrieve baseboard product"
$baseBoardProduct = "Unknown"
} else {
$baseBoardProduct = $baseBoard.Product
}
Write-Host "Baseboard Product: $baseBoardProduct"
} catch {
# CIM may fail - baseboard info is supplementary
$baseBoardProduct = "Unknown"
Write-Host "Baseboard Product: $baseBoardProduct"
}
# 30. SecureBootTaskEnabled
# PS Version: All | Admin: No | System Requirements: Scheduled Task exists
# Checks if the Secure-Boot-Update scheduled task is enabled
$secureBootTaskEnabled = $null
$secureBootTaskStatus = "Unknown"
try {
$taskOutput = schtasks.exe /Query /TN "\Microsoft\Windows\PI\Secure-Boot-Update" /FO CSV 2>&1
if ($LASTEXITCODE -eq 0) {
$taskData = $taskOutput | ConvertFrom-Csv
if ($taskData) {
$secureBootTaskStatus = $taskData.Status
$secureBootTaskEnabled = ($taskData.Status -eq 'Ready' -or $taskData.Status -eq 'Running')
}
} else {
$secureBootTaskStatus = "NotFound"
$secureBootTaskEnabled = $false
}
if ($secureBootTaskEnabled -eq $false) {
Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Yellow
} else {
Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Green
}
} catch {
$secureBootTaskStatus = "Error"
$secureBootTaskEnabled = $false
Write-Host "SecureBoot Update Task: Error checking - $_" -ForegroundColor Red
}
# 31. WinCS Key Status (F33E0C8E002 - Secure Boot Certificate Update)
# PS Version: All | Admin: Yes (for query) | System Requirements: WinCsFlags.exe
$wincsKeyApplied = $null
$wincsKeyStatus = "Unknown"
try {
# Check common locations for WinCsFlags.exe
$wincsFlagsPath = $null
$possiblePaths = @(
"$env:SystemRoot\System32\WinCsFlags.exe",
"$env:SystemRoot\SysWOW64\WinCsFlags.exe"
)
foreach ($p in $possiblePaths) {
if (Test-Path $p) { $wincsFlagsPath = $p; break }
}
if ($wincsFlagsPath) {
# Query specific key - requires admin rights
$queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1
$queryOutputStr = $queryOutput -join "`n"
if ($LASTEXITCODE -eq 0) {
# Check if key is applied (look for "Active Configuration" or similar indicator)
if ($queryOutputStr -match "Active Configuration.*:.*enabled" -or $queryOutputStr -match "Configuration.*applied") {
$wincsKeyApplied = $true
$wincsKeyStatus = "Applied"
Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green
} elseif ($queryOutputStr -match "not found|No configuration") {
$wincsKeyApplied = $false
$wincsKeyStatus = "NotApplied"
Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow
} else {
# Key exists - check output for state
$wincsKeyApplied = $true
$wincsKeyStatus = "Applied"
Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green
}
} else {
# Check for specific error messages
if ($queryOutputStr -match "Access denied|administrator") {
$wincsKeyStatus = "AccessDenied"
Write-Host "WinCS Key F33E0C8E002: Access denied (run as admin)" -ForegroundColor DarkGray
} elseif ($queryOutputStr -match "not found|No configuration") {
$wincsKeyApplied = $false
$wincsKeyStatus = "NotApplied"
Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow
} else {
$wincsKeyStatus = "QueryFailed"
Write-Host "WinCS Key F33E0C8E002: Query failed" -ForegroundColor Red
}
}
} else {
$wincsKeyStatus = "WinCsFlagsNotFound"
Write-Host "WinCS Key F33E0C8E002: WinCsFlags.exe not found" -ForegroundColor Gray
}
} catch {
$wincsKeyStatus = "Error"
Write-Host "WinCS Key F33E0C8E002: Error checking - $_" -ForegroundColor Red
}
# =============================================================================
# Certificate Presence Detection (UEFI db and KEK)
# =============================================================================
# Initialize cert detection variables
$FirstPartyDB2023Updated = 0
$FirstPartyKEK2023Updated = 0
$ThirdParty2011CAPresent = 0
$ThirdParty2023CertsRequired = 0
$ThirdParty2023CertUpdated = 0
$ThirdPartyOptionRom2023CertUpdated = 0
try {
# Read the UEFI db (Signature Database) once
$dbBytes = (Get-SecureBootUEFI db -ErrorAction Stop).bytes
$dbString = [System.Text.Encoding]::ASCII.GetString($dbBytes)
# 1P DB: Windows UEFI CA 2023 (required on ALL systems)
if ($dbString -match 'Windows UEFI CA 2023') {
$FirstPartyDB2023Updated = 1
}
# Check if 3P 2011 CA is trusted (determines whether 3P 2023 certs are required)
if ($dbString -match 'Microsoft Corporation UEFI CA 2011') {
$ThirdParty2011CAPresent = 1
$ThirdParty2023CertsRequired = 1
}
# 3P DB: Microsoft UEFI CA 2023 (required only if 3P 2011 CA present)
if ($dbString -match 'Microsoft UEFI CA 2023') {
if ($ThirdParty2023CertsRequired -eq 1) {
$ThirdParty2023CertUpdated = 1
}
}
# 3P DB: Microsoft Option ROM UEFI CA 2023 (required only if 3P 2011 CA present)
if ($dbString -match 'Microsoft Option ROM UEFI CA 2023') {
if ($ThirdParty2023CertsRequired -eq 1) {
$ThirdPartyOptionRom2023CertUpdated = 1
}
}
} catch {
Write-Warning "Unable to read UEFI Secure Boot db variable: $_"
Write-Host "UEFI db certificate detection: Not Available (requires admin and UEFI system)" -ForegroundColor DarkGray
}
try {
# Read the UEFI KEK once
$kekBytes = (Get-SecureBootUEFI kek -ErrorAction Stop).bytes
$kekString = [System.Text.Encoding]::ASCII.GetString($kekBytes)
# 1P KEK: Microsoft Corporation KEK 2K CA 2023 (required on ALL systems)
if ($kekString -match 'Microsoft Corporation KEK 2K CA 2023') {
$FirstPartyKEK2023Updated = 1
}
} catch {
Write-Warning "Unable to read UEFI Secure Boot KEK variable: $_"
Write-Host "UEFI KEK certificate detection: Not Available (requires admin and UEFI system)" -ForegroundColor DarkGray
}
# 3P cert updated flags are only meaningful when 1P certs are both updated
# If 1P certs are not updated, reset 3P updated flags to 0 since the base requirement is not met
if ($FirstPartyDB2023Updated -eq 0 -or $FirstPartyKEK2023Updated -eq 0) {
$ThirdParty2023CertUpdated = 0
$ThirdPartyOptionRom2023CertUpdated = 0
}
# Visual summary with full certificate names
Write-Host ""
Write-Host "=== Certificate Update Summary ===" -ForegroundColor Cyan
Write-Host " [1P] Windows UEFI CA 2023 (db): $(if ($FirstPartyDB2023Updated) { 'Updated' } else { 'Not Updated' })" -ForegroundColor $(if ($FirstPartyDB2023Updated) { 'Green' } else { 'Yellow' })
Write-Host " [1P] Microsoft Corporation KEK 2K CA 2023 (KEK): $(if ($FirstPartyKEK2023Updated) { 'Updated' } else { 'Not Updated' })" -ForegroundColor $(if ($FirstPartyKEK2023Updated) { 'Green' } else { 'Yellow' })
Write-Host " [3P] Microsoft Corporation UEFI CA 2011 (db): $(if ($ThirdParty2011CAPresent) { 'Present - 3P 2023 certs required' } else { 'Not Present - 3P 2023 certs not required' })" -ForegroundColor $(if ($ThirdParty2011CAPresent) { 'Cyan' } else { 'Green' })
if ($ThirdParty2023CertsRequired) {
Write-Host " [3P] Microsoft UEFI CA 2023 (db): $(if ($ThirdParty2023CertUpdated) { 'Updated' } else { 'Not Updated' })" -ForegroundColor $(if ($ThirdParty2023CertUpdated) { 'Green' } else { 'Yellow' })
Write-Host " [3P] Microsoft Option ROM UEFI CA 2023 (db): $(if ($ThirdPartyOptionRom2023CertUpdated) { 'Updated' } else { 'Not Updated' })" -ForegroundColor $(if ($ThirdPartyOptionRom2023CertUpdated) { 'Green' } else { 'Yellow' })
}
Write-Host "===================================" -ForegroundColor Cyan
Write-Host ""
# =============================================================================
# Remediation Detection - Status Output & Exit Code
# =============================================================================
# Build status object from all collected inventory data
$status = [ordered]@{
UEFICA2023Status = $uefica2023Status
UEFICA2023Error = $uefica2023Error
UEFICA2023ErrorEvent = $uefica2023ErrorEvent
AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } else { $null }
AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } else { $null }
Hostname = $hostname
CollectionTime = if ($collectionTime -is [datetime]) { $collectionTime.ToString("o") } else { "$collectionTime" }
SecureBootEnabled = $secureBootEnabled
HighConfidenceOptOut = $highConfidenceOptOut
MicrosoftUpdateManagedOptIn = $microsoftUpdateManagedOptIn
OEMManufacturerName = $oemManufacturerName
OEMModelSystemFamily = $oemModelSystemFamily
OEMModelNumber = $oemModelNumber
FirmwareVersion = $firmwareVersion
FirmwareReleaseDate = $firmwareReleaseDate
OSArchitecture = $osArchitecture
CanAttemptUpdateAfter = if ($canAttemptUpdateAfter -is [datetime]) { $canAttemptUpdateAfter.ToString("o") } else { "$canAttemptUpdateAfter" }
LatestEventId = $latestEventId
BucketId = $bucketId
Confidence = $confidence
SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<number> from SkipReason in BucketId event
Event1801Count = $event1801Count
Event1808Count = $event1808Count
# Error events with captured details
Event1795Count = $event1795Count # Firmware returned error
Event1795ErrorCode = $event1795ErrorCode # Error code from firmware
Event1796Count = $event1796Count # Error code logged
Event1796ErrorCode = $event1796ErrorCode # Captured error code
Event1800Count = $event1800Count # Reboot needed (NOT an error)
RebootPending = $rebootPending # True if Event 1800 present
Event1802Count = $event1802Count # Known firmware issue
KnownIssueId = $knownIssueId # KI_<number> from SkipReason
Event1803Count = $event1803Count # Missing KEK update
MissingKEK = $missingKEK # OEM needs to supply PK signed KEK
OSVersion = $osVersion
LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" }
BaseBoardManufacturer = $baseBoardManufacturer
BaseBoardProduct = $baseBoardProduct
SecureBootTaskEnabled = $secureBootTaskEnabled
SecureBootTaskStatus = $secureBootTaskStatus
WinCSKeyApplied = $wincsKeyApplied # True if F33E0C8E002 key is applied
WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound, etc.
# Certificate presence detection (UEFI db/KEK)
FirstPartyDB2023Updated = $FirstPartyDB2023Updated # 1 if Windows UEFI CA 2023 present in db
FirstPartyKEK2023Updated = $FirstPartyKEK2023Updated # 1 if Microsoft Corporation KEK 2K CA 2023 present
ThirdParty2011CAPresent = $ThirdParty2011CAPresent # 1 if Microsoft Corporation UEFI CA 2011 present in db
ThirdParty2023CertsRequired = $ThirdParty2023CertsRequired # 1 if 3P 2011 CA present (system trusts 3P)
ThirdParty2023CertUpdated = $ThirdParty2023CertUpdated # 1 if Microsoft UEFI CA 2023 present (when 1P certs updated)
ThirdPartyOptionRom2023CertUpdated = $ThirdPartyOptionRom2023CertUpdated # 1 if Microsoft Option ROM UEFI CA 2023 present (when 1P certs updated)
}
# Output the status - For data aggregation
$jsonOutput = $status | ConvertTo-Json -Compress
# If OutputPath provided, save to file; otherwise output to stdout
if (-not [string]::IsNullOrEmpty($OutputPath)) {
# Validate OutputPath - skip if it looks like a help request or has invalid chars
if ($OutputPath -match '^[/\-]' -or $OutputPath -match '[<>:"|?*]') {
Write-Host "Invalid OutputPath specified, outputting to stdout" -ForegroundColor Yellow
Write-Output $jsonOutput
if ($secureBootEnabled -and $uefica2023Status -eq "Updated") { exit 0 } else { exit 1 }
}
# Ensure the output folder exists
if (-not (Test-Path $OutputPath)) {
try {
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
} catch {
Write-Warning "Could not create output folder: $OutputPath - $_"
}
}
# Save to HOSTNAME_latest.json
$outputFile = Join-Path $OutputPath "$($hostname)_latest.json"
try {
$jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force
Write-Host "JSON saved to: $outputFile" -ForegroundColor Green
} catch {
Write-Warning "Could not write to file: $outputFile - $_"
# Fall back to stdout
Write-Output $jsonOutput
}
} else {
# Original behavior - output to stdout
Write-Output $jsonOutput
}
# Exit code: "Updated" is the success value per the playbook
if ($secureBootEnabled -and $uefica2023Status -eq "Updated") {
exit 0 # Without issue
} else {
exit 1 # With issue
}
# SIG # Begin signature block
# MIIpxQYJKoZIhvcNAQcCoIIptjCCKbICAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCeNkBwSJyyu73C
# //+931qN//lrktOQKYxtmEZ3qkNTO6CCDeUwgga9MIIEpaADAgECAhMzAAAAHEif
# gd+hsLd3AAAAAAAcMA0GCSqGSIb3DQEBDAUAMIGIMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0
# aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yNDA4MDgyMTM2MjNaFw0zNTA2MjMy
# MjA0MDFaMF8xCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xMDAuBgNVBAMTJ01pY3Jvc29mdCBXaW5kb3dzIENvZGUgU2lnbmluZyBQ
# Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJp9a30nwXYq
# Lq7j1TT/zCtt7vxU+CCj+7BkifS/B2gXKGU7OV9SXRJGP1yFs5p6jpsYi4cYzF56
# AV0AEmmEjV8wT2lvPU5BhN3wV30HqYPIYEj5P3WXf0kXD9fvjUf1GAtXEriJ8w7A
# LNaVEm9Rs4ePA0ZsYHaCbU5kBUJQDXv76hafOcQgdFCA3I3zYtfzX2vOwx87uDOa
# CuyKORZih9c3zTf+TLC5QYLyhVMBnDXEHDOrvaw92DSyIqpdgRWpufzqDFy1egVj
# koXZhb+9pZ9heUzNXTXhOoXzexh6YzAL4flBWm+Bc1hQyESenEvBJznV+25u3h77
# jjgMUY44+WXQ4u9qddDe/U5SeAaKRvvibmi4z7QRpLvZsla0CPiOUGz00Do5sfkC
# 0EwlsSzfM3+8A9rsyFVOgWDVPzt98OJP2EoaEOq8GE9GCoN2i7/4C2FCwff1BSCT
# JWZO1Wcr2MteJE6UxGV+ihA8nN51YPKD2dYGoewrXvRzC/1HoUeSvlZf0mf9GHEt
# vvkbJVRRo6PBf0md5t87Vb1mM/fIp1eypyaxmXkgpcBwuylsOq2kSVOJ5wBPoaEs
# sJkeMcKnEuuu++UKdDHlS0DtsYjN0QnOucvTdSsdvhzKOSjJF3XVqr9f2C945LXT
# 5rxKIHUIEDBcNYU6BKDDH6rfpKOOCSilAgMBAAGjggFGMIIBQjAOBgNVHQ8BAf8E
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFB6C3w7XjLPXAjSDDtqr
# rWW5r7jsMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB
# Af8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBL
# oEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
# TWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggr
# BgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNS
# b29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQEMBQADggIBAENf+N8/
# u+mUjDtc9btoA52RBc0XVDSBMQBMqxu56hXHBwuctUWs1XBqDDMIFCHu9c6Y/UF+
# TN8EIgjnujApKYmHP4f4EM3ARSmlzrpF5ozOJx0BA5FUv1jmpdf/2ZbqpvCxlxv/
# G1R4KjrSmmqPHzs6igw3b7RTbj7BxIS8fOIkwYWQhB2fLjlg+3HSrDGPFIhpIJWV
# amMIR7a72OGonjdf45rspwqIHuynZU4avy9ruB/Rhhbwm+fMb8BMecIaTmkohx/E
# ZZ5GNWcN6oTYW3G2BM3B3YznWkl9t4shP60fMue+2ksdHGWSE8EVTdSmGUdj0jrU
# c46lGVFJISF3/MxcxnlNeP1Khyr+ZzT4Ets/I7mufpaLnLalzMR2zIuhGOAWWswe
# sbjtFzkVUFgDR2SW903I0XKlbPEA6q8epHGJ9roxh85nsEKcBNUw4Scp68KCqSpF
# BaKiyV1skd+l8U50WNePMb9Bzz0OfASal8v5sQG+DW01kN+I+RKUIbM5I50wJjiH
# ymQFNDsbobFx9I95mCEEPU7fUZ3VT/HOUVbkmX7ltIC/eQAu5GO8fu+ceETMybvb
# oxUM4dYNC+PzooUxfmC0DuKRwB21bX9+acuIBkxIm4Ed3O19w1VLoA7UNOUuJ7z6
# NQ2W/+q7cnfOPl2QVL4qlgCblUT2vmQpllV3MIIHIDCCBQigAwIBAgITMwAAASJs
# BjOj0VK23QAAAAABIjANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQGEwJVUzEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTAwLgYDVQQDEydNaWNyb3NvZnQg
# V2luZG93cyBDb2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwMzA1MTk1ODI0WhcN
# MjcwMzAzMTk1ODI0WjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMR4wHAYDVQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQCeFlu3IJtMm0DcCUF5EKHUKh/L06a1JyvxX2aV
# aapyABxwDINwxmSS0MR5ObqvX4TKhYX2Ic7+HNhNjxZg7UJUTMamRDcmnS3QHYOe
# oqsgveL1mGQsvBqWROEi2tBe8PrwJrYd4tefld81kaQ1cnbzuUuou3fuAHNudJnA
# CW5SqPmZHF565Ij7jwMeJPxU5JHsPAs/Y11aWPxI85kVEUecjfOMpIx5oTXnNi9U
# nw7BSv/SSrXfkyAyFyqu+PN9ymIWLmOAPaAnJ+QxGRZ9D7jJy4fZK0RxO1GlPTaj
# h9xgbz7SDSeC70z8Ro8mgO3ImrCDv4KdJztT5dnCieVXLMSxCqWikfKznmoCaAqG
# 5skdylL5CFi8TQVKASb2QR0MjS1fqX0FpOkgibu7+m2EPzjp36SkgZ1TXVfAO3j5
# BjRZT/VXaWS0Zk+eNn8/SQf8U/LRRpnuJXhkOWVBNIGq5ew6EsKIQm5Dter5NTSK
# J8gUlqiwDKZ1HuaTEWn1PmgN0YYF9av8fDTeVbEPQe04yv47o8lYpldFM0B9kWOc
# kIc0U+hXNC/+pnDVUh2fjN+JtMaLKTTOciXM2F0tt3CbdKO+cCmlCzSuhN9aeQ2m
# GEnQY3v3V3W15uaUpYELTYOTeTwDVkYJXCZK/zNRXxU38rQ+LwxLOeRVNvEYh2Js
# 0nuX0QIDAQABo4IBvjCCAbowDgYDVR0PAQH/BAQDAgeAMB8GA1UdJQQYMBYGCisG
# AQQBgjc9BgEGCCsGAQUFBwMDMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFJ8ytbdA
# tti7ifaKbKxtPwbvlJiSMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQLEyRNaWNyb3Nv
# ZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUTDTIzMDg2NSs1
# MDY5NjUwHwYDVR0jBBgwFoAUHoLfDteMs9cCNIMO2qutZbmvuOwwagYDVR0fBGMw
# YTBfoF2gW4ZZaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWlj
# cm9zb2Z0JTIwV2luZG93cyUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAyNC5j
# cmwwdwYIKwYBBQUHAQEEazBpMGcGCCsGAQUFBzAChltodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFdpbmRvd3MlMjBDb2Rl
# JTIwU2lnbmluZyUyMFBDQSUyMDIwMjQuY3J0MA0GCSqGSIb3DQEBDAUAA4ICAQCY
# WFIyjTfk5OvOrxA8oAS2jbS6/P0DDLLiqZsyy6dY9vfid+P2uawuygeoVwkvGqMO
# 0UDWuupsy8VQ/5Fw+GXfx7n9AfvoVg30rHm883siWQ9/GaayCh219lbearlRziyq
# TZoz7ShvA23fRoKs3I9LlXWWOH1d5CeFtuyX0D4oRBU1pQS+ijDSv848ZiLwqjig
# Q7XBaYiPNVQI8xMkkVeIc6B575rVsxqLF5rQFMuXZhwU+BXEbVa4tmVAzY9geP3X
# dOP+L/OwWQV83Z6poT/RW6QMqkNpgf7Pc3oSGKGTpr32AwHIutwmWaEaj8asyDUj
# FABzJBG6AH8pugTf440r61uNlw6mDXppfOZVyuHuH93uNzaINvuW/Y/yEYSDdTvy
# 6Sn5GwWrHKNA23UR18Abu7B2uOeDhiTq69oePmKEAPjjHMTQBrZUX+VBwv+v7MJB
# r8A0s4zg/AY+A/LmN5veQpcAjTj9H+2mKEQobRTUHKBDW1T1fXYQb1JdWQXDK9In
# 6Lx8EaWOExYktAceGfzxC9NoCjxBUb8ba6QOQXNaqrzQlDzGwqxLsiClN+H6h58p
# BfFF2OoSaLlgpih0WRfp7sTGddsp6ajbAAX7VSI/W32o2G7KaDIc1jiok64BnBRo
# ewtKnNm3Ny0ulmJ6IgIZA5DOAxT9tPtEtNhwHmhshzGCGzYwghsyAgEBMHYwXzEL
# MAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEwMC4G
# A1UEAxMnTWljcm9zb2Z0IFdpbmRvd3MgQ29kZSBTaWduaW5nIFBDQSAyMDI0AhMz
# AAABImwGM6PRUrbdAAAAAAEiMA0GCWCGSAFlAwQCAQUAoIH6MBkGCSqGSIb3DQEJ
# AzEMBgorBgEEAYI3AgEEMC8GCSqGSIb3DQEJBDEiBCCmId3C9kmlMdEzQB18EVrc
# qFY8Rxaju134uxb3e+pR1DBQBgorBgEEAYI3CgMcMUIMQDBDOTc2OEI0M0I3OTA0
# MTNFN0I5QUYyNjMxMEM2NjVFMUE5MkJENkFCMDg3MTQ0QUNCMjRCMTQzMjI3NTZC
# MUYwWgYKKwYBBAGCNwIBDDFMMEqgJIAiAE0AaQBjAHIAbwBzAG8AZgB0ACAAVwBp
# AG4AZABvAHcAc6EigCBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vd2luZG93czAN
# BgkqhkiG9w0BAQEFAASCAgCMd0WERvfSz9PkHNQN9mDE8L8SdCmHG6LHW6plWIk3
# tsYofpeCFGMBrkfJDHsWh06YhZ9CgG0ph7bJi0mS+qCDuCR8fF91lTyvhQUyprcA
# 3fomWkR0hoGwvQZ5O1vmSS04QZPrKrVmaAvLKfk3D/E9kiCHzx9CtDyJzFQSTTLg
# O9DVqr+ogPlN4Vjznp3Nn6VrMf1JnO6Imd9UOKrs1wZVKbtjG77O6+cJGjxxbizj
# Fd3Rx/T/dO3CAmoduNxGal7gTrp9UZ6GOd8n6Wrjn/0YOMgZDcAa+/Hai8cxN0lV
# giXNo05gFjkZhbSC80L2gu0GmNMWkMr6R6IjFcCb3N1lv4OzKj+YEZMllW0CNujo
# 3XcQPGw8b4cAhNi7U+uWgORoLQEdiwY5bgBCDv6jVmIqFxi0DAOuVfvswlaJ0P6+
# z/Z2+KU+paCjsElJlOmqxN1ATSvG/SufmX/oJ7wGLOFYSCXTPlrQNyYPIeMcfQE2
# k9qR4BzA8nx+HNyzrg77DerdfSC1MD7Ze1jW4PKAhP9Axoq9fIUPkfepoA6cH/lN
# zbqZ8OE2378pHD9sSVB6yausxEmpMr1RvEWyHKmXMvybADZU44L4k+0fvjPkcLVb
# 3gYamc8kRYxUNdAK7KY4TWbPZg/lyrR8mV3p9TE9eqVPhRNfsoq2DBD9j7OcD56a
# m6GCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCCF3wGCSqGSIb3DQEHAqCCF20wghdp
# AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIB
# OQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCAIrPtLljpGeSr+Gjoj
# 6YCvl/iUgZ/x50+bRCGGy94MIwIGahdQGsStGBMyMDI2MDYwNjA4MzU1Ni40NzRa
# MASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WgghHqMIIHIDCCBQigAwIBAgITMwAA
# Ah6jrKRuOW98SQABAAACHjANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
# dGFtcCBQQ0EgMjAxMDAeFw0yNjAyMTkxOTM5NDlaFw0yNzA1MTcxOTM5NDlaMIHL
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxN
# aWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRT
# UyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0
# YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCl0Tjt
# bDwsR7Fe8ac6ol5s1zhtTqd2AWpchQhLp9G5mmSM23N5fyQGCQ1D06rOA3PgXKF+
# 76vXvOCs2VsLv1owj4mHEyEqiq8GJ5yC+/QNYRpZPA8e7OgekzDO6S/4vy/jTMYb
# p3rhuFiKKCzTWOQtdFcF+D0k369I7pm/E07SyNMGkuNd5lj5SJ91UqFuZfjMB6cQ
# 2wh77mtiRUVdj53yjdNqj+GQl+Yaz29Bjrzn7U1ln+JpLlnb0xdGmZoIPKZbwBVc
# WtyL4uyhML7SSTmiOfWXU+g+yNl0CdoLGL8LtWHEi8FsuTPeSdSqmeMrvLaEmibT
# VTS4vQQY8NPnb6uI5y6iNV9vBFcm8LU/lDTjGTqPa7UBT4gdf5Jm3wYrfCFZ4P/j
# 5MoqT0JONca50jt4TGI90SihXaDEYqk23S0IJZ3UkUpukDRTjK713BIykffxyBqM
# eQqfO0zvWfUx7BrmUpugQcw99+DxLl2gf+uQEpRmnlbrVJ9dvW9ds4fqEPN2jG0Q
# wF1PBSglNcV1SpqZKitQgBGSwu/82AKztoCHwYRHRNwzwTVe/1KNTvmqAd4Uges4
# ywOH02haagT8wYY8OdWdjKn3k052w+kmc0UC0F+iVXTGZIMxvo9iBZQoXehzRtWJ
# /VOtKvCyS3csKzN7rStWJwjSWz6dtOf0l+ytLQIDAQABo4IBSTCCAUUwHQYDVR0O
# BBYEFOYKFprqBB0JZmJcFC4cPPmeF4JkMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl
# 0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAy
# MDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93
# d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1T
# dGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/
# BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IC
# AQCkoZB5NnJVFb5wKejRonk518a2TBNYpKcBMtfL6BS0ARaABOMGYLlPNuhI1Hwm
# elP9hX3oq3TaEm/cDkkzNQAzDedPgoRI2R7+8poNSWvHXEAs7SZODm9x7KqlBkNZ
# M9ex4XY1yNmVOAmWDjRr7jKjaiQbntf7EC4GNikxGGaVWOjfYt3Q9X0r/Ks8KBlb
# zDR9zjA/TCctR4co1WpU1ZRLFrB9bl8dRxsbnyT2qQ41E7dT12R30eIGUziEs5GN
# +26V/ovXOi20dJiM13hYWvy1NNJAhkKOlLB1ONund6ffhPdUcHWsu8V+lR0aakMV
# 64HqDbLumZrCNwUofVx3xMk8F4tCYJtQxLTywc30sZAD1S2sC1959x6KixA+p41F
# LUl8g64oHy3bfYnH5xd4JOBgQoaqndGjcctxr+8EknjhKyrgAzrTcKLJbUezgoye
# 8brCLJ+y6PAoEjpXRkSYAU8wfQ3YWRck6ALwoV7Uin8+rpGQSbXhF6c1dTFakXmC
# hClud4IADY/t6JRkJ+06FzL+jDd8KLV8Qj77JfiuTiPIG5G/xlnGoZFcX+yyBtDv
# zZE48d+Y+HYUd/cvhH1FKl7AH+5AyotqJSFmvM/BuYRx2B20asVXilV2k2JbNO3L
# GCz3Q+dpElzwsfJrka1N/getma7fWpowsNvoIaEQvjad8TCCB3EwggVZoAMCAQIC
# EzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoX
# DTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC
# 0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VG
# Iwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP
# 2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/P
# XfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361
# VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwB
# Sru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9
# X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269e
# wvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDw
# wvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr
# 9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+e
# FnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAj
# BgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+n
# FV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEw
# PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j
# cy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3
# FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAf
# BgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBH
# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNS
# b29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl
# ckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4Swf
# ZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTC
# j/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu
# 2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/
# GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3D
# YXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbO
# xnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqO
# Cb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I
# 6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0
# zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaM
# mdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNT
# TY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNNMIICNQIBATCB+aGB0aSBzjCByzEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWlj
# cm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1Mg
# RVNOOjdGMDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQCD/QNkKDIW4VIF7j3oi2qbrR0a/6CB
# gzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk
# BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEB
# CwUAAgUA7c5TazAiGA8yMDI2MDYwNjA4MDYwM1oYDzIwMjYwNjA3MDgwNjAzWjB0
# MDoGCisGAQQBhFkKBAExLDAqMAoCBQDtzlNrAgEAMAcCAQACAgkQMAcCAQACAhJF
# MAoCBQDtz6TrAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAI
# AgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBACaPc2RoA+yC
# z9wgkBKbVBjWE8gp5qk8WSPRyjkKmSiY+iFPc23T/fvQejgdYGKv5SHM2b+Cxy6S
# lvnFuiMqSE33Xr1IGOnGQXR/8E+FSYeNaCWKy5TJiKpArGVqWqY9ooiW+tselnsJ
# P9T4OeRPseBlEd6tRzynQ1F75sxkAEP4wO6DowyxNkTr+MhXoPAwyJPCqN0ppdFF
# zWR8B1l4bsq9ky2qBTYYRIxN6I6xtKQ0cCV+hTf2Pqs3OQYvII4X41Q/2t21U5p3
# SH2QIAbTE7Pz1k2NCdgp294//Mtv1u64PDFpuT8uOu4U7EIReXmA/OvuW6XzTV1w
# jzGhtWhpaZcxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMAITMwAAAh6jrKRuOW98SQABAAACHjANBglghkgBZQMEAgEFAKCCAUowGgYJ
# KoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCC1La3P1Lpd
# 5YH160cD8QBwx5hn1dHGfkE2KX/rVY/g7DCB+gYLKoZIhvcNAQkQAi8xgeowgecw
# geQwgb0EIC+BXWrz9geMgM8Bvn8bqxHjhHXJ29EBizITIw0B9vOCMIGYMIGApH4w
# fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIeo6ykbjlvfEkAAQAA
# Ah4wIgQgvS0k3nz2XDL602akpRZTRaLGTq5J5dncwG+bYLk+Oc8wDQYJKoZIhvcN
# AQELBQAEggIATJCHa0PvQJvaTrCNIc0Z5S1kl78jWGvHeuHwfcdkWZ2vd3Aa46Ud
# lugVHo6Az+IKNvPs8nZ1NX1wTWpSrBzumLdnt5k4G7yS4yxNsCyXWOz2Ji+2e3Sw
# znd9pjBRZg4azzhIuTW0BqSgUbE8pVZ1+4H7fizsnGlpmiO6CBkEBlyTNYwA90f0
# ouGmSG85vgLd7ZbKlFdlaXscbJImRnKSaB5JNw7DUK5sLO45WAr7a2plFG/QTDGQ
# Vw4BKmgyWxQch71lg1CzyZMA5pmnfXmwKTtwQlGl0PAt7R6vUdWMXoW+i9c/3X/b
# ZDYziaYwyVLCKjiJBJ1pE9bhjoITx2XoY8FBMstEaCV5b5MVXL7Jsn5kZCjH/eEE
# 4jLp1H/IHolEP3dE8CSBMqhGe+qB37yYDKJOWdKR8IbOWxGgkt3kR3IEiCkjGiH0
# DrpxbOAKS1eo0mTTtxHvlNRw1b2hY83K+u/gFh3ei+HKeuitZOaqPYyzFwOgYqkE
# NGvoWA+uWnjfWbcI+VtfYbAhyzd8WuEJrihH8SW7q2gav0qbUv4fkQc01RB0cOiI
# aG2RQq12SEho6urShjobhuJAWMMHX+HUMEyNZVfNh+QlBewvshEwTCqEc9FrjZdu
# GzTror7eJn4emOGPVJRz+Aba7+sercRlcDeXgK6E1vFPihaUSq107AI=
# SIG # End signature block