共用方式為


核心位址清理工具 (KASAN)

核心位址清理程式 (KASAN) 是 Windows 核心驅動程式上支援的 Bug 偵測技術,可讓您偵測數個不合法的記憶體存取類別,例如緩衝區溢位和無用事件。 它要求您在系統上啟用 KASAN,並使用特定的 MSVC 編譯程式旗標重新編譯核心驅動程式。

Pre-requisites

若要使用 KASAN,您需要:

  • 將載入核心驅動程式的目標系統的 OS 版本:
    • 用戶端:Windows 11 24H2 或更新版本。
    • 伺服器:Windows Server 2025 或更新版本。
  • VisualStudio:17.11 版或更新版本。
  • WDK:10.0.26100.2161 版或更新版本。

只有在 x64 上才支援 KASAN。

如何在核心驅動程式上啟用 KASAN

  1. 在目標系統的系統管理員命令 提示字元 視窗中輸入下列命令列:

    reg add "HKLM\System\CurrentControlSet\Control\Session Manager\Kernel" /v KasanEnabled /t REG_DWORD /d 1
    

    設定此登錄機碼會指示 Windows 核心準備並接受載入 KASAN 檢測的驅動程式。 未設定此登錄機碼會導致 Windows 核心拒絕載入 KASAN 檢測驅動程式。

  2. 重新啟動目標系統,變更才會生效。

  3. 將新的旗標傳遞至 MSVC 編譯程式,以啟用 KASAN 檢測來重新編譯核心驅動程式。 請使用下列其中一個方法:

    • GUI:在 VisualStudio 中,流覽至 [方案總管],以滑鼠右鍵按一下核心驅動程式專案,然後選取 [屬性]。 在屬性頁面中,流覽至 [組態屬性>>C/C++>>General],並將 [啟用核心位址清理器 ] 設定為 [是]。 然後重建您的解決方案。
    • 命令提示字元:將 /fsanitize=kernel-address 參數新增至編譯器命令列。 然後,重建您的解決方案。
  4. 在目標系統上載入您重新編譯的核心驅動程式,並像平常一樣對它進行壓力測試。 KASAN 會在運行時間運作,並透過 錯誤檢查0x1F2報告不合法的記憶體存取事件:KASAN_ILLEGAL_ACCESS

VisualStudio 17.12 中的回歸

如果您使用 VisualStudio 17.12,可能會遇到下列建置錯誤:

error LNK2019: unresolved external symbol __asan_wrap_wcscat referenced in function

您可以將下列旗標新增至連結器命令列,以解決此問題:

/alternatename:__asan_wrap_wcscat=wcscat

此迴歸已在 VisualStudio 17.14.15 中修正。

VisualStudio 17.14 至 17.14.14 中的迴歸

如果您使用 VisualStudio 17.14,可能會遇到下列建置錯誤:

error LNK2001: unresolved external symbol __LINK_WITH_asan_compat.lib_TO_USE_NEW_COMPILER_WITH_OLDER_ASAN_RUNTIME

您可以將下列旗標新增至編譯程式命令列,以解決此問題:

/fno-sanitize-address-asan-compat-lib

在連結器命令列中添加以下標誌:

/alternatename:__asan_wrap_wcscat=wcscat
/alternatename:__asan_wrap_wcscpy=wcscpy
/alternatename:__asan_wrap_wcsncpy=wcsncpy

此迴歸已在 VisualStudio 17.14.15 中修正。

如何確認核心驅動程式上已啟用 KASAN

使用 KASAN 編譯的核心驅動程式具有名為 「KASAN的 PE 區段。 在開發人員命令提示字元中執行下列命令,確認您的驅動程式已啟用 KASAN:

dumpbin /ALL YourDriver.sys

如果輸出包含名為 「KASAN的區段,則會在驅動程式上啟用 KASAN。

如何分析 KASAN 報告

當 KASAN 偵測到驅動程式中的非法記憶體存取時,它會發出 錯誤檢查0x1F2:KASAN_ILLEGAL_ACCESS。 檢查產生的核心記憶體轉儲,以判斷驅動程式執行非法記憶體存取的位置。

使用 KASAN 搭配連結至目標系統的核心調試程式,以便在發出錯誤檢查時動態檢查記憶體,而不是使用記憶體轉儲進行驗屍。

錯誤檢查參數

錯誤檢查0x1F2的參數 :KASAN_ILLEGAL_ACCESS 為:

  1. 參數 1:非法存取的位址。
  2. 參數 2:記憶體存取的大小。
  3. 參數 3:執行非法記憶體存取的呼叫端位址。
  4. 參數 4:記憶體存取的額外資訊:
    • 位 [0:7]:KASAN 陰影程序代碼。 請參閱下表。
    • 位 8: 1 如果存取是寫入, 0 則為讀取。

KASAN 陰影代碼

在 KASAN 中,我們認為所有核心記憶體都被劃分為 8 位元組對齊的 8 位元組 儲存格的連續區塊。 使用 KASAN,核心記憶體中的每個 8 位元組單元都有一個與之關聯的 影子代碼 ,這是一個表示單元有效性的單位元組整數。 陰影代碼的編碼方式如下:

Value Meaning
0x00 單元格完全有效:存取單元格的所有八個字節都是合法的。
0x01 ->0x07 儲存格部分有效:儲存格中的第一個 位元組有效,但其餘值無效。
0x08 ->0x7F 數據格有條件地有效:根據特定條件,對單元格所有八個字節的存取可能是合法或非法的。
>= 0x80 單元格完全無效:存取儲存格的所有八個字節都是非法的。

條件有效和完全無效的儲存格使用數個子代碼,進一步指出儲存格所關聯的記憶體類型,以及存取它可能是非法的原因。

條件式有效儲存格所使用的子代碼:

  • 0x09:可分頁記憶體,在 DISPATCH_LEVEL 或以上時存取是非法的,但以其他方式存取是合法的。

完全無效儲存格所使用的子代碼:

  • 0x81:alloca 的左紅分區。
  • 0x82:alloca 的中間紅區。
  • 0x83:alloca 的右紅區域。
  • 0x84:全域變數的右紅色區域。
  • 0x85:泛型 redzone。
  • 0x86:集區內存的右紅區域。
  • 0x87:釋放集區內存。
  • 0x8A:連續記憶體的左紅區域。
  • 0x8B:連續記憶體的右紅色區域。
  • 0x8C:釋放 lookasidelist 記憶體。
  • 0x8D:集區內存的左紅區域。
  • 0xF1:堆疊變數的左紅區域。
  • 0xF2:堆疊變數的中間紅色區域。
  • 0xF3:堆疊變數的右紅色區域。
  • 0xF5:used-after-ret 堆棧變數。
  • 0xF8:範圍外堆棧變數。

瞭解 KASAN 錯誤檢查:範例

假設 KASAN 在驅動程式執行時發出錯誤檢查,並具有下列參數:

  1. 參數 1: 0xFFFFFFFFFFFFABCD
  2. 參數 2: 0x0000000000000004
  3. 參數 3: 0xFFFFFFFF12345678
  4. 參數 4: 0x0000000000000184

參數 1 告訴您您的驅動程式嘗試存取位址 0xFFFFFFFFFFFFABCD ,而且此存取是非法的。 參數 2 告訴您這是四位元組存取。 參數 3 會提供驅動程式執行非法存取的指令指標位址。 參數 4 告訴您這是寫入權限,且被觸及的記憶體是全域變數的右邊界紅區域。

換句話說,您的驅動程式可能嘗試在全域變數上執行寫入緩衝區溢位。 使用這項資訊來調查及判斷驅動程式中修正此錯誤的位置和方式。

KASAN 的效能影響

KASAN 會增加核心記憶體耗用量,並在啟用 KASAN 編譯的驅動程式中引入大約兩倍的速度變慢。

與驅動程式驗證器比較

KASAN 和驅動程式驗證器是完全獨立的功能,但相互相容。

KASAN 著重於偵測不合法的記憶體存取,而且比該網域中的驅動程序驗證器更有效率,因為它使用更精細的方法並涵蓋更多的記憶體區域。 驅動程式驗證器有驅動程式特定的規則,旨在尋找其他類型的 Bug,KASAN 不會偵測到。 如需詳細資訊,請參閱 Microsoft:Microsoft 平臺上的核心清理工具簡介。

搭配驅動程式驗證器使用 KASAN,將驅動程式中的 Bug 偵測最大化。

Resources