セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.9 PowerShellサンプル「PatcthWinREScript_」の別の味わい方
2024年05月13日配信
2024年06月18日更新
執筆者:山内 和朗
私はプログラムやスクリプトをゼロからゴリゴリ書くようなタイプではありません。自分がやりたいことに近い、あるいは参考になりそうなスクリプトやコマンドラインに出会うと、コードを追いかけて調べ上げ、自分の目的のために美味しく頂戴いたします。このブログでこれまで取り上げてきた、WinREの脆弱性に対策するMicrosoft提供のPowerShellスクリプトのサンプルもまた、とても美味しそうです。
Microsoftは、「CVE-2024-20666(外部サイト)」の脆弱性(ただし、悪用される可能性は“低い”)に対する手動によるパッチ作業を簡素化するPowerShellスクリプトのサンプル「PatchWinREScript_2004plus.ps1」(Windows 10バージョン2004以降向け)と「PatchWinREScript_General.ps1」(汎用向け)を、以下のKBで公開しています。
KB5034957: CVE-2024-20666 のセキュリティの脆弱性に対処するために、展開されたデバイスの WinRE パーティションを更新する
https://support.microsoft.com/ja-jp/help/5034957
前回は、Windows Server 2019に対してこのサンプルスクリプトを実行して、このオフラインパッチによる脆弱性対策を実際に行ってみました(画面1)。
画面1 オフラインパッチに成功した「PatchWinREScript_General.ps1」の出力結果
画面1の出力結果を見ると、WinREの状態や場所の情報を取得するコードが含まれていることが分かります。これに関しては、もっと良い別のサンプルがあるので次回以降に回すとして、サンプルスクリプトのコードを追いかけていくと、他にも応用できそうなテクニックがいくつか見つかります。
例えば、WinREのベースとなっているWindowsのバージョン/ビルド情報を取得してパッチの必要性を判断している部分があります。それには、WinREイメージ内のバイナリ「winload.efi」からファイルバージョン情報を取得し、Windows 10以降のWinREイメージであるか(10.0.*.*)、Windows 10以降のWinREイメージの場合、Windowsのバージョン(ビルド)ごとにリビジョン番号まで調べて(10.0.ビルド.リビジョン)、パッチ済みであるかどうかを判断しています(画面2)。例えば、Windows 11バージョン22H2/23H2の場合、WinREのバージョンが「10.0.22621.3000」以降(2024年1月の累積更新プログラムのOSビルド.リビジョンは「10.0.22621/22631.3007」、WinREは22H2/23H2で共通)であればパッチ済みの扱いになります。
WinREはWindowsのように更新プログラムでバージョン情報のリビジョン番号「ビルド.リビジョン」が更新されることはありません。画面2のWindows Server 2019の場合、パッチ前もパッチ後も、WinREのコマンドプロンプトで実行するverコマンドは「Version 10.0.17763.1」を返します。そのため、WinREがパッチ済みであるかどうかは、更新されたバイナリであるかどうかで判断する必要があるのです。Windows 10バージョン1809およびWindows Server 2019の場合、「10.0.17763.5322」以降のバイナリに更新されたWinREがパッチ済みということになります。
WinREイメージ内のバイナリからのファイルバージョン情報の取得は、WinREイメージのマウント/アンマウント操作を伴う複雑なコードになるため、ここでは取り上げません(※追記参照)。(稼働中のWindowsの)ファイルバージョン情報の取得のテクニックとして、頭の片隅にでも置ておこうと思います。
画面2 パッチが必要かどうか判断するために、ローカルマウントしたWinREイメージ内のバイナリ「winload.efi」からファイルバージョン情報を取得しているところ(一部)
今回、私が最も注目したのは、BitLockerドライブ暗号化に関する情報取得のテクニックです(画面3)。
画面3 サンプルスクリプトには、BitLockerドライブ暗号化の情報を取得するコードが含まれている
サンプルスクリプトからほとんどそのままコピペした以下のコードをPowerShell(管理者)で実行することで、C:ドライブでBitLockerドライブ暗号化が有効になっているかどうかを確認、およびその状態を取得することができます(画面4、画面5)。$BitLockerにオブジェクトが返ってくれば有効、そうでなければBitLockerがサポートされていない環境(BitLockerドライブ暗号化の機能が有効になっていないWindows Serverなど)です。$BitLockerオブジェクトが返ってくる場合、$BitLockerオブジェクトが示すさまざまな情報のうち、IsVolumeInitializedForProtectionがTrueであればドライブで保護の準備が済んでおり(つまりBitLockerが有効、Falseの場合はBitLockerが無効)、ProtectionStatusを見れば保護の状態(1:オン/0:オフ)がわかります。
画面4 C:ドライブがBitLockerドライブ暗号化で保護されている場合
上記の5行のコード(つまりMicrosoftのサンプルスクリプトの書き方)は、実はあまりお勧めできるものではありません。「Get-WmiObject(外部サイト)」は古いコマンドレットであり、Windows PowerShell 3.0以降で「Get-CimInstance(外部サイト)」に置き換えられたことになっています。Windows PowerShell 5.1では問題なく機能しますが、PowerShell(.pwsh.exe)ではエラーになる場合があります。確認した限りでは、Windows 10にインストールしたPowerShellでは、Get-WmiObjectはコマンドレットして認識されず、エラーになります。
したがって、Get-WmiObjectの代わりにGet-CimInstanceを使用するべきです(両者のパラメーターはほぼ共通です)。以下はGet-CimInstanceを使用した場合のサンプルコードです。このサンプルは、BitLockerの有効/無効の状態と保護の状態を出力するように(画面5)、さらにカスタマイズを加えています。
画面5 C:ドライブがBitLockerドライブ暗号化で保護されていない場合
上記のコードはカスタマイズ部分を含めて、サンプルスクリプトのヘルパーファンクションである「IsTPMBasedProtector」ファンクション定義に含まれています。IsTPMBasedProtectorファンクションではさらに、キー保護の種類(TPMのみ、TPM+PIN、TPM+スタートアップキー、TPM+PIN+スタートアップキー)や、TPMベースの保護であるかどうかといったさらに詳しい情報も取得しています。IsTPMBasedProtectorファンクションの機能すべてを拝借したいなら、このファンクションと「LogMessage」ファンクションの定義を丸ごとコピーし、最後にIsTPMBasedProtectorファンクションを呼び出すことで簡単に実現できます。
このスクリプトの出力結果は画面6のようになります(BitLockerドライブ暗号化が有効な場合)。なお、先ほど触れたように、Get-WmiObjectコマンドレットは.NETベースのPowerShell(pwsh.exe)で実行するとInvalidOperationエラーが発生する場合があるので注意してください。つまり、Microsoft提供のPowerShellサンプルスクリプトも、PowerShell(pwsh.exe)で実行するとエラーになる場合があります。
画面6 IsTPMBasedProtectorファンクション全体を拝借したサンプルスクリプト。.NETベースのPowerShell(pwsh.exe)ではエラーになることに注意
Microsoft提供のサンプルスクリプトはWinREのBitLockerバイパス脆弱性のパッチが目的であるためC:ドライブのみを対象としていますが、ドライブ文字を変えてあげれば、データドライブを含めて暗号化保護を取得できるでしょう。
ここまで、Microsoft提供のPowerShellサンプルスクリプトから拝借したテクニックは、WMIからBitLockerドライブ暗号化の情報を取得するものでした。Windows標準のコマンドラインツール「manage-bde -status」や「Get-BitLockerVolume」コマンドレットを使用して、その出力結果をPowerShellで加工することも可能であることを、最後に付け加えておきます。実を言うと、こちらの方法のほうがもっと簡単かつ確実かもしれません。
画面7 Windows標準のBitLocker関連のコマンドラインツール「manage-bde.exe」と「Get-BitLockerVolume」コマンドレット
次回は今回少し触れた、もっと良い別のサンプルスクリプトを紹介します。そのサンプルスクリプトを利用すれば、回復パーティションやWinREの詳細情報をスクリプトで取得できるようになるはずです。
弊社製品「SSD-assistance」は、サーバー(Windows、Linux、クラウドなど)やWindows 10/11デスクトップの設定仕様書の作成を自動化するサービス/ツールです。この製品のWindows向け機能には、かつて山市某と名乗っていた頃に提供したテクニックが組み込まれいるとかいないとか。残念ながら、現状、BitLockerドライブ暗号化や回復パーティション、WinREに関する情報を収集する機能の存在は確認できませんでした(→「サーバー設定仕様書【基本設定】の出力サンプルを見る)。次の会議の際に、今回の情報取得を含む、いくつかのアイデアを組み込めないかどうか相談してみるつもりです。
※ 追記(2024/06/17)
WinREのバージョンは、マウント/マウント解除しなくても、以下の方法で取得できました。
C:¥> reagentc /info
Windows RE の場所: ¥¥?\GLOBALROOT¥device¥harddisk#¥partition#¥Recovery¥WindowsRE
C:¥> Dism /Get-ImageInfo /ImageFile:¥¥?¥GLOBALROOT¥・・・¥WindowsRE¥winre.wim /Index:1
2024年09月02日 | vol.39 VMゲストの初期設定に役立つスクリプト|ラボ環境 in オンプレを作る(7) |
---|---|
2024年08月29日 | デモ. VMテンプレートのオフラインパッチ(動画) |
2024年08月29日 | vol.38 Hyper-V VMの管理に役立つスクリプト|ラボ環境 in オンプレを作る(6) |
2024年08月26日 | vol.37 オンプレのVMをAzureラボ環境に持ち込む|ラボ環境 in オンプレを作る(5) |
2024年08月22日 | vol.36 Azure Backupでクラウドバックアップ|ラボ環境 in オンプレを作る(4) |
2024年08月20日 | ITニュース. WinREの更新失敗の既知の問題、本当に解消したの? |
2024年08月19日 | vol.35 ローカルバックアップは超簡単|ラボ環境 in オンプレを作る(3) |
2024年08月08日 | vol.34 Windows Admin Centerの導入|ラボ環境 in オンプレを作る(2) |
2024年08月06日 | お知らせ. 定期セミナー「セイテク・シス管道場」、第2回を9月10日に開催 |
2024年08月05日 | vol.33 ラボ環境 in オンプレを作る(新シリーズスタート) |