对象句柄
驱动程序和用户模式组件通过 句柄访问大多数系统定义的对象。 句柄由 HANDLE 不透明数据类型表示。 (请注意,句柄不用于访问设备对象或驱动程序对象。)
对于大多数对象类型,创建或打开 对象的内核模式例程为调用方提供句柄。 然后,调用方在对象的后续操作中使用该句柄。
下面是驱动程序通常使用的对象类型列表,以及为该类型的对象提供句柄的例程。
对象类型 | 相应的创建/打开例程 |
---|---|
文件 |
|
注册表项 |
IoOpenDeviceInterfaceRegistryKey、 IoOpenDeviceRegistryKey、 ZwCreateKey、 ZwOpenKey |
线程 |
|
事件 |
|
符号链接 |
|
目录对象 |
|
Section 对象 |
当驱动程序不再需要访问 对象时,它会调用 ZwClose 例程来关闭句柄。 这适用于上表中列出的所有对象类型。
大多数提供句柄的例程都采用 OBJECT_ATTRIBUTES 结构作为参数。 此结构可用于指定句柄的属性。
驱动程序可以指定以下句柄属性:
OBJ_KERNEL_HANDLE
只能从内核模式访问句柄。
OBJ_INHERIT
当前进程的任何子进程在创建时都会收到句柄的副本。
OBJ_FORCE_ACCESS_CHECK
此属性指定系统对句柄执行所有访问检查。 默认情况下,系统会绕过对内核模式下创建的句柄进行的所有访问检查。
使用 InitializeObjectAttributes 例程在 OBJECT_ATTRIBUTES 结构中设置这些属性。
有关验证对象句柄的信息,请参阅 验证对象句柄失败。
专用对象句柄
每当驱动程序创建用于其专用的对象句柄时,驱动程序都必须指定 OBJ_KERNEL_HANDLE 属性。 这可确保用户模式应用程序无法访问句柄。
共享对象句柄
在内核模式和用户模式之间共享对象句柄的驱动程序必须仔细编写,以避免意外造成安全漏洞。 下面是一些准则:
在内核模式下创建句柄,并将其传递到用户模式,而不是相反。 不应信任由用户模式组件创建并传递给驱动程序的句柄。
如果驱动程序必须代表用户模式应用程序操作句柄,请使用 OBJ_FORCE_ACCESS_CHECK 属性来验证应用程序是否具有必要的访问权限。
使用 ObReferenceObjectByPointer 在共享句柄上保留内核模式引用。 否则,如果用户模式组件关闭句柄,引用计数将变为零,如果驱动程序尝试使用或关闭句柄,系统将崩溃。
如果用户模式应用程序创建事件对象,则驱动程序可以安全地等待该事件发出信号,但前提是应用程序通过 IOCTL 将事件对象的句柄传递给驱动程序。 驱动程序必须在创建事件的进程的上下文中处理 IOCTL,并且必须通过调用 ObReferenceObjectByHandle 来验证句柄是否为事件句柄。