documents:tools:others:tools-003
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン | |||
| documents:tools:others:tools-003 [2026/03/30 06:39] – [説明] k896951 | documents:tools:others:tools-003 [2026/05/07 22:22] (現在) – ↷ 移動操作に合わせてリンクを書き換えました。 k896951 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== セキュアブート関連確認ツール ====== | ||
| + | 2026年3月28日\\ | ||
| + | YouTubeのとあるセキュアブート問題説明動画を見てちょっとモヤったので作りました。 | ||
| + | |||
| + | |||
| + | ===== SecureBoot-Checkダウンロード ===== | ||
| + | |||
| + | <WRAP download> | ||
| + | {{ : | ||
| + | </ | ||
| + | |||
| + | ===== 説明 ===== | ||
| + | |||
| + | セキュアブート関連設定を確認するためのツールです。 | ||
| + | |||
| + | [[..: | ||
| + | |||
| + | PowerShell5.1で動作を確認しています。 | ||
| + | |||
| + | PowerShellのコンソールからスクリプトを実行する場合、そのコンソールは管理者として実行してください。 | ||
| + | SecureBoot-Check.ps1が G:\sandbox に存在する場合、 | ||
| + | |||
| + | cd /d G:\sandbox | ||
| + | powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\SecureBoot-Check.ps1 | ||
| + | |||
| + | EXEから実行する場合はSecureBoot-Check.exeをダブルクリックしてください。 | ||
| + | UACで管理者権限を要求するので与えてください。 | ||
| + | |||
| + | {{.: | ||
| + | |||
| + | Readme.txtに説明を入れているのでそちらを確認しましょう。 | ||
| + | ===== その他 ===== | ||
| + | |||
| + | 作り上、アンチウイルス製品が何か検出して動作を止めてくるかもしれません。 | ||
| + | ※特にEXE実行時 | ||
| + | |||
| + | ===== その他2 ===== | ||
| + | |||
| + | 駄目だダウンロードが阻止される… | ||
| + | |||
| + | PowerShellのコードも公開しておく(ZIP内にも入っている奴) | ||
| + | |||
| + | <code powershell SecureBoot-Check.ps1> | ||
| + | #requires -version 5.1 | ||
| + | # SecureBoot-Check.ps1 | ||
| + | # GUIで KEK/db/dbx と、公式レジストリ進捗(UEFICA2023Status等)を表示し、 | ||
| + | # 結果に応じた推奨アクション(分岐ロジック)を下部に出す。 | ||
| + | # PS2EXEで -noConsole -requireAdmin を付けてEXE化する想定。 | ||
| + | |||
| + | Set-StrictMode -Version Latest | ||
| + | $ErrorActionPreference = ' | ||
| + | |||
| + | Add-Type -AssemblyName System.Windows.Forms | Out-Null | ||
| + | Add-Type -AssemblyName System.Drawing | ||
| + | |||
| + | # ------------------------ | ||
| + | # 権限チェック(要件どおり:警告して終了) | ||
| + | # ------------------------ | ||
| + | function Assert-AdminOrExit { | ||
| + | $id = [Security.Principal.WindowsIdentity]:: | ||
| + | $p = New-Object Security.Principal.WindowsPrincipal($id) | ||
| + | if (-not $p.IsInRole([Security.Principal.WindowsBuiltInRole]:: | ||
| + | [System.Windows.Forms.MessageBox]:: | ||
| + | " | ||
| + | " | ||
| + | [System.Windows.Forms.MessageBoxButtons]:: | ||
| + | [System.Windows.Forms.MessageBoxIcon]:: | ||
| + | ) | Out-Null | ||
| + | exit 1 | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # ------------------------ | ||
| + | # PowerShell標準チェック | ||
| + | # ------------------------ | ||
| + | function Try-ConfirmSecureBoot { | ||
| + | try { return Confirm-SecureBootUEFI } catch { return $null } | ||
| + | } | ||
| + | |||
| + | |||
| + | function Test-ByteSubsequence { | ||
| + | param( | ||
| + | [Parameter(Mandatory)][byte[]]$Haystack, | ||
| + | [Parameter(Mandatory)][byte[]]$Needle | ||
| + | ) | ||
| + | |||
| + | if ($Needle.Length -eq 0) { return $true } | ||
| + | if ($Haystack.Length -lt $Needle.Length) { return $false } | ||
| + | |||
| + | for ($i = 0; $i -le $Haystack.Length - $Needle.Length; | ||
| + | $ok = $true | ||
| + | for ($j = 0; $j -lt $Needle.Length; | ||
| + | if ($Haystack[$i + $j] -ne $Needle[$j]) { $ok = $false; break } | ||
| + | } | ||
| + | if ($ok) { return $true } | ||
| + | } | ||
| + | return $false | ||
| + | } | ||
| + | |||
| + | function Try-UefiVarMatch { | ||
| + | param( | ||
| + | [Parameter(Mandatory)][string[]]$Names, | ||
| + | [Parameter(Mandatory)][string]$Needle | ||
| + | ) | ||
| + | |||
| + | function Test-ByteSubsequence { | ||
| + | param([byte[]]$Haystack, | ||
| + | if ($Needle.Length -eq 0) { return $true } | ||
| + | if ($Haystack.Length -lt $Needle.Length) { return $false } | ||
| + | |||
| + | for ($i = 0; $i -le $Haystack.Length - $Needle.Length; | ||
| + | $ok = $true | ||
| + | for ($j = 0; $j -lt $Needle.Length; | ||
| + | if ($Haystack[$i + $j] -ne $Needle[$j]) { $ok = $false; break } | ||
| + | } | ||
| + | if ($ok) { return $true } | ||
| + | } | ||
| + | return $false | ||
| + | } | ||
| + | |||
| + | $errs = @() | ||
| + | $needleAscii = [System.Text.Encoding]:: | ||
| + | $needleUtf16 = [System.Text.Encoding]:: | ||
| + | |||
| + | foreach ($n in $Names) { | ||
| + | try { | ||
| + | # Get-SecureBootUEFI は UEFI変数を Bytes(byte[]) として返す | ||
| + | $bytes = (Get-SecureBootUEFI -Name $n -ErrorAction Stop).Bytes | ||
| + | |||
| + | $matched = (Test-ByteSubsequence $bytes $needleAscii) -or | ||
| + | | ||
| + | |||
| + | return [pscustomobject]@{ | ||
| + | Readable = $true | ||
| + | Matched | ||
| + | Error = $null | ||
| + | Source | ||
| + | } | ||
| + | } | ||
| + | catch { | ||
| + | $errs += ($n + ": " + $_.Exception.Message) | ||
| + | } | ||
| + | } | ||
| + | |||
| + | return [pscustomobject]@{ | ||
| + | Readable = $false | ||
| + | Matched | ||
| + | Error = ($errs -join " | ") | ||
| + | Source | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # ------------------------ | ||
| + | # 公式レジストリ読み取り | ||
| + | # ------------------------ | ||
| + | function Try-GetRegValue { | ||
| + | param( | ||
| + | [Parameter(Mandatory)][string]$Path, | ||
| + | [Parameter(Mandatory)][string]$Name | ||
| + | ) | ||
| + | |||
| + | try { | ||
| + | $v = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop).$Name | ||
| + | return [pscustomobject]@{ | ||
| + | Readable = $true | ||
| + | Value = $v | ||
| + | Error = $null | ||
| + | } | ||
| + | } | ||
| + | catch { | ||
| + | return [pscustomobject]@{ | ||
| + | Readable = $false | ||
| + | Value = $null | ||
| + | Error = $_.Exception.Message | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function To-Hex([object]$v) { | ||
| + | if ($null -eq $v) { return "" | ||
| + | try { | ||
| + | $n = [uint32]$v | ||
| + | return (" | ||
| + | } catch { | ||
| + | return " | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function ShortErr([string]$s) { | ||
| + | if ([string]:: | ||
| + | if ($s.Length -gt 160) { return $s.Substring(0, | ||
| + | return $s | ||
| + | } | ||
| + | |||
| + | function BoolText([bool]$b) { | ||
| + | if ($b) { " | ||
| + | } | ||
| + | |||
| + | # ------------------------ | ||
| + | # UIヘルパ | ||
| + | # ------------------------ | ||
| + | |||
| + | function Set-RowBool { | ||
| + | param( | ||
| + | [System.Windows.Forms.ListViewItem]$Item, | ||
| + | [object]$Value, | ||
| + | [string]$Note, | ||
| + | [string]$Err | ||
| + | ) | ||
| + | |||
| + | if ($null -eq $Value) { | ||
| + | $Item.SubItems[1].Text = " | ||
| + | $Item.ForeColor = [System.Drawing.Color]:: | ||
| + | |||
| + | $se = ShortErr $Err | ||
| + | if ($null -ne $se) { $Item.SubItems[2].Text = $Note + " / " + $se } | ||
| + | else { $Item.SubItems[2].Text = $Note } | ||
| + | return | ||
| + | } | ||
| + | |||
| + | # $Value は bool のことも Nullable[bool] のこともあるので、boolに寄せて評価 | ||
| + | $b = [bool]$Value | ||
| + | if ($b) { | ||
| + | $Item.SubItems[1].Text = " | ||
| + | $Item.ForeColor = [System.Drawing.Color]:: | ||
| + | } else { | ||
| + | $Item.SubItems[1].Text = " | ||
| + | $Item.ForeColor = [System.Drawing.Color]:: | ||
| + | } | ||
| + | $Item.SubItems[2].Text = $Note | ||
| + | } | ||
| + | |||
| + | function Set-RowText { | ||
| + | param( | ||
| + | [System.Windows.Forms.ListViewItem]$Item, | ||
| + | [string]$ValueText, | ||
| + | [string]$Note, | ||
| + | [string]$Err | ||
| + | ) | ||
| + | |||
| + | if (-not [string]:: | ||
| + | $Item.SubItems[1].Text = $ValueText | ||
| + | $Item.ForeColor = [System.Drawing.Color]:: | ||
| + | $Item.SubItems[2].Text = $Note | ||
| + | } else { | ||
| + | $Item.SubItems[1].Text = " | ||
| + | $Item.ForeColor = [System.Drawing.Color]:: | ||
| + | |||
| + | $se = ShortErr $Err | ||
| + | if ($null -ne $se) { | ||
| + | $Item.SubItems[2].Text = $Note + " / " + $se | ||
| + | } else { | ||
| + | $Item.SubItems[2].Text = $Note | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # ------------------------ | ||
| + | # 推奨アクション生成(分岐ロジック) | ||
| + | # ------------------------ | ||
| + | function Build-Recommendations { | ||
| + | param( | ||
| + | [Nullable[bool]]$SecureBoot, | ||
| + | [string]$UEFICA2023Status, | ||
| + | [Nullable[uint32]]$UEFICA2023Error, | ||
| + | [Nullable[uint32]]$UEFICA2023ErrorEvent, | ||
| + | [Nullable[uint32]]$AvailableUpdates, | ||
| + | [string]$ConfidenceLevel, | ||
| + | [Nullable[bool]]$Kek2023, | ||
| + | [Nullable[bool]]$Db2023, | ||
| + | [Nullable[bool]]$DbxWinUefi2023, | ||
| + | [Nullable[bool]]$DbxPca2011 | ||
| + | ) | ||
| + | |||
| + | $out = New-Object System.Collections.Generic.List[string] | ||
| + | $out.Add(" | ||
| + | |||
| + | # 1) 前提 | ||
| + | if ($SecureBoot -eq $false) { | ||
| + | $out.Add(" | ||
| + | $out.Add(" | ||
| + | return ($out -join " | ||
| + | } | ||
| + | elseif ($SecureBoot -eq $null) { | ||
| + | $out.Add(" | ||
| + | $out.Add(" | ||
| + | } else { | ||
| + | $out.Add(" | ||
| + | } | ||
| + | |||
| + | # 2) 公式進捗(主軸) | ||
| + | if (-not [string]:: | ||
| + | switch ($UEFICA2023Status) { | ||
| + | " | ||
| + | $out.Add(" | ||
| + | } | ||
| + | " | ||
| + | $out.Add(" | ||
| + | } | ||
| + | " | ||
| + | $out.Add(" | ||
| + | $out.Add(' | ||
| + | $out.Add(" | ||
| + | } | ||
| + | default { | ||
| + | $out.Add((" | ||
| + | } | ||
| + | } | ||
| + | } else { | ||
| + | $out.Add(" | ||
| + | $out.Add(" | ||
| + | } | ||
| + | |||
| + | # 3) エラーがあるならそこが最優先 | ||
| + | if ($UEFICA2023Error -ne $null -and ([uint32]$UEFICA2023Error) -ne 0) { | ||
| + | $out.Add(" | ||
| + | if ($UEFICA2023ErrorEvent -ne $null) { | ||
| + | $out.Add((" | ||
| + | } | ||
| + | $out.Add(" | ||
| + | } | ||
| + | |||
| + | # 4) AvailableUpdates(IT管理向け観測) | ||
| + | if ($AvailableUpdates -ne $null) { | ||
| + | $out.Add((" | ||
| + | } | ||
| + | |||
| + | if (-not [string]:: | ||
| + | $out.Add((" | ||
| + | } | ||
| + | |||
| + | # 5) 参考(文字列マッチ) | ||
| + | $out.Add(" | ||
| + | if ($Kek2023 -ne $null) { $out.Add((" | ||
| + | if ($Db2023 | ||
| + | |||
| + | if ($DbxWinUefi2023 -ne $null) { | ||
| + | $out.Add((" | ||
| + | } | ||
| + | if ($DbxPca2011 -ne $null) { | ||
| + | $out.Add((" | ||
| + | } | ||
| + | |||
| + | $out.Add("" | ||
| + | $out.Add(" | ||
| + | $out.Add(" | ||
| + | $out.Add(" | ||
| + | |||
| + | return ($out -join " | ||
| + | } | ||
| + | |||
| + | # ---- UI開始 ---- | ||
| + | Assert-AdminOrExit | ||
| + | |||
| + | $form = New-Object System.Windows.Forms.Form | ||
| + | $form.Text = " | ||
| + | $form.Size = New-Object System.Drawing.Size(1040, | ||
| + | $form.StartPosition = " | ||
| + | $form.MaximizeBox = $false | ||
| + | |||
| + | $btnRun = New-Object System.Windows.Forms.Button | ||
| + | $btnRun.Text = " | ||
| + | $btnRun.Size = New-Object System.Drawing.Size(120, | ||
| + | $btnRun.Location = New-Object System.Drawing.Point(12, | ||
| + | |||
| + | $btnCopy = New-Object System.Windows.Forms.Button | ||
| + | $btnCopy.Text = " | ||
| + | $btnCopy.Size = New-Object System.Drawing.Size(120, | ||
| + | $btnCopy.Location = New-Object System.Drawing.Point(140, | ||
| + | |||
| + | $lbl = New-Object System.Windows.Forms.Label | ||
| + | $lbl.AutoSize = $true | ||
| + | $lbl.Location = New-Object System.Drawing.Point(280, | ||
| + | $lbl.Text = " | ||
| + | |||
| + | $split = New-Object System.Windows.Forms.SplitContainer | ||
| + | $split.Orientation = [System.Windows.Forms.Orientation]:: | ||
| + | $split.Location = New-Object System.Drawing.Point(12, | ||
| + | $split.Size = New-Object System.Drawing.Size(1000, | ||
| + | $split.Anchor = ' | ||
| + | $split.SplitterWidth = 6 | ||
| + | $split.Panel1MinSize = 180 | ||
| + | $split.Panel2MinSize = 80 | ||
| + | $split.SplitterDistance = 260 # 初期:上を広めに | ||
| + | |||
| + | $list = New-Object System.Windows.Forms.ListView | ||
| + | $list.View = ' | ||
| + | $list.FullRowSelect = $true | ||
| + | $list.GridLines = $true | ||
| + | $list.Dock | ||
| + | |||
| + | [void]$list.Columns.Add(" | ||
| + | [void]$list.Columns.Add(" | ||
| + | [void]$list.Columns.Add(" | ||
| + | |||
| + | function Add-Row([string]$title, | ||
| + | $it = New-Object System.Windows.Forms.ListViewItem($title) | ||
| + | [void]$it.SubItems.Add("" | ||
| + | [void]$it.SubItems.Add($note) | ||
| + | [void]$list.Items.Add($it) | ||
| + | return $it | ||
| + | } | ||
| + | |||
| + | $rowSB | ||
| + | $rowKEK | ||
| + | $rowDB | ||
| + | $rowDBX1 | ||
| + | $rowDBX2 | ||
| + | |||
| + | $rowStat | ||
| + | $rowErr | ||
| + | $rowErrEv = Add-Row " | ||
| + | $rowCap | ||
| + | $rowAvail = Add-Row " | ||
| + | $rowConf | ||
| + | |||
| + | $log = New-Object System.Windows.Forms.TextBox | ||
| + | $log.Multiline | ||
| + | $log.ScrollBars = " | ||
| + | $log.ReadOnly | ||
| + | $log.Dock | ||
| + | |||
| + | function Run-Checks { | ||
| + | |||
| + | # 1) SecureBoot | ||
| + | $sb = Try-ConfirmSecureBoot | ||
| + | Set-RowBool -Item $rowSB -Value $sb -Note " | ||
| + | |||
| + | # KEK確認(Active→Default) | ||
| + | $r = Try-UefiVarMatch -Names @(' | ||
| + | $kek2023 = $r.Matched | ||
| + | $err = $r.Error | ||
| + | $src = $r.Source | ||
| + | $srcText = " | ||
| + | if ($null -ne $src -and $src -ne "" | ||
| + | Set-RowBool -Item $rowKEK -Value $kek2023 -Note (" | ||
| + | |||
| + | # DB確認 | ||
| + | $r = Try-UefiVarMatch -Names @(' | ||
| + | $db2023 = $r.Matched | ||
| + | $err = $r.Error | ||
| + | $src = $r.Source | ||
| + | $srcText = " | ||
| + | if ($null -ne $src -and $src -ne "" | ||
| + | Set-RowBool -Item $rowDB -Value $db2023 -Note (" | ||
| + | |||
| + | # DBX確認 | ||
| + | # 何処かのパソコン博士が説明してない話 | ||
| + | $r = Try-UefiVarMatch -Names @(' | ||
| + | $dbxWinUefi2023 = $r.Matched | ||
| + | $err = $r.Error | ||
| + | $src = $r.Source | ||
| + | $srcText = " | ||
| + | if ($null -ne $src -and $src -ne "" | ||
| + | Set-RowBool -Item $rowDBX1 -Value $dbxWinUefi2023 -Note (" | ||
| + | | ||
| + | # DBX確認(失効対象確認) | ||
| + | $r = Try-UefiVarMatch -Names @(' | ||
| + | $dbxPca2011 = $r.Matched | ||
| + | $err = $r.Error | ||
| + | $src = $r.Source | ||
| + | $srcText = " | ||
| + | if ($null -ne $src -and $src -ne "" | ||
| + | Set-RowBool -Item $rowDBX2 -Value $dbxPca2011 -Note (" | ||
| + | |||
| + | # 3) 公式レジストリ | ||
| + | $pBase = " | ||
| + | $pSvc = " | ||
| + | |||
| + | ## 公式進捗 | ||
| + | $r = Try-GetRegValue -Path $pSvc -Name " | ||
| + | $status = $r.Value | ||
| + | $e1 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $status) { $vt = " | ||
| + | Set-RowText -Item $rowStat -ValueText $vt -Note " | ||
| + | |||
| + | ## 公式エラー情報 | ||
| + | $r = Try-GetRegValue -Path $pSvc -Name " | ||
| + | $errCodeN = $r.Value | ||
| + | $e2 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $errCodeN) { $vt = " | ||
| + | Set-RowText -Item $rowErr -ValueText $vt -Note " | ||
| + | |||
| + | ## 公式エラー時関連イベントID | ||
| + | $r = Try-GetRegValue -Path $pSvc -Name " | ||
| + | $errEvN = $r.Value | ||
| + | $e3 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $errEvN) { $vt = " | ||
| + | Set-RowText -Item $rowErrEv -ValueText $vt -Note " | ||
| + | |||
| + | ## 公式エラー時参考用 | ||
| + | $r = Try-GetRegValue -Path $pSvc -Name " | ||
| + | $capN = $r.Value | ||
| + | $e4 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $capN) { $vt = " | ||
| + | Set-RowText -Item $rowCap -ValueText $vt -Note " | ||
| + | |||
| + | ## IT管理方式の観測用(公式) | ||
| + | $r = Try-GetRegValue -Path $pBase -Name " | ||
| + | $availN = $r.Value | ||
| + | $e5 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $availN) { $vt = " | ||
| + | Set-RowText -Item $rowAvail -ValueText $vt -Note " | ||
| + | |||
| + | ## 段階展開のヒント(公式) | ||
| + | $r = Try-GetRegValue -Path $pSvc -Name " | ||
| + | $conf = $r.Value | ||
| + | $e6 = $r.Error | ||
| + | $vt = "" | ||
| + | if ($r.Readable -and $null -ne $conf) { $vt = " | ||
| + | Set-RowText -Item $rowConf -ValueText $vt -Note " | ||
| + | |||
| + | # 4) 分岐ロジックの結論 | ||
| + | $log.Text = Build-Recommendations ` | ||
| + | -SecureBoot $sb ` | ||
| + | -UEFICA2023Status ($status -as [string]) ` | ||
| + | -UEFICA2023Error $errCodeN ` | ||
| + | -UEFICA2023ErrorEvent $errEvN ` | ||
| + | -AvailableUpdates $availN ` | ||
| + | -ConfidenceLevel ($conf -as [string]) ` | ||
| + | -Kek2023 $kek2023 ` | ||
| + | -Db2023 $db2023 ` | ||
| + | -DbxWinUefi2023 $dbxWinUefi2023 ` | ||
| + | -DbxPca2011 $dbxPca2011 | ||
| + | } | ||
| + | |||
| + | function Copy-ResultsToClipboard { | ||
| + | $lines = New-Object System.Collections.Generic.List[string] | ||
| + | foreach ($it in $list.Items) { | ||
| + | $lines.Add((" | ||
| + | } | ||
| + | [System.Windows.Forms.Clipboard]:: | ||
| + | $log.Text = " | ||
| + | } | ||
| + | |||
| + | $btnRun.Add_Click({ Run-Checks }) | ||
| + | $btnCopy.Add_Click({ Copy-ResultsToClipboard }) | ||
| + | |||
| + | |||
| + | $split.Panel1.Controls.Add($list) | ||
| + | $split.Panel2.Controls.Add($log) | ||
| + | |||
| + | $form.Controls.AddRange(@($btnRun, | ||
| + | |||
| + | # 初回自動実行 | ||
| + | Run-Checks | ||
| + | |||
| + | [void]$form.ShowDialog() | ||
| + | |||
| + | </ | ||
| + | |||
| + | {{tag> | ||
documents/tools/others/tools-003.txt · 最終更新: by k896951
