HN 日本語サマリー

← 一覧へ戻る
プログラミング

WindowsドライバーテストとファジングのためのステートレスハーネスとしてのWinPE

WinPE as a stateless harness for Windows driver testing and fuzzing (bednars.me)

77 pointsby piotrbednarsalt5 コメント

要約

この記事では、Windowsシステム向けのCI/CD環境のオーケストレーションと、カーネルモードドライバーの動的なファジングおよび例外キャプチャという2つの低レベル自動化のエンジニアリング課題を分析しています。これらの課題は、従来のフルWindowsランナーが抱えるリソース過多、決定論の欠如、遅いフィードバックループといった問題に起因します。解決策として、Windows PE (Windows Preinstallation Environment) をステートレスで高速なテストハーネスとして活用する方法を提案しています。

全文翻訳

最近、低レベル自動化の分野で2つの特定のエンジニアリング問題を分析しました。最初の問題は、Windowsシステム向けのCI/CD環境のオーケストレーションであり、エンドツーエンド(E2E)テストのための再現可能で決定論的な条件を作成することが非常に高価で非効率的であることです。カーネルモードドライバーフレームワーク(KMDF)カーネルドライバーのリポジトリを管理していると仮定しましょう。完全に自動化されたE2Eテストをどのように展開しますか?フルWindowsランナーに基づいた従来ののアプローチは、膨大なリソースの負担となります。環境は決定論的でなく、冪等性が欠如しており、ゼロからの起動時間(いわゆるコールドスタート)はパイプラインのフィードバックループを劇的に延長します。2番目の問題は、ソフトウェアライフサイクルの異なる段階に関わる双子の問題ですが、KMDFドライバーの動的なファジングとカーネル例外(バグチェック/BSOD)の即時キャプチャに関するものです。ここでは、メモリオーバーヘッド、スナップショットからのマシン状態の復元の遅さ、オペレーティングシステムの予測可能性の欠如といった同様の障壁があります。これら両方の問題は同じ根本原因から生じます。標準的なWindowsインストールは、グラフィカルコンポーネント、バックグラウンドサービス、テレメトリからかなりのリソースオーバーヘッドを伴います。自動テストでは、このユーザーモードレイヤーは不要です。ミニマリストな環境でNTカーネルを実行するだけで十分です。解決策はWindows PE(Windows Preinstallation Environment)です。これは、すべてのWindows ISOイメージに配布されている公式の、削減された環境です。RAM全体で実行され、最小512MBのメモリを必要とし、DirectX、PowerShellサブシステム、または標準のグラフィカルシェル(Explorer)のサポートがありません。デフォルトでNT AUTHORITY\SYSTEM権限で起動するため、これら両方のタスクにとって理想的なテストハーネスとなります。以下の分析は、WinPEの低レベルメカニズム、およびこのシステムを超高速で冪等なテスト環境に変えることを可能にするBCDとQEMUの変更に焦点を当てています。 偵察とブート構成の自動化 WinPE環境はWIM(Windows Image)ファイルから起動し、ブートローダーは仮想ドライブ文字X:の下にRAMディスクとしてマウントします。プロセス全体はBCD(Boot Configuration Data)ストアによって制御されます。仮想マシンがミリ秒単位で起動するようにするには、bcdeditツールを使用して積極的なブート最適化を展開する必要があります。 bcdedit /set {default} bootstatuspolicy ignoreallfailures bcdedit /set {default} recoveryenabled no bcdedit /set {bootmgr} timeout 0 ignoreallfailures – CI/CDシステムにとって重要なフラグです。不正なシャットダウンエラーを無視し、ブロッキングウェルカム画面の表示を防ぎます。 recoveryenabled no – ディスクレス環境ではクラッシュループに終わる自動システム修復の試みを完全に遮断します。 デジタル署名されていないKMDFドライバーをテストする場合、テストモードの有効化が主な要件です。多くのレガシーガイドでは nointegritychecks yes を推奨していますが、このフラグはWindows Vista/7以降 x64 ブートローダーでは無視されています。代わりに、仮想化ベースのセキュリティ(VBS)とHypervisor-Protected Code Integrity(HVCI)を無効にする主なレバーは hypervisorlaunchtype off です。これらのカーネルレベルの保護を無効にするには: bcdedit /set {default} testsigning yes bcdedit /set {default} hypervisorlaunchtype off bcdedit /set {default} isolatedcontext no ここで、testsigning yes は署名されていないドライバーのロードを許可し、hypervisorlaunchtype off はハイパーバイザーレベルでVBS/HVCIを無効にし、isolatedcontext no は分離ユーザーモードコンテキスト(Credential GuardやIsolated User Modeなど)を無効にします。これらを組み合わせることで、ハイパーバイザーが検証されていないコードをブロックするのを防ぎ、ファジング中にカーネル構造を直接操作できるようになります。 QEMUでのハードウェアトポロジアーキテクチャ カーネルデバッグの安定性のための環境のエミュレーションには、チップセットの正確な選択が必要です。QEMUで仮想化する場合、デフォルトの最新のq35プロファイルはPCIe(PCI Express)バスとその完全で複雑なトポロジ(Root Complex、root ports)を実装しています。WinPEに存在する簡略化された組み込みネットワークドライバーの場合、PCIeツリーをナビゲートするのは問題になる可能性があります。古いpc(i440FX)マシンプロファイルは、フラットでクラシックなPCIバス(バス0)を提供し、はるかに予測可能です。ここではデバイスのアドレス指定は単純で、HAL(Hardware Abstraction Layer)レベルでのリソース割り当てエラーを排除します。 # Recommended, stable base QEMU configuration for Windows (WHPX) # with a specific CPU model selected instead of 'host' (WHPX has issues with 'host') # and Hyper-V enlightenments removed by default, so they do not break KDNET: qemu-system-x86_64.exe -M pc -accel whpx -cpu Skylake-Client-IBRS -m 1024 -vga none -nographic ... KDNETを介したネットワークデバッグ KDNETメカニズムは、UDPプロトコルを介したカーネルデバッグを可能にします。これはシステムネットワークスタック(NDIS)とは完全に独立して動作し、ハードウェアコントローラーレベルで直接機能します。ミニマリスト環境では、KDNETはネットワークカードをスキャンするためにバスを普遍的にクエリしません。バスパラメータを使用してハードウェアマッピングを強制する必要があります。これは、Bus.Device.Function形式で正確な座標を提供します。 bcdedit /dbgsettings net hostip:10.0.2.2 port:50000 key:1.2.3.4 bcdedit /set {dbgsettings} busparams 0.16.0 QEMUでネットワークカードを -device e1000,bus=pci.0,addr=0x10 というコマンドで設定する場合、アドレス0x10(16進数)は10進数で16に相当します。したがって、busparams=0.16.0 パラメータが使用されます。 重要: KDNETには、ネイティブにサポートされているアダプターのハードコードされた、非常に限定的なハードウェア識別子(ベンダーID/デバイスID)のリストがあります。クラシックなIntel PRO/1000エミュレーション(-device e1000)は自動的に初期化されます。適切なブートモジュールをboot.wimに注入せずに、より新しいe1000eまたはパラバーチャル化インターフェイス(virtio-net)に切り替えようとすると失敗します。 絶対的な決定論とシェル変更 WinPEは絶対的な冪等性を保証します。システムはメモリにロードされたクリーンなWIMイメージから起動し、あらゆる変更は一時的な状態として表現されます。永続的なアーキテクチャ変更には、DISMツールを使用したオフライン編集が必要です。 dism /Mount-Image /ImageFile:C:\winpe\boot.wim /Index:1 /MountDir:C:\winpe\mount # [File / registry modification] dism /Unmount-Image /MountDir:C:\winpe\mount /Commit BCDストアとシステムイメージ自体は、メディア(例: ISOファイル)上の2つの別個のエンティティであることを覚えておいてください。BCDは \boot\bcd フォルダにあり(bcdedit /store でオフラインで変更)、ファイルシステムは DISM ツールで \sources\boot.wim ファイルをマウントすることによって変更されます。初期化速度を最大化し、ブート時間のオーバーヘッドを排除するために、スタートアップスクリプトを解析しDHCPクエリを設定する標準のwpeinit.exeプロセスをバイパスまたはカスタマイズする必要があります。NDISネットワーク初期化を無効にすることは、windowsPEパス中に処理される適切なunattend.xmlプロファイルを注入することによって達成されます。 <?xml version="1.0" encoding="utf-8"?> <unattend xmlns="urn:schemas-microsoft-com:unattend"> <settings pass="windowsPE"> <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> <EnableNetwork>false</EnableNetwork> </component> </settings> </unattend> これにより、オペレーティングシステムはIPネゴシエーションをスキップし、KDNET機能(NDISスタックより下で動作することが確立されている)を維持しながら、ブート時間を最小限に抑えます。不要な抽象化レイヤーを排除する最もエレガントなアプローチは、システムシェルの完全な置き換えです。シェル設定ファイルX:\Windows\System32\winpeshl.iniを作成することにより、セッションマネージャーにcmd.exeインタープリターを無視させ、直接テストエージェントバイナリを実行するように指示します。 [LaunchApps] %SYSTEMROOT%\System32\test_agent.exe, "--param1" 自動化の目的で非常に重要なのは、WinPEログオンサブシステムのアーキテクチャは、winpeshl.iniでメインシェルとして定義されたプロセスを終了すると、仮想マシンの即時再起動が自動的にトリガーされるように設計されていることです。