コマンド&スクリプト強化週間(2024秋)の第3弾は、サーバーやPCのハードウェアのセキュリティ機能のサポート状況をチェックするスクリプトです。WebベースのWindows Server/クラスター/コンピューター管理ツールである「Windows Admin Center(WAC)」は、PowerShellスクリプトのサンプルの宝庫です。今回は、Windows Admin Centerの「セキュリティ」ツールの機能をちょっと拝借。
セキュアコアPC/セキュアコアサーバーとは
セキュアコアPC(Secure-Cored PC)」とは、Microsoftが2019年に初めて提唱した、高いセキュリティ機能を備えるWindows 10デバイスの要件を示すもので、OEMベンダーと協力してセキュアコアPC対応デバイスを提供しています。ユーザーは、セキュアコアPC対応デバイスを選択することで、ハードウェア構成に悩むことなく、電源投入直後からセキュリティで高度に保護されたシステムを導入することができます。セキュアコアPCのコンセプトは、その後、Windows 11はもちろんのこと、Windows Server 2022にも導入されています。
Windows 11 のセキュアコア PC(Microsoft Learn)
セキュア コア サーバー|Windows Server 2022 の新機能(Microsoft Learn)
物理、仮想、オンプレミス、クラウド問わず、あらゆる場所で稼働するWindows ServerおよびWindows 10/11用のリモート管理ツール「Windows Admin Center(WAC)」は、「セキュリティ」ツールの中にセキュアコア対応状況を表示する「Secured-core」タブが用意されており、管理対象のサーバーやWindows 10/11デバイスのハードウェアがセキュアコアサーバー、セキュアコアPCに対応しているかどうか、および機能が構成されているかどうかを確認することができます。
「セキュリティ」ツールのPowerShellスクリプトを表示すると([>_]をクリック)、これらの情報は、CheckVBS関数、CheckDGSecurityServicesRunning関数、CheckTpmVersion関数、checkSecureBoot関数、および$bootDMAProtectionCheck変数で取得しているのが分かります(画面1)。
画面1 WACの「セキュリティ」ツールが使用するPowerShellスクリプト
関数と変数を丸ごとコピペしてスクリプト化
関連する関数と変数部分をコピー&ペーストし、関数の返り値や変数の値を分かりやすい表現で出力するコードを追加すれば、セキュアコア対応状況の確認スクリプト(check-securecore.ps1)の完成です。このスクリプトがあれば、WACのインストールや管理対象への追加をしなくても、セキュアコアサーバー/セキュアコアPCの要求するセキュリティ機能の状態を確認することができます(画面2、画面3)。
画面2 Windows Server 2022を実行するサーバーのセキュアコアサーバー対応状況
画面3 Windows 11を実行するデバイスのセキュアコアサーバー対応状況
[check-securecore.ps1](青色のコードはWACから丸ごとコピーした部分)
<#
Check whether VBS is enabled and running
0. VBS is not enabled.
1. VBS is enabled but not running.
2. VBS is enabled and running.
#>
function CheckVBS {
return (Get-CimInstance -classname Win32_DeviceGuard -namespace root\Microsoft\Windows\DeviceGuard).VirtualizationBasedSecurityStatus
}
<#
# device guard checked used for hcvi and system guard
0. No services running.
1. If present, Windows Defender Credential Guard is running.
2. If present, HVCI is running.
3. If present, System Guard Secure Launch is running.
4. If present, SMM Firmware Measurement is running.
#>
function CheckDGSecurityServicesRunning($_val) {
$DGObj = Get-CimInstance -classname Win32_DeviceGuard -namespace root\Microsoft\Windows\DeviceGuard
# loop to avoid out of index out of bounds errors
for ($i = 0; $i -lt $DGObj.SecurityServicesRunning.length; $i++) {
if ($DGObj.SecurityServicesRunning[$i] -eq $_val) {
return $true
}
}
return $false
}
# tpm version check
function CheckTpmVersion {
$TpmObj = Get-CimInstance -classname Win32_Tpm -namespace root\cimv2\Security\MicrosoftTpm
if ($null -ne $TpmObj) {
return $TpmObj.SpecVersion[0] -eq "2"
}
return $false
}
function checkSecureBoot {
if ((Get-Command Confirm-SecureBootUEFI -ErrorAction SilentlyContinue) -ne $null) {
<#
For devices that Standard hardware security is not supported, this means that the device does not meet
at least one of the requirements of standard hardware security.
This causes the Confirm-SecureBootUEFI command to fail with the error:
Cmdlet not supported on this platform: 0xC0000002
#>
try {
return Confirm-SecureBootUEFI
}
catch {
return $false
}
}
return $false
}
$bootDMAProtectionCheck =
@"
namespace SystemInfo
{
using System;
using System.Runtime.InteropServices;
public static class NativeMethods
{
internal enum SYSTEM_DMA_GUARD_POLICY_INFORMATION : int
{
/// </summary>
SystemDmaGuardPolicyInformation = 202
}
[DllImport("ntdll.dll")]
internal static extern Int32 NtQuerySystemInformation(
SYSTEM_DMA_GUARD_POLICY_INFORMATION SystemDmaGuardPolicyInformation,
IntPtr SystemInformation,
Int32 SystemInformationLength,
out Int32 ReturnLength);
public static byte BootDmaCheck() {
Int32 result;
Int32 SystemInformationLength = 1;
IntPtr SystemInformation = Marshal.AllocHGlobal(SystemInformationLength);
Int32 ReturnLength;
result = NativeMethods.NtQuerySystemInformation(
NativeMethods.SYSTEM_DMA_GUARD_POLICY_INFORMATION.SystemDmaGuardPolicyInformation,
SystemInformation,
SystemInformationLength,
out ReturnLength);
if (result == 0) {
byte info = Marshal.ReadByte(SystemInformation, 0);
return info;
}
return 0;
}
}
}
"@
Add-Type -TypeDefinition $bootDMAProtectionCheck
##この上はWindows Admin Centerからのコピペ##
switch (CheckVBS) {
0 { Write-Host "VBS: Disabled" }
1 { Write-Host "VBS: ON (not running)" }
2 { Write-Host "VBS: ON" }
}
$osBuildNumber = [int](Get-CimInstance Win32_OperatingSystem).BuildNumber
$osVersion22H2 = 20349;
if ($osBuildNumber -le $osVersion22H2) {
if (CheckDGSecurityServicesRunning(3) ) {
Write-Host "HVCI: ON (System Guard Secure Launch)"
} else {
Write-Host "HVCI: OFF"
}
} else {
if (CheckDGSecurityServicesRunning(2) ) {
Write-Host "HVCI: ON"
} else {
Write-Host "HVCI: OFF)"
}
}
if (CheckTpmVersion -eq 2){
Write-Host "TPM 2.0: ON"
} else {
Write-Host "TPM 2.0: Not Supported"
}
if (CheckSecureBoot) {
Write-Host "SECUREBOOT: ON"
} else {
Write-Host "SECUREBOOT: OFF"
}
if ([SystemInfo.NativeMethods]::BootDmaCheck() -ne 0) {
Write-Host "bootDMAProtection: ON"
} else {
Write-Host "bootDMAProtection: Not Supported"
}