对象句柄

驱动程序和用户模式组件通过 句柄访问大多数系统定义的对象。 句柄由 HANDLE 不透明数据类型表示。 (请注意,句柄不用于访问设备对象或驱动程序对象。)

对于大多数对象类型,创建或打开 对象的内核模式例程为调用方提供句柄。 然后,调用方在对象的后续操作中使用该句柄。

下面是驱动程序通常使用的对象类型列表,以及为该类型的对象提供句柄的例程。

对象类型 相应的创建/打开例程

文件

IoCreateFileZwCreateFileZwOpenFile

注册表项

IoOpenDeviceInterfaceRegistryKeyIoOpenDeviceRegistryKeyZwCreateKeyZwOpenKey

线程

PsCreateSystemThread

事件

IoCreateSynchronizationEventIoCreateNotificationEvent

符号链接

ZwOpenSymbolicLinkObject

目录对象

ZwCreateDirectoryObject

Section 对象

ZwOpenSection

当驱动程序不再需要访问 对象时,它会调用 ZwClose 例程来关闭句柄。 这适用于上表中列出的所有对象类型。

大多数提供句柄的例程都采用 OBJECT_ATTRIBUTES 结构作为参数。 此结构可用于指定句柄的属性。

驱动程序可以指定以下句柄属性:

  • OBJ_KERNEL_HANDLE

    只能从内核模式访问句柄。

  • OBJ_INHERIT

    当前进程的任何子进程在创建时都会收到句柄的副本。

  • OBJ_FORCE_ACCESS_CHECK

    此属性指定系统对句柄执行所有访问检查。 默认情况下,系统会绕过对内核模式下创建的句柄进行的所有访问检查。

使用 InitializeObjectAttributes 例程在 OBJECT_ATTRIBUTES 结构中设置这些属性。

有关验证对象句柄的信息,请参阅 验证对象句柄失败

专用对象句柄

每当驱动程序创建用于其专用的对象句柄时,驱动程序都必须指定 OBJ_KERNEL_HANDLE 属性。 这可确保用户模式应用程序无法访问句柄。

共享对象句柄

在内核模式和用户模式之间共享对象句柄的驱动程序必须仔细编写,以避免意外造成安全漏洞。 下面是一些准则:

  1. 在内核模式下创建句柄,并将其传递到用户模式,而不是相反。 不应信任由用户模式组件创建并传递给驱动程序的句柄。

  2. 如果驱动程序必须代表用户模式应用程序操作句柄,请使用 OBJ_FORCE_ACCESS_CHECK 属性来验证应用程序是否具有必要的访问权限。

  3. 使用 ObReferenceObjectByPointer 在共享句柄上保留内核模式引用。 否则,如果用户模式组件关闭句柄,引用计数将变为零,如果驱动程序尝试使用或关闭句柄,系统将崩溃。

如果用户模式应用程序创建事件对象,则驱动程序可以安全地等待该事件发出信号,但前提是应用程序通过 IOCTL 将事件对象的句柄传递给驱动程序。 驱动程序必须在创建事件的进程的上下文中处理 IOCTL,并且必须通过调用 ObReferenceObjectByHandle 来验证句柄是否为事件句柄。