对象句柄

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

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

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

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

文件

IoCreateFileZwCreateFileZwOpenFile

注册表项

IoOpenDeviceInterfaceRegistryKeyIoOpenDeviceRegistryKeyZwCreateKeyZwOpenKey

线程数

PsCreateSystemThread

事件

IoCreateSynchronizationEventIoCreateNotificationEvent

符号链接

ZwOpenSymbolicLinkObject

目录对象

ZwCreateDirectoryObject

节对象

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来验证该句柄是否为事件句柄。