メモリの整合性と VBS とのドライバーの互換性
メモリの整合性は、Windows 10、Windows 11、Windows Server 2016 以降で使用できる仮想化ベースのセキュリティ (VBS) 機能です。 メモリの整合性と VBS により、Windows の脅威モデルが改善され、Windows カーネルを悪用しようとするマルウェアに対してより強力な保護が提供されます。 VBS は Windows ハイパーバイザーを使用して、カーネルが侵害される可能性があることを前提とする OS の信頼のルートとなる分離された仮想環境を作成します。 メモリの整合性は、VBS の分離された仮想環境内でカーネル モード コードの整合性を実行することで、Windows を保護および強化する重要なコンポーネントです。 メモリの整合性により、システムの侵害に使用できるカーネル メモリ割り当ても制限され、セキュリティで保護されたランタイム環境内でコード整合性チェックを渡した後にのみカーネル メモリ ページが実行可能にされ、実行可能ページ自体が書き込み可能にならないようにします。
Note
メモリの整合性は、 ハイパーバイザーで保護されたコード整合性 (HVCI) または ハイパーバイザーによって適用されるコード整合性と呼ばれる場合があり、最初は Device Guard の一部としてリリースされました。 Device Guard は、グループ ポリシーまたは Windows レジストリでメモリの整合性と VBS 設定を見つける以外に使用されなくなりました。
メモリ整合性は、「メモリ整合性の有効化」で説明されているように、S モードでWindows 10をインストールし、互換性のあるハードウェアにWindows 11クリーン既定で有効になります。 メモリ整合性の自動有効化要件を満たしていない他のシステムでは、お客様は、 メモリの整合性を有効にする方法に関するページで説明されている方法のいずれかを使用してオプトインできます。
アプリケーションの互換性
メモリ整合性との互換性は、Windows 10 Anniversary Update (1607) 以降のすべてのドライバーの要件でしたが、一部のアプリケーションとハードウェア デバイス ドライバーには互換性がない場合があります。 この非互換性により、デバイスまたはソフトウェアが誤動作する可能性があり、まれに起動エラー (ブルー スクリーン) が発生する可能性があります。 このような問題は、メモリ整合性保護が有効になった後、または有効化プロセス自体の間に発生する可能性があります。 アプリケーション開発者で、ドライバーとソフトウェア パッケージがメモリ整合性と互換性があることを検証する場合は、次の手順に従います。
メモリの整合性に関する非互換性を確認した例を次に示します。
- ゲームでのチート対策ソリューション
- サードパーティの入力方式
- サードパーティの銀行パスワード保護
影響を受けるエクスペリエンスを軽減するために懸命に取り組んだので、ブート クリティカルなドライバーに非互換性が存在する場合、メモリ整合性保護が自動有効になっていた場合、メモリ整合性保護は自動的にオフになります。 他のアプリと互換性がない場合は、メモリ整合性保護をオフにする前に、特定のアプリとバージョンの更新プログラムをチェックすることをお勧めします。
互換性のあるドライバーを構築する方法
メモリのページとセクションは書き込み可能にも実行可能にもできないため、最初の手順は、データとコードを明確に分離し、コードのページを直接変更しないようにすることです。
- 既定で NX にオプトインする
- メモリ割り当て-NonPagedPoolNxに NX APIs とフラグを使用する
- 書き込み可能かつ実行可能なセクションを使用しないでください
- 実行可能プログラムのシステム メモリを直接変更しないでください
- カーネルでは動的コードを使用しないでください
- データ ファイルを実行可能ファイルとして読み込まないでください
- セクションのアラインメントは、0x1000 (PAGE_SIZE) の倍数である必要があります。 E.g. DRIVER_ALIGNMENT=0x1000
既定の設定を使用する場合は、最新バージョンのWDKおよびVisual Studioを使用して互換性のあるドライバーを生成します。
ドライバーとメモリの整合性との互換性を確認する方法
ドライバーの互換性を確認するには、次の 3 つの手順があります。
- コード整合性互換性チェックを有効にした状態でドライバー検証ツール (下記のセクションを参照) を使用します。
- メモリ整合性が有効になっているシステムでドライバーをテストします。
- Windows HLK でハイパーバイザー コード整合性準備テストを実行します。
ドライバーの検証ツールによる互換性チェック
ドライバー検証ツールには、コード整合性オプション フラグ (0x02000000) があり、メモリ整合性への準拠を検証する追加のチェックを有効にします。 これをコマンド ラインから有効にするには、次のコマンドを使用します。
verifier.exe /flags 0x02000000 /driver <driver.sys>
検証ツールの GUI を使用している場合にこのオプションを選択するには、[カスタム設定の作成 (コード開発者用)] を選択し、[次へ] を選択してから、[コード整合性チェック] を選択します。
成功した場合、出力はありません。 エラー出力の例を次に示します。
Driver Verifier: Enabled for DvCi.sys, flags 0x2000000, build 16299, key o4Dbg8OVJqaBYlqWQ2QvRH
\*\*\*\*\*\*\*\*\*\*\* Verifier Detected a Code Integrity Issue \*\*\*\*\*\*\*\*\*\*\*\*
\*\* The caller 0xFFFFF8094B9852F0 specified an executable page protection 0x40.
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\*\* Verifier assertion failed \*\*\*
(B)reak, (I)gnore, (W)arn only, (R)emove assert? B
メモリ整合性が有効になっているドライバーをテストする
Windows ではほとんどのシステムで既定でメモリの整合性がオンになりますが、その原因としていくつかの理由が考えられます。 メモリの整合性を有効にするには、「メモリの整合性 を有効にする方法」を参照してください。 次に、ドライバーの機能をテストします。 ドライバーでメモリ整合性と互換性のない操作が実行時に実行されないようにするには、ドライバー内のすべてのコード パスを必ず実行してください。
HLK テスト (デスクトップとサーバー)
ドライバーが Microsoft の署名を承認するには、 HLK テスト HyperVisor コード整合性準備テスト に合格する必要があります。 デスクトップエディションとサーバーエディションの両方にメモリ整合性互換ドライバーが必要です。 HLK テストは、メモリ整合性と互換性のあるドライバーが OS によって正しく読み込まれ、実行されていることを確認するために記述された基本的なテストです。
ドライバーの Microsoft 署名には HLK テストに合格するだけで十分ですが、メモリ整合性を有効にした完全な機能テストを強くお勧めします。 たとえば、NX 保護に違反するメモリ割り当てが正しくコーディングされていないため、テストでキャッチされないエラーが発生する可能性があります。 ドライバーの作成者は、メモリの整合性を有効にしたまま、ドライバーを徹底的にテストする必要があります。
ドライバーの開発中と HLK テスト中に、ドライバーの読み込みを妨げる可能性があるため、メモリの整合性を無効にする必要がある場合があります。
HLK Hypervisor Code Integrity Readiness Test は、Windows Server Assurance AQ の一部として必要です。また、他の HLK テスト中にドライバー検証ツールを有効にしながら、コード整合性チェックを有効にするフラグも設定されます。
FAQ
既存のドライバーについてはどうしますか? Windows 10 で動作するようにするには、これらのドライバーを再構築する必要がありますか?
一概には言えません。 多くのドライバーは、既に互換性があります。 以前のバージョンの WDK および Visual Studio で標準設定を使用している場合、既知の問題は、INIT セクションが RWX としてマークされることです。 ただし、Windows 10 では W が自動的に削除されるため、これが唯一の問題である場合、ドライバーには互換性があります。
操作方法メモリの整合性が有効になっていることを確認しますか?
最も簡単な方法は、システム情報アプリ (msinfo32) を実行することです。 "仮想化ベースのセキュリティ サービスの実行中" という行を探します。 「Hypervisor enforced Code Integrity (ハイパーバイザーがコード整合性を強制)」と報告されているはずです。 管理ツールを使用して確認するための WMI インターフェイスもあります。「 有効な VBS とメモリの整合性機能を検証する」を参照してください。
メモリの整合性は、Windows セキュリティ アプリの [設定] [Update Security]\(セキュリティの更新&\)Windows セキュリティDevice security>Core の分離の>詳細 >[メモリの整合性] で確認することもできます。>> 詳細については、KB4096339を参照してください。
ドライバーの動作を変更するために、カーネルからプログラムでメモリの整合性が有効になっていることを確認できますか?
はい、NtQuerySystemInformation を使用できます: https://msdn.microsoft.com/library/windows/desktop/ms724509(v=vs.85).aspx
SYSTEM_CODEINTEGRITY_INFORMATION構造体には、メモリの整合性がオンになっていることを示す0x400値が公開されています。
互換性の問題の操作方法とは?
上で説明したように、W + X ページがないことと、ドライバーセクションが正しく調整されていることを二重確認するだけでなく、最も可能性の高い問題は不適切なメモリ割り当てです。 発行されたメモリ割り当てに関連する Code Analysis の警告については、MSDN の次のページを参照してください:
次の MSDN リンクは、実行可能メモリの割り当てを引き起こす一般的に使用される API の例と修正例をいくつか示しています:
次の表を使用して出力を解釈し、さまざまな種類の HVCI 非互換性を解決するために必要なドライバーコードの変更を決定します。
警告 | 解像度 |
---|---|
プールの種類の実行 | 呼び出し元は、実行可能なプールの種類を指定しました。 実行可能メモリを要求するメモリ割り当て関数の呼び出し。 すべてのプールの種類に実行可能でない NX フラグが含まれていることを確認してください。 |
ページ保護の実行 | 呼び出し元は、実行可能ページの保護を指定しました。 "No execute" ページ保護マスクを指定します。 |
ページマッピングの実行 | 呼び出し元は、実行可能なメモリ記述子リスト (MDL) マッピングを指定しました。 使用するマスクに MdlMappingNoExecute が含まれていることを確認します。 詳細については、「 MmGetSystemAddressForMdlSafe 」を参照してください |
Execute-Write セクション | イメージには、実行可能ファイルと書き込み可能セクションが含まれています。 |
セクションのアラインメントエラー | このイメージには、ページがアラインされていないセクションが含まれています。 セクションのアラインメントは、0x1000 (PAGE_SIZE) の倍数である必要があります。 E.g. DRIVER_ALIGNMENT=0x1000 |
サポートされていない Relocs を含んでいます | Windows 10 バージョン1507からバージョン1607では、アドレス空間レイアウトのランダム化 (ASLR) が使用されているため、アドレスの配置とメモリの再配置で問題が発生する可能性があります。 オペレーティングシステムは、リンカーによって既定のベースアドレスが ASLR に割り当てられた実際の場所に設定されている場所からアドレスを再配置する必要があります。 この再配置では、ページの境界をまたがることはできません。 たとえば、ページのオフセット0x3FFC で始まる64ビットアドレス値を考えてみます。 このアドレス値は、オフセット0x0003 の次のページに重なっています。 Windows 10 バージョン1703より前では、この種類の重複する relocs 含んはサポートされていません。
このような状況は、グローバル構造体型の変数初期化子が、及ぶ再配置を避けるために変数を移動できないようにレイアウトされた別のグローバルへのポインターが不整合になっている場合に発生する可能性があります。 リンカーは変数を移動しようとしますが、それができない場合もあります。たとえば、大規模なミスアライメントの構造体や、ミスアライメントされた構造体の大きな配列などです。 該当する場合は、/Gy (COMDAT) オプションを使用してモジュールをアセンブリし、リンカーがモジュール コードを可能な限りアラインできるようにする必要があります。 #include <pshpack1.h> typedef struct _BAD_STRUCT { USHORT Value; CONST CHAR *String; } BAD_STRUCT, * PBAD_STRUCT; #include <poppack.h> #define BAD_INITIALIZER0 { 0, "BAD_STRING" }, #define BAD_INITIALIZER1 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 \ BAD_INITIALIZER0 #define BAD_INITIALIZER2 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 \ BAD_INITIALIZER1 #define BAD_INITIALIZER3 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 \ BAD_INITIALIZER2 #define BAD_INITIALIZER4 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 \ BAD_INITIALIZER3 BAD_STRUCT MayHaveStraddleRelocations[4096] = { // as a global variable BAD_INITIALIZER4 }; ほかにも、この問題が発生する可能性がある、アセンブラー コードの使用が関係する状況があります。 |
実行可能なセクションの IAT | インポートアドレステーブル (IAT) は、メモリの実行可能なセクションである必要はありません。
この問題は、IAT がメモリの読み取りおよび実行 (RX) のみのセクションにある場合に発生します。 これは、参照されている DLL の正しいアドレスを設定するために、OS が IAT に書き込むことができないことを意味します。 この問題を発生させる方法の1つとして、コードリンクで /MERGE (セクションの結合) オプションを使用する方法があります。 たとえば、.rdata (読み取り専用で初期化されたデータ) をテキストデータ (実行可能コード) にマージすると、IAT がメモリの実行可能なセクションに存在する可能性があります。 |
影響を受ける可能性がある APIとは?
システムで使用するために予約されていない次の API の一覧は、影響を受ける可能性があります: