共用方式為


使用靜態驅動程式驗證器在 Windows 驅動程式中尋找瑕疵

靜態驅動程式驗證器 (SDV) 會使用一組介面規則和操作系統模型來判斷驅動程式是否與 Windows 作業系統正確互動。 SDV 會在驅動程式程式代碼中尋找可能指向驅動程式中潛在 Bug 的缺陷。

SDV 可以分析符合下列其中一個驅動程式模型的核心模式驅動程式:WDM、KMDF、NDIS 或 Storport。 如需詳細資訊,請參閱 支援的驅動程式判斷靜態驅動程序驗證器是否支援您的驅動程式或連結庫。 此外,SDV 為未遵循上述驅動程式模型的驅動程式提供有限的支援(嚴重限制的規則集著重於一般錯誤,例如 Null 取值)。

重要

不再支援 SDV,且 Windows 24H2 WDK 或 EWDK 版本無法使用 SDV。 它不適用於比組建 26017 還新的 WDK,而且不包含在 Windows 24H2 RTM WDK 中。 從下載 Windows 驅動程式套件 (WDK) 下載 Windows 11 版本 22H2 EWDK(2023 年 10 月 24 日發行)與 Visual Studio 組建工具 17.1.5,仍然可以使用 SDV。 建議只使用企業 WDK 來執行 SDV。 不建議使用舊版的標準 WDK 搭配最新版的 Visual Studio,因為這可能會導致分析失敗。
接下來,CodeQL 將是驅動程式的主要靜態分析工具。 CodeQL 提供功能強大的查詢語言,會將程式代碼視為要查詢的資料庫,讓您輕鬆地撰寫查詢特定行為、模式等等。 如需使用 CodeQL 的詳細資訊,請參閱 CodeQL 和靜態工具標誌測試

準備您的原始程式碼

使用下列步驟來準備程序代碼以供分析。

  1. 使用函式角色類型宣告驅動程式提供的函式

    SDV 需要使用函式角色類型宣告來宣告函式。 例如, DriverEntry 例程必須使用DRIVER_INITIALIZE函式角色類型來宣告:

    DRIVER_INITIALIZE DriverEntry;
    

    宣告之後,您會實作 (或定義) 回呼例程,如下所示:

    /
    // Driver initialization routine
    //
    NTSTATUS
      DriverEntry(
        _In_ struct _DRIVER_OBJECT  *DriverObject,
        _In_ PUNICODE_STRING  RegistryPath
        )
      {
          // Function body
      }
    

    每個支援的驅動程式模型都有一組驅動程式回呼函式和分派例程的函式角色類型。 這些函式角色類型會在 WDK 頭檔中宣告。 例如,以下是DRIVER_INITIALIZE角色類型的函式原型,如 Wdm.h 所示。

    /
    // Define driver initialization routine type.
    //
    _Function_class_(DRIVER_INITIALIZE)
    _IRQL_requires_same_
    typedef
    NTSTATUS
    DRIVER_INITIALIZE (
        _In_ struct _DRIVER_OBJECT *DriverObject,
        _In_ PUNICODE_STRING RegistryPath
        );
    
    typedef DRIVER_INITIALIZE *PDRIVER_INITIALIZE;
    

    由於函式角色類型已在 WDK 頭檔中定義,因此您只需要將回呼函式宣告為該類型。 在此情況下,您會宣告 DriverEntry 為類型 DRIVER_INITIALIZE。 如需驅動程式模型函式角色類型的完整清單,請參閱 使用函式角色類型宣告。

  2. 執行 C/C++的程式代碼分析

    為了協助您判斷原始程式碼是否已備妥,請在 Visual Studio 中執行程式 代碼分析工具 。 程式代碼分析工具會檢查 SDV 所需的函式角色類型宣告。 當函式定義的參數不符合函式角色類型的參數時,程式代碼分析工具可協助您識別可能遺漏或警告的任何函式宣告。

    • 在 Visual Studio 中開啟您的驅動程序專案。
    • 從 [ 建置] 功能表中,按兩下 [在方案上執行程序代碼分析]。

    結果會顯示在 [ 程序代碼分析] 視窗中。 修正您可能遺漏的任何函式宣告。 您也可以設定程式碼分析工具,以便在建置解決方案時執行。

    下表顯示程式代碼分析工具可能會在驅動程式程式代碼中找到的一些警告。 若要執行靜態驅動程序驗證器,您的驅動程式必須沒有這些瑕疵。

    C/C++ 警告的程式代碼分析 描述
    C28101 Drivers 模組推斷目前的函式是函 <式類型> 函式
    C28022 此函式上的函式類別 (es) 與用來定義它的 typedef 上的函式類別 (es) 不相符。
    C28023 指派或傳遞的函式應該至少有一個類別的 _Function_class_ annotation
    C28024 受指派的函式指標會以函式類別標注,該類別未包含在函式類別 (es) 清單中。
    C28169 分派函<>式函式沒有任何_Dispatch_type_註釋
    C28208 函式簽章與函式宣告不符

執行靜態驅動程式驗證器

  1. 在 Visual Studio 中開啟驅動程式專案 (.vcxProj) 檔案。 從 [驅動程式] 功能表中,按兩下 [啟動靜態驅動程序驗證程式...]。

    這會開啟靜態驅動程式驗證器應用程式,您可以在其中控制、設定及排程靜態驅動程式驗證器執行分析的時間。

  2. 如果您的驅動程式包含連結庫,請按兩下 [連結庫] 索引標籤,然後按兩下 [新增連結庫] 以新增連結庫。

    流覽至連結庫原始碼的目錄,然後選取項目檔 (.vcxProj)。 新增驅動程式包含的所有連結庫。 在 SDV 分析驅動程式之前,必須先新增連結庫。 當您開始分析驅動程式時,SDV 也會分析尚未處理的連結庫。 處理連結庫之後,它會儲存在全域 SDV 快取中。 如需詳細資訊,請參閱 靜態驅動程式驗證器中的連結庫處理

  3. 檢查靜態驅動程式驗證工具的組態設定。 按兩下 [設定] 索引標籤。

    項目組態 專案組態 會顯示您在Visual Studio中選取的組態和平台設定。

    資源 在大部分情況下,您可以使用預設設定。 如果 SDV 報告 Timeout、GiveUp 或 Spaceout,您可以嘗試調整這些設定。 如需詳細資訊,請參閱 針對靜態驅動程序驗證程序進行疑難解答的建議。

    排程 選取開始驗證的開始時間。 默認設定是在按兩下 [主要] 索引標籤上的 [開始] 之後立即開始分析。根據驅動程式的大小及其複雜性,靜態分析可能需要很長的時間才能執行。 您可能想要將分析排程在最方便您時開始;例如,在一天結束時。

    注意

    請務必檢查計算機的電源管理計劃,以確保計算機不會在分析期間進入睡眠狀態。

  4. 按兩下 [ 規則] 索引標籤,以選取當您開始分析時要驗證的驅動程式 API 使用規則。

    靜態驅動程式驗證器會偵測您要分析的驅動程式類型(WDF、WDM、NDIS 或 Storport),並選取驅動程式類型的默認規則集。 如果這是您第一次在驅動程式上執行 SDV,您應該執行預設規則集。

    如需規則的相關信息,請參閱 DDI 合規性規則

  5. 啟動靜態分析。 按兩下 [ 主要] 索引標籤 ,然後按兩下 [ 開始]。 當您按兩下 [開始] 時,會顯示一則訊息,讓您知道已排程靜態分析,而且分析可能需要很長的時間才能執行。 按一下 [確定] 繼續進行。 分析會從您排程的時間開始。

檢視和分析結果

隨著靜態分析的進行,SDV 會報告分析的狀態。 分析完成時,SDV 會報告結果和統計數據。 如果驅動程式無法滿足 API 使用規則,結果會回報為瑕疵。

如果遇到任何問題,SDV 會在 [警告 ] 和 [錯誤 ] 頁面上顯示這些問題。 [ 驅動程序屬性] 頁面會顯示特定驅動程式屬性的測試結果。 驅動程式屬性測試可用來識別驅動程式功能,以進一步限定分析。 您可以使用 驅動程式屬性 結果來確認驅動程式的預期屬性和支援的功能。

若要在 [靜態驅動程序驗證器報告] 中檢視特定瑕疵,請單擊 [結果] 窗格中的 [瑕疵]。 這會開啟 追蹤查看器,其會顯示規則違規程式代碼路徑的追蹤。 如需詳細資訊,請參閱 解譯靜態驅動程序驗證器結果

注意

靜態驅動程式驗證器會保留分析的結果和設定。 若要清除結果,請按兩下 [ 清除]。

針對靜態驅動程式驗證器結果進行疑難解答

如果 SDV 回報找不到瑕疵,請檢查 [主要 ] 索引標籤,以確保偵測到進入點。 如果驅動程式未使用函式角色類型宣告函式,SDV 將無法分析和尋找驅動程式程式代碼中的瑕疵。 如需詳細資訊,請參閱 使用函式角色類型宣告

如果 SDV 回報逾時或無法傳回有用的結果,您可能需要變更幾個 SDV 組態選項。 如需如何針對 SDV 進行疑難解答的詳細資訊,請參閱 針對靜態驅動程式驗證程式進行疑難解答的建議。

判斷靜態驅動程式驗證器是否支援您的驅動程式或連結庫

使用函式角色類型宣告

靜態驅動程式驗證器規則

程式代碼分析工具