적용 대상
Windows 10 Windows 10, version 1607, all editions Win 10 Ent LTSC 2019 Win 10 IoT Ent LTSC 2019 Windows 10 IoT Core LTSC Windows 10 Enterprise LTSC 2021 Windows 10 IoT Enterprise LTSC 2021 Windows 10, version 22H2, all editions Windows 11 Home and Pro, version 21H2 Windows 11 Enterprise Multi-Session, version 21H2 Windows 11 Enterprise and Education, version 21H2 Windows 11 IoT Enterprise, version 21H2 Windows 11 Home and Pro, version 22H2 Windows 11 Enterprise Multi-Session, version 22H2 Windows 11 Enterprise and Education, version 22H2 Windows 11 IoT Enterprise, version 22H2 Windows 11 SE, version 23H2 Windows 11 Home and Pro, version 23H2 Windows 11 Enterprise and Education, version 23H2 Windows 11 Enterprise Multi-Session, version 23H2 Windows 11 SE, version 24H2 Windows 11 Enterprise and Education, version 24H2 Windows 11 Enterprise Multi-Session, version 24H2 Windows 11 Home and Pro, version 24H2 Windows 11 IoT Enterprise, version 24H2 Windows Server 2012 ESU Windows Server 2012 R2 ESU Windows Server 2016 Windows Server 2019 Windows Server 2022 Windows Server 2025

원래 게시 날짜: 2025년 11월 17일

KB ID: 5072718

중요 샘플 스크립트가 포함된 이 문서는 사용 중지되었습니다. 2026년 5월 12일 이후에 릴리스된 Windows 업데이트부터 샘플 스크립트는 디바이스의 %systemroot%\SecureBoot\ExampleRolloutScripts 폴더에 있습니다.

샘플 보안 부팅 인벤토리 데이터 수집 스크립트

이 샘플 스크립트를 복사하여 붙여넣고 사용자 환경에 필요한 대로 수정합니다. 샘플 보안 부팅 인벤토리 데이터 수집 스크립트입니다.

<# . 시놉시스     플릿 전체 모니터링을 위해 보안 부팅 인증서 업데이트 상태 검색합니다.

. 설명     이 검색 스크립트는 보안 부팅 상태, 인증서 업데이트 레지스트리 값을 수집합니다.     및 디바이스 정보입니다. 모니터링 및 보고를 위해 JSON 문자열을 출력합니다.

    Intune 수정, GPO 기반 컬렉션 및 기타 관리 도구와 호환됩니다.수정 스크립트가 필요하지 않습니다. 이는 모니터링 전용입니다.

    종료 0 = "문제 없음"(인증서 업데이트됨)     Exit 1 = "With issue"(인증서가 업데이트되지 않음 - 정보만 해당)

. PARAMETER OutputPath     선택적. JSON 파일이 저장될 폴더의 경로입니다.제공된 경우 이 폴더에 HOSTNAME_latest.json 저장합니다.제공되지 않으면 JSON을 stdout(원래 동작)으로 출력합니다.

. 예제     # stdout에 출력(Intune/SCCM 검색)     .\Detect-SecureBootCertUpdateStatus.ps1

. 예제     # 네트워크 공유에 저장(GPO 배포)     .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"

. 노트     https://aka.ms/securebootplaybook 당 레지스트리 경로:       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing

    소프트웨어는 어떠한 종류의 보증도 없이 "있는 그대로" 제공됩니다.     가맹점 보증을 포함하지만 이에 국한되지 않는 암시적     특정 목적 및 비침해에 대한 적합성. 어떠한 경우에도     작성자 또는 저작권 소유자는 모든 청구, 손해 또는 기타에 대해 책임을 져야 합니다.     계약, 불법 행위 또는 기타 행위에서 발생하는 책임,     소프트웨어 또는 사용 또는 기타 거래와 관련하여     소프트웨어.#> param(     [Parameter(Mandatory = $false)]     [string]$OutputPath )

# 다운로드 URL: https://aka.ms/getsecureboot -> "배포 및 모니터링 샘플" # 참고: 이 스크립트는 엔드포인트에서 실행하여 보안 부팅 상태 데이터를 수집합니다.

# 1. 호스트 # PS 버전: 모두 | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $hostname = $env:COMPUTERNAME     if ([string]::IsNullOrEmpty($hostname)) {         Write-Warning "호스트 이름을 확인할 수 없습니다."         $hostname = "알 수 없음"     }     Write-Host "호스트 이름: $hostname" } catch {     Write-Warning "호스트 이름을 검색하는 동안 오류가 발생했습니다. $_"     $hostname = "오류"     Write-Host "호스트 이름: $hostname" }

# 2. CollectionTime # PS 버전: 모두 | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $collectionTime = Get-Date     if ($null -eq $collectionTime) {         Write-Warning "현재 날짜/시간을 검색할 수 없음"         $collectionTime = "알 수 없음"     }     Write-Host "컬렉션 시간: $collectionTime" } catch {     Write-Warning "날짜/시간 검색 오류: $_"     $collectionTime = "오류"     Write-Host "컬렉션 시간: $collectionTime" }

# 레지스트리: 보안 부팅 기본 키(3개 값)

# 3. SecureBootEnabled # PS 버전: 3.0 이상 | 관리: 필요할 수 있음 | 시스템 요구 사항: UEFI/보안 부팅 가능 시스템 try {     $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction 중지     Write-Host "보안 부팅 사용: $secureBootEnabled" } catch {     Write-Warning "cmdlet을 통해 보안 부팅 상태 확인할 수 없음: $_"     # 레지스트리 대체 시도     try {         $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop         $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled         Write-Host "보안 부팅 사용: $secureBootEnabled"     } catch {         Write-Warning "레지스트리를 통해 보안 부팅 상태 확인할 수 없습니다. 시스템에서 UEFI/보안 부팅을 지원하지 않을 수 있습니다."         $secureBootEnabled = $null         Write-Host "보안 부팅 사용: 사용할 수 없음"     } }

# 4. HighConfidenceOptOut # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop     $highConfidenceOptOut = $regValue.HighConfidenceOptOut     Write-Host "높은 신뢰도 옵트아웃: $highConfidenceOptOut" } catch {     # HighConfidenceOptOut은 선택 사항이며 대부분의 시스템에는 없습니다.     $highConfidenceOptOut = $null     Write-Host "높은 신뢰도 옵트아웃: 설정되지 않음" }

# 4b. MicrosoftUpdateManagedOptIn # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop     $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn     Write-Host "Microsoft 업데이트 관리되는 옵트인: $microsoftUpdateManagedOptIn" } catch {     # MicrosoftUpdateManagedOptIn은 선택 사항이며 대부분의 시스템에는 없습니다.     $microsoftUpdateManagedOptIn = $null     Write-Host "Microsoft 업데이트 관리 옵트인: 설정 안 함" }

# 5. AvailableUpdates # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop     $availableUpdates = $regValue.AvailableUpdates     if ($null -ne $availableUpdates) {         # 16진수 형식으로 변환         $availableUpdatesHex = "0x{0:X}" -f $availableUpdates         Write-Host "사용 가능한 업데이트: $availableUpdatesHex"     } else {         Write-Host "사용 가능한 업데이트: 사용할 수 없음"     } } catch {     Write-Warning "AvailableUpdates 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $availableUpdates = $null     Write-Host "사용 가능한 업데이트: 사용할 수 없음" }

# 5b. AvailableUpdatesPolicy(GPO 제어 영구 값) # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop     $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy     if ($null -ne $availableUpdatesPolicy) {         # 16진수 형식으로 변환         $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy         Write-Host "사용 가능한 업데이트 정책: $availableUpdatesPolicyHex"     } else {         Write-Host "사용 가능한 업데이트 정책: 설정 안 함"     } } catch {     # AvailableUpdatesPolicy는 선택 사항이며 GPO가 적용된 경우에만 설정됩니다.     $availableUpdatesPolicy = $null     Write-Host "사용 가능한 업데이트 정책: 설정 안 함" }

# 레지스트리: 서비스 키(3개 값)

# 6. UEFICA2023Status # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop     $uefica 2023Status = $regValue.UEFICA2023Status     Write-Host "Windows UEFI CA 2023 상태: $uefica 2023Status" } catch {     Write-Warning "Windows UEFI CA 2023 상태 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $uefica 2023Status = $null     Write-Host "Windows UEFI CA 2023 상태: 사용할 수 없음" }

# 7. UEFICA2023Error # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop     $uefica 2023Error = $regValue.UEFICA2023Error     Write-Host "UEFI CA 2023 오류: $uefica 2023Error" } catch {     # UEFICA2023Error는 오류가 발생한 경우에만 존재합니다. 부재가 좋습니다.     $uefica 2023Error = $null     Write-Host "UEFI CA 2023 오류: 없음" }

# 8. UEFICA2023ErrorEvent # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop     $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent     Write-Host "UEFI CA 2023 오류 이벤트: $uefica 2023ErrorEvent" } catch {     $uefica 2023ErrorEvent = $null     Write-Host "UEFI CA 2023 오류 이벤트: 사용할 수 없음" }

# 레지스트리: 디바이스 특성(7개 값: 9-15)

# 9. OEMManufacturerName # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 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이 비어 있습니다."         $oemManufacturerName = "알 수 없음"     }     Write-Host "OEM 제조업체 이름: $oemManufacturerName" } catch {     Write-Warning "OEMManufacturerName 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $oemManufacturerName = $null     Write-Host "OEM 제조업체 이름: 사용할 수 없음" }

# 10. OEMModelSystemFamily # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 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가 비어 있습니다."         $oemModelSystemFamily = "알 수 없음"     }     Write-Host "OEM 모델 시스템 패밀리: $oemModelSystemFamily" } catch {     Write-Warning "OEMModelSystemFamily 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $oemModelSystemFamily = $null     Write-Host "OEM 모델 시스템 패밀리: 사용할 수 없음" }

# 11. OEMModelNumber # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 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가 비어 있음"         $oemModelNumber = "알 수 없음"     }     Write-Host "OEM 모델 번호: $oemModelNumber" } catch {     Write-Warning "OEMModelNumber 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $oemModelNumber = $null     Write-Host "OEM 모델 번호: 사용할 수 없음" }

# 12. FirmwareVersion # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 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이 비어 있음"         $firmwareVersion = "알 수 없음"     }     Write-Host "펌웨어 버전: $firmwareVersion" } catch {     Write-Warning "FirmwareVersion 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $firmwareVersion = $null     Write-Host "펌웨어 버전: 사용할 수 없음" }

# 13. FirmwareReleaseDate # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 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가 비어 있음"         $firmwareReleaseDate = "알 수 없음"     }     Write-Host "펌웨어 릴리스 날짜: $firmwareReleaseDate" } catch {     Write-Warning "FirmwareReleaseDate 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $firmwareReleaseDate = $null     Write-Host "펌웨어 릴리스 날짜: 사용할 수 없음" }

# 14. OSArchitecture # PS 버전: 모두 | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $osArchitecture = $env:PROCESSOR_ARCHITECTURE     if ([string]::IsNullOrEmpty($osArchitecture)) {         # 레지스트리 대체 시도         $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를 확인할 수 없음"         $osArchitecture = "알 수 없음"     }     Write-Host "OS 아키텍처: $osArchitecture" } catch {     Write-Warning "OSArchitecture를 검색하는 동안 오류가 발생했습니다. $_"     $osArchitecture = "알 수 없음"     Write-Host "OS 아키텍처: $osArchitecture" }

# 15. CanAttemptUpdateAfter(FILETIME) # PS 버전: 모두 | 관리: 필요할 수 있음 | 시스템 요구 사항: 없음 try {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop     $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter     # FILETIME을 UTC DateTime으로 변환 - 레지스트리는 REG_BINARY(바이트[]) 또는 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 "CanAttemptUpdateAfter FILETIME을 DateTime으로 변환할 수 없음"         }     }     Write-Host "다음에 업데이트를 시도할 수 있습니다. $canAttemptUpdateAfter" } catch {     Write-Warning "CanAttemptUpdateAfter 레지스트리 키를 찾을 수 없거나 액세스할 수 없음"     $canAttemptUpdateAfter = $null     Write-Host "다음에 업데이트를 시도할 수 있음: 사용할 수 없음" }

# 이벤트 로그: 시스템 로그(10개 값: 16-25)

# 16-25. 이벤트 로그 쿼리 # 이벤트 ID: # 1801 - 업데이트 시작됨, 다시 부팅 필요 # 1808 - 업데이트가 성공적으로 완료됨 # 1795 - 펌웨어가 오류를 반환했습니다(캡처 오류 코드) # 1796 - 오류 코드로 기록된 오류(캡처 코드) # 1800 - 다시 부팅 필요(오류가 아님 - 다시 부팅 후 업데이트가 진행됨) # 1802 - 알려진 펌웨어 문제 차단 업데이트(SkipReason에서 KI_<번호> 캡처) # 1803 - 일치하는 KEK 업데이트를 찾을 수 없음(OEM은 PK 서명된 KEK를 제공해야 합니다.) # PS 버전: 3.0 이상 | 관리: 시스템 로그에 필요할 수 있음 | 시스템 요구 사항: 없음 try {     # 모든 관련 보안 부팅 이벤트 ID 쿼리     $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 "시스템 로그에서 보안 부팅 이벤트를 찾을 수 없음"         $latestEventId = $null         $bucketId = $null         $confidence = $null         $skipReasonKnownIssue = $null         $event 1801Count = 0         $event 1808Count = 0         $event 1795Count = 0         $event 1795ErrorCode = $null         $event 1796Count = 0         $event 1796ErrorCode = $null         $event 1800Count = 0         $rebootPending = $false         $event 1802Count = 0         $knownIssueId = $null         $event 1803Count = 0         $missingKEK = $false         Write-Host "최신 이벤트 ID: 사용할 수 없음"         Write-Host "버킷 ID: 사용할 수 없음"         Write-Host "신뢰도: 사용할 수 없음"         Write-Host "이벤트 1801 개수: 0"         Write-Host "이벤트 1808 개수: 0"     } else {         # 16. LatestEventId         $latestEvent = $events | Sort-Object TimeCreated -Descending | Select-Object -First 1         if ($null -eq $latestEvent) {             Write-Warning "최신 이벤트를 확인할 수 없음"             $latestEventId = $null             Write-Host "최신 이벤트 ID: 사용할 수 없음"         } else {             $latestEventId = $latestEvent.Id             Write-Host "최신 이벤트 ID: $latestEventId"         }

        # 17. BucketID - 이벤트 1801/1808에서 추출됨         if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketId:\s*(.+)') {                 $bucketId = $matches[1]. Trim()                 Write-Host "버킷 ID: $bucketId"             } else {                 Write-Warning "이벤트 메시지에서 BucketId를 찾을 수 없음"                 $bucketId = $null                 Write-Host "버킷 ID: 이벤트에서 찾을 수 없음"             }         } else {             Write-Warning "최신 이벤트 또는 메시지가 null이면 BucketId를 추출할 수 없습니다."             $bucketId = $null             Write-Host "버킷 ID: 사용할 수 없음"         }

        # 18. 신뢰도 - 이벤트 1801/1808에서 추출됨         if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') {                 $confidence = $matches[1]. Trim()                 Write-Host "신뢰도: $confidence"             } else {                 Write-Warning "이벤트 메시지에서 신뢰 수준을 찾을 수 없음"                 $confidence = $null                 Write-Host "신뢰도: 이벤트에서 찾을 수 없음"             }         } else {             Write-Warning "최신 이벤트 또는 메시지가 null이면 신뢰도를 추출할 수 없습니다."             $confidence = $null             Write-Host "신뢰도: 사용할 수 없음"         }

        # 18b. SkipReason - BucketId와 동일한 이벤트에서 SkipReason에서 KI_<번호> 추출         # 이 캡처는 BucketId/Confidence와 함께 표시되는 알려진 문제 ID를 캡처합니다(이벤트 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 알려진 문제: $skipReasonKnownIssue" -ForegroundColor 노란색             }         }

        # 19. Event1801Count         $event 1801Array = @($events | Where-Object {$_. Id -eq 1801})         $event 1801Count = $event 1801Array.Count         Write-Host "이벤트 1801 개수: $event 1801Count"

        # 20. Event1808Count         $event 1808Array = @($events | Where-Object {$_. Id -eq 1808})         $event 1808Count = $event 1808Array.Count         Write-Host "이벤트 1808 개수: $event 1808Count"         # 오류 이벤트 변수 초기화         $event 1795Count = 0         $event 1795ErrorCode = $null         $event 1796Count = 0         $event 1796ErrorCode = $null         $event 1800Count = 0         $rebootPending = $false         $event 1802Count = 0         $knownIssueId = $null         $event 1803Count = 0         $missingKEK = $false         # 업데이트가 완료되지 않은 경우 오류 이벤트에 대한 검사         # 오류 분석 건너뛰기: 1808이 최신 이벤트이거나 UEFICA2023Status가 "업데이트됨"인 경우         $updateComplete = ($latestEventId -eq 1808) -또는 ($uefica 2023Status -eq "Updated")         if (-not $updateComplete) {             Write-Host "업데이트가 완료되지 않음 - 오류 이벤트 확인 중..." -ForegroundColor 노란색             # 21.                                         Event1795 - 펌웨어 오류(캡처 오류 코드)             $event 1795Array = @($events | Where-Object {$_. Id -eq 1795})             $event 1795Count = $event 1795Array.Count             if ($event 1795Count -gt 0) {                 $latestEvent 1795 = $event 1795Array | Sort-Object TimeCreated -Descending | Select-Object -First 1                 if ($latestEvent 1795.Message -match '(?:error|code|상태)[:\s]*(?:0x)? ([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {                     $event 1795ErrorCode = $matches[1]                 }                 Write-Host "이벤트 1795(펌웨어 오류) 개수: $event 1795Count" $(if ($event 1795ErrorCode) { "Code: $event 1795ErrorCode" })             }             # 22.              Event1796 - 기록된 오류 코드(캡처 오류 코드)             $event 1796Array = @($events | Where-Object {$_. Id -eq 1796})             $event 1796Count = $event 1796Array.Count             if ($event 1796Count -gt 0) {                 $latestEvent 1796 = $event 1796Array | Sort-Object TimeCreated -Descending | Select-Object -First 1                 if ($latestEvent 1796.Message -match '(?:error|code|상태)[:\s]*(?:0x)? ([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {                     $event 1796ErrorCode = $matches[1]                 }                 Write-Host "이벤트 1796(오류 기록) 개수: $event 1796Count" $(if ($event 1796ErrorCode) { "Code: $event 1796ErrorCode" })             }             # 23.              Event1800 - 다시 부팅 필요(오류가 아님 - 다시 부팅 후 업데이트가 진행됨)             $event 1800Array = @($events | Where-Object {$_. Id -eq 1800})             $event 1800Count = $event 1800Array.Count             $rebootPending = $event 1800Count -gt 0             if ($rebootPending) {                 Write-Host "이벤트 1800(다시 부팅 보류 중): 다시 부팅한 후 업데이트가 진행됩니다." -ForegroundColor Cyan             }                          # 24. Event1802 - 알려진 펌웨어 문제(SkipReason에서 KI_<번호> 캡처)             $event 1802Array = @($events | Where-Object {$_. Id -eq 1802})             $event 1802Count = $event 1802Array.Count             if ($event 1802Count -gt 0) {                 $latestEvent 1802 = $event 1802Array | Sort-Object TimeCreated -Descending | Select-Object -First 1                 if ($latestEvent 1802.Message -match 'SkipReason:\s*(KI_\d+)') {                     $knownIssueId = $matches[1]                 }                 Write-Host "이벤트 1802(알려진 펌웨어 문제) 개수: $event 1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" })             }                          # 25. Event1803 - 누락된 KEK 업데이트(OEM은 PK 서명된 KEK를 제공해야 합니다).             $event 1803Array = @($events | Where-Object {$_. Id -eq 1803})             $event 1803Count = $event 1803Array.Count             $missingKEK = $event 1803Count -gt 0             if ($missingKEK) {                 Write-Host "이벤트 1803(누락된 KEK): OEM은 PK 서명 KEK를 제공해야 합니다." -ForegroundColor Yellow             }         } else {             Write-Host "업데이트 완료(이벤트 1808 또는 상태=업데이트됨) - 오류 분석 건너뛰기" -ForegroundColor 녹색         }     } } catch {     Write-Warning "이벤트 로그를 검색하는 동안 오류가 발생했습니다. 관리자 권한이 필요할 수 있음: $_"     $latestEventId = $null     $bucketId = $null     $confidence = $null     $skipReasonKnownIssue = $null     $event 1801Count = 0     $event 1808Count = 0     $event 1795Count = 0     $event 1795ErrorCode = $null     $event 1796Count = 0     $event 1796ErrorCode = $null     $event 1800Count = 0     $rebootPending = $false     $event 1802Count = 0     $knownIssueId = $null     $event 1803Count = 0     $missingKEK = $false     Write-Host "최신 이벤트 ID: 오류"     Write-Host "버킷 ID: 오류"     Write-Host "신뢰도: 오류"     Write-Host "이벤트 1801 개수: 0"     Write-Host "이벤트 1808 개수: 0" }

# WMI/CIM 쿼리(5개 값)

# 26. OSVersion # PS 버전: 3.0 이상(2.0에 Get-WmiObject 사용) | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction 중지     if ($null -eq $osInfo -또는 [string]::IsNullOrEmpty($osInfo.Version)) {         Write-Warning "OS 버전을 검색할 수 없음"         $osVersion = "알 수 없음"     } else {         $osVersion = $osInfo.Version     }     Write-Host "OS 버전: $osVersion" } catch {     # CIM이 일부 환경에서 실패할 수 있음 - 대체 사용     $osVersion = [System.Environment]::OSVersion.Version.ToString()     if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" }     Write-Host "OS 버전: $osVersion" }

# 27. LastBootTime # PS 버전: 3.0 이상(2.0에 Get-WmiObject 사용) | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction 중지     if ($null -eq $osInfo -또는 $null -eq $osInfo.LastBootUpTime) {         Write-Warning "마지막 부팅 시간을 검색할 수 없음"         $lastBootTime = $null         Write-Host "마지막 부팅 시간: 사용할 수 없음"     } else {         $lastBootTime = $osInfo.LastBootUpTime         Write-Host "마지막 부팅 시간: $lastBootTime"     } } catch {     # CIM이 일부 환경에서 실패할 수 있음 - 대체 사용     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 버전: 3.0 이상(2.0에 Get-WmiObject 사용) | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction 중지     if ($null -eq $baseBoard -또는 [string]::IsNullOrEmpty($baseBoard.Manufacturer)) {         Write-Warning "베이스보드 제조업체를 검색할 수 없음"         $baseBoardManufacturer = "알 수 없음"     } else {         $baseBoardManufacturer = $baseBoard.Manufacturer     }     Write-Host "베이스보드 제조업체: $baseBoardManufacturer" } catch {     # CIM이 실패할 수 있음 - 베이스보드 정보는 추가 정보입니다.     $baseBoardManufacturer = "알 수 없음"     Write-Host "베이스보드 제조업체: $baseBoardManufacturer" }

# 29. BaseBoardProduct # PS 버전: 3.0 이상(2.0에 Get-WmiObject 사용) | 관리: 아니요 | 시스템 요구 사항: 없음 try {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction 중지     if ($null -eq $baseBoard -또는 [string]::IsNullOrEmpty($baseBoard.Product)) {         Write-Warning "베이스보드 제품을 검색할 수 없음"         $baseBoardProduct = "알 수 없음"     } else {         $baseBoardProduct = $baseBoard.Product     }     Write-Host "베이스보드 제품: $baseBoardProduct" } catch {     # CIM이 실패할 수 있음 - 베이스보드 정보는 추가 정보입니다.     $baseBoardProduct = "알 수 없음"     Write-Host "베이스보드 제품: $baseBoardProduct" }

# 30. SecureBootTaskEnabled # PS 버전: 모두 | 관리: 아니요 | 시스템 요구 사항: 예약된 작업이 있음 # Secure-Boot-Update 예약된 작업이 사용하도록 설정되어 있는지 확인합니다. $secureBootTaskEnabled = $null $secureBootTaskStatus = "알 수 없음" 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' -또는 $taskData.Status -eq 'Running')         }     } else {         $secureBootTaskStatus = "NotFound"         $secureBootTaskEnabled = $false     }     if ($secureBootTaskEnabled -eq $false) {         Write-Host "SecureBoot 업데이트 작업: $secureBootTaskStatus(사용: $secureBootTaskEnabled)" -ForegroundColor Yellow     } else {         Write-Host "SecureBoot 업데이트 작업: $secureBootTaskStatus(사용: $secureBootTaskEnabled)" -ForegroundColor Green     } } catch {     $secureBootTaskStatus = "오류"     $secureBootTaskEnabled = $false     Write-Host "SecureBoot 업데이트 작업: 오류 검사 - $_" -ForegroundColor Red }

# 31. WinCS 키 상태(F33E0C8E002 - 보안 부팅 인증서 업데이트) # PS 버전: 모두 | 관리: 예(쿼리용) | 시스템 요구 사항: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "알 수 없음" try {     # WinCsFlags.exe 대한 공통 위치 확인     $wincsFlagsPath = $null     $possiblePaths = @(         "$env:SystemRoot\System32\WinCsFlags.exe",         "$env:SystemRoot\SysWOW64\WinCsFlags.exe"     )     foreach($possiblePaths $p) {         if (Test-Path $p) { $wincsFlagsPath = $p; break }     }     if ($wincsFlagsPath) {         # 쿼리 특정 키 - 관리자 권한이 필요합니다.         $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1         $queryOutputStr = $queryOutput -join "'n"         if ($LASTEXITCODE -eq 0) {             # 키가 적용되었는지 확인합니다("활성 구성" 또는 유사한 표시기를 찾습니다.)             if ($queryOutputStr -match "Active Configuration.*:.*enabled" -or $queryOutputStr -match "Configuration.*applied") {                 $wincsKeyApplied = $true                 $wincsKeyStatus = "적용됨"                 Write-Host "WinCS 키 F33E0C8E002: 적용됨" -ForegroundColor 녹색             } elseif($queryOutputStr -match "찾을 수 없음|구성 없음") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "WinCS 키 F33E0C8E002: 적용되지 않음" -ForegroundColor 노란색             } else {                 # 키가 있음 - 상태에 대한 출력 검사                 $wincsKeyApplied = $true                 $wincsKeyStatus = "적용됨"                 Write-Host "WinCS 키 F33E0C8E002: 적용됨" -ForegroundColor 녹색             }         } else {             # 특정 오류 메시지 확인             if ($queryOutputStr -match "Access denied|administrator") {                 $wincsKeyStatus = "AccessDenied"                 Write-Host "WinCS 키 F33E0C8E002: 액세스 거부(관리자 권한으로 실행)" -ForegroundColor DarkGray             } elseif($queryOutputStr -match "찾을 수 없음|구성 없음") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "WinCS 키 F33E0C8E002: 적용되지 않음" -ForegroundColor 노란색             } else {                 $wincsKeyStatus = "QueryFailed"                 Write-Host "WinCS 키 F33E0C8E002: 쿼리 실패" -ForegroundColor Red             }         }     } else {         $wincsKeyStatus = "WinCsFlagsNotFound"         Write-Host "WinCS 키 F33E0C8E002: WinCsFlags.exe 찾을 수 없음" -ForegroundColor Gray     } } catch {     $wincsKeyStatus = "오류"     Write-Host "WinCS 키 F33E0C8E002: 오류 검사 - $_" -ForegroundColor Red }              

# ============================================================================= # 수정 검색 - 상태 출력 & 종료 코드 # =============================================================================

# 수집된 모든 인벤토리 데이터에서 상태 개체 빌드 $상태 = [ordered]@{     UEFICA2023Status = $uefica 2023Status     UEFICA2023Error = $uefica 2023Error     UEFICA2023ErrorEvent = $uefica 2023ErrorEvent     AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } else { $null }     AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } else { $null }     호스트 이름 = $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     SkipReasonKnownIssue = bucketId 이벤트의 SkipReason에서 $skipReasonKnownIssue # KI_<번호>     Event1801Count = $event 1801Count     Event1808Count = $event 1808Count     # 캡처된 세부 정보가 있는 오류 이벤트     Event1795Count = $event 1795Count # Firmware 반환 오류     Event1795ErrorCode = $event 1795ErrorCode # 펌웨어의 오류 코드     Event1796Count = $event 1796Count # 오류 코드가 기록됨     Event1796ErrorCode = $event 1796ErrorCode # 캡처된 오류 코드     Event1800Count = $event 1800Count # 다시 부팅 필요(오류가 아님)     RebootPending = $rebootPending # True이면 이벤트 1800이 존재합니다.     Event1802Count = $event 1802Count # 알려진 펌웨어 문제     KnownIssueId = skipReason의 $knownIssueId # KI_<번호>     Event1803Count = $event 1803Count # 누락된 KEK 업데이트     MissingKEK = $missingKEK # OEM은 PK 서명 KEK를 제공해야 합니다.     OSVersion = $osVersion     LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" }     BaseBoardManufacturer = $baseBoardManufacturer     BaseBoardProduct = $baseBoardProduct     SecureBootTaskEnabled = $secureBootTaskEnabled     SecureBootTaskStatus = $secureBootTaskStatus     WinCSKeyApplied = $wincsKeyApplied # true이면 F33E0C8E002 키가 적용됩니다.     WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound 등 }

# 상태 출력 - 데이터 집계용 $jsonOutput = $상태 | ConvertTo-Json -Compress

# OutputPath가 제공된 경우 파일에 저장합니다. 그렇지 않으면 stdout에 출력됩니다. if (-not [string]::IsNullOrEmpty($OutputPath)) {     # OutputPath 유효성 검사 - 도움말 요청처럼 보이거나 잘못된 문자가 있는 경우 건너뜁니다.     if ($OutputPath -match '^[/\-]' -또는 $OutputPath -match '[<>:"|? *]') {         Write-Host "잘못된 OutputPath가 지정되어 stdout에 출력됨" -ForegroundColor Yellow         Write-Output $jsonOutput         if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 } else { exit 1 }     }          # 출력 폴더가 있는지 확인     if (-not (Test-Path $OutputPath)) {         try {             New-Item -ItemType 디렉터리 -경로 $OutputPath -Force | Out-Null         } catch {             Write-Warning "출력 폴더를 만들 수 없습니다. $OutputPath - $_"         }     }          # HOSTNAME_latest.json 저장     $outputFile = "$($hostname)_latest.json"Join-Path $OutputPath     try {         $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force         Write-Host "저장한 JSON: $outputFile" -ForegroundColor Green     } catch {         Write-Warning "파일에 쓸 수 없음: $outputFile - $_"         # stdout으로 대체         Write-Output $jsonOutput     } } else {     # 원래 동작 - stdout에 출력     Write-Output $jsonOutput }

# 종료 코드: "업데이트됨"은 플레이북당 성공 값입니다. if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") {     exit 0 # without issue } else {     exit 1 # With issue }

날짜 변경

설명 변경

2026년 5월 13일

  • 2026년 5월 13일 또는 그 이후에 Windows 업데이트 릴리스가 설치된 후 디바이스에서 샘플 스크립트를 사용할 수 있으므로 문서 맨 위에 다음이 추가되었습니다.중요 샘플 스크립트를 포함하는 이 문서는 사용 중지되었습니다. 2026년 5월 12일 이후에 릴리스된 Windows 업데이트부터 샘플 스크립트는 디바이스의 %systemroot%\SecureBoot\ExampleRolloutScripts 폴더에 있습니다.

2026년 2월 24일

  • 샘플 보안 부팅 인벤토리 데이터 수집 스크립트를 업데이트했습니다.

2026년 2월 22일

  • 샘플 보안 부팅 인벤토리 데이터 수집 스크립트를 업데이트했습니다.

2026년 2월 13일

  • 샘플 보안 부팅 인벤토리 데이터 수집 스크립트를 업데이트했습니다.

도움이 더 필요하세요?

더 많은 옵션을 원하세요?

구독 혜택을 살펴보고, 교육 과정을 찾아보고, 디바이스를 보호하는 방법 등을 알아봅니다.