共用方式為


處理 UMDF 驅動程式中的用戶端模擬

本主題描述從 UMDF 第 2 版開始,User-Mode Driver Framework (UMDF) 驅動程式如何存取受保護的資源。

UMDF 驅動程式通常會在 LocalService 帳戶下執行,而且無法存取需要使用者認證的檔案或資源,例如受保護的檔案或其他受保護的資源。 UMDF 驅動程式通常會在用戶端應用程式與裝置之間流動的命令和資料上運作。 因此,大部分的 UMDF 驅動程式都不會存取受保護的資源。

不過,某些驅動程式可能需要存取受保護的資源。 例如,UMDF 驅動程式可能會從用戶端應用程式提供的檔案將韌體載入裝置。 檔案可能有存取控制清單 (ACL) ,以防止未經授權的使用者修改檔案並控制裝置。 不幸的是,此 ACL 也會防止 UMDF 驅動程式存取檔案。

架構提供模擬功能,可讓驅動程式模擬驅動程式的用戶端,並取得用戶端對受保護資源的存取權限。

啟用模擬

UMDF 驅動程式的安裝套件和用戶端應用程式都必須啟用架構的模擬功能,如下所示:

  • UMDF 驅動程式安裝套件的 INF 檔案必須包含 UmdfImpersonationLevel 指示詞,並設定允許的最大模擬層級。 只有在 INF 檔案包含 UmdfImpersonationLevel 指示詞時,才會啟用模擬。 如需設定模擬層級的詳細資訊,請參閱 在 INF 檔案中指定 WDF 指示詞

  • 用戶端應用程式必須為每個檔案控制代碼設定允許的模擬層級。 應用程式會使用 Microsoft Win32 CreateFile 函式中的服務品質 (QoS) 設定,來設定允許的模擬層級。 如需這些設定的詳細資訊,請參閱 Windows SDK 檔中CreateFiledwFlagsAndAttributes參數。

處理 I/O 要求的模擬

UMDF 驅動程式和架構會以下列連續處理 I/O 要求的模擬:

  1. 驅動程式會呼叫 WdfRequestImpersonate 方法,以指定必要的模擬層級和 EvtRequestImpersonate 回 呼函式。

  2. 架構會檢查要求的模擬層級。 如果要求的層級大於 UMDF 驅動程式安裝套件和用戶端應用程式允許的層級,模擬要求就會失敗。 否則,架構會模擬用戶端,並立即呼叫 EvtRequestImpersonate 回 呼函式。

EvtRequestImpersonate回呼函式只能執行需要要求模擬層級的作業,例如開啟受保護的檔案。

架構不允許驅動程式的 EvtRequestImpersonate 回呼函式呼叫任何架構的物件方法。 這可確保驅動程式不會向其他驅動程式回呼函式或其他驅動程式公開模擬層級。

最佳做法是,在呼叫該要求的 WdfRequestImpersonate之前,您的驅動程式不應該啟用 I/O 要求的取消

WdfRequestImpersonate方法只會授與驅動程式要求的模擬層級。

將認證傳遞至驅動程式堆疊

當您的驅動程式收到 WdfRequestTypeCreate類型 I/O 要求時,驅動程式可能會將 I/O 要求向下轉送至核心模式驅動程式。 核心模式驅動程式沒有 WdfRequestImpersonate 提供給 UMDF 驅動程式的模擬功能。

因此,如果您想要核心模式驅動程式接收用戶端的使用者認證, (驅動程式主機進程的認證) ,驅動程式必須在呼叫WdfRequestSend時設定WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT旗標,以將建立要求傳送至 I/O 目標。 如果模擬嘗試失敗, 則 Send 方法會傳回錯誤碼,除非驅動程式也會設定 WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE 旗標。

下列範例示範 UMDF 驅動程式如何使用 WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT 旗標,將檔案建立要求傳送至 I/O 目標。 驅動程式的 INF 檔案也必須包含 UmdfImpersonationLevel 指示詞,如上所述。

WDFIOTARGET iotarget;
WDF_REQUEST_SEND_OPTIONS options;
NTSTATUS status;
WDF_REQUEST_PARAMETERS params;
ULONG sendFlags;  
 
WDF_REQUEST_PARAMETERS_INIT(&params);
WdfRequestGetParameters(Request, &params);
   
sendFlags = WDF_REQUEST_SEND_OPTION_SYNCHRONOUS;
if (params.Type == WdfRequestTypeCreate) {
    sendFlags |= WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT;
}
   
WDF_REQUEST_SEND_OPTIONS_INIT(&options, sendFlags);
if (WdfRequestSend(Request,
                   iotarget,
                   &options
                   ) == FALSE) {
    status = WdfRequestGetStatus(Request);
}

驅動程式不需要先呼叫 WdfRequestImpersonate ,再將要求傳送至 I/O 目標。

如果較低層級的驅動程式也會轉送要求,用戶端的模擬層級會向下移動驅動程式堆疊。

降低安全性威脅

若要降低「提高許可權」攻擊的機會,您應該:

  • 請嘗試避免使用模擬。

    例如,若要避免使用模擬來開啟驅動程式必須使用的檔案,用戶端應用程式可以開啟檔案,並使用 I/O 作業將檔案內容傳送至驅動程式。

  • 使用驅動程式所需的最低模擬層級。

    盡可能將驅動程式 INF 檔案中的模擬層級設定為最低。 如果您的驅動程式不需要任何模擬,請勿在 INF 檔案中包含 UmdfImpersonationLevel 指示詞。

  • 將攻擊者惡意探索驅動程式的機會降到最低。

    EvtRequestImpersonate回呼函式應該包含一小段的程式碼,只執行需要模擬的作業。 例如,如果您的驅動程式存取受保護的檔案,只有在開啟檔案控制碼時,才需要模擬。 它不需要模擬來讀取或寫入檔案。