[译]为驱动设备对象设置适当的安全描述符
正确的安全描述符能够让你有效的控制其他人对你的驱动设备对象的访问。通常,你可以调用:
IoCreateDeviceSecure 来创建驱动设备对象并拥有正确的 DACL 权限。IoCreateDeviceSecure
的一个问题是 SSDL 字符串的功能有限,一般来说,只能选用预定义的 SID 值。如果你想使用非
预定义的 SID 值,那么你必须自己创建安全描述符,令人遗憾的是这种编码的方法并不简单。
IoCreateDeviceSecure 来创建驱动设备对象并拥有正确的 DACL 权限。IoCreateDeviceSecure
的一个问题是 SSDL 字符串的功能有限,一般来说,只能选用预定义的 SID 值。如果你想使用非
预定义的 SID 值,那么你必须自己创建安全描述符,令人遗憾的是这种编码的方法并不简单。
感谢 Paul Sliwowicz 热心的提供了以下这段为驱动设备对象设置适当的安全描述符的代码。不过,
这种方法需要你首先拥有打开驱动设备句柄的权限。因此,最好的方法是在最初创建设备时选择一
个非常严格的 SDDL 字符串从而限制其只能由系统打开,之后通过以下代码调低访问权限。这种方法
适用于 WDM 或者 KMDF 驱动程序。这种方法还可以用来调整其他驱动程序创建的驱动设备对象,但是
你必须仔细考虑并解决在设备创建和你设置安全描述符时的竞争问题。
NTSTATUS
SetDeviceDacl(
PDEVICE_OBJECT DeviceObject
)
{
SECURITY_DESCRIPTOR sd = { 0 };
ULONG aclSize = 0;
PACL pAcl = NULL;
NTSTATUS status;
status = ObOpenObjectByPointer (DeviceObject,
OBJ_KERNEL_HANDLE,
NULL,
WRITE_DAC,
0,
KernelMode,
&fileHandle);
if (!NT_SUCCESS(status)) {
goto Exit;
}
//
// Calculate how big our ACL needs to be to support one ACE (in
// this case we'll use a predefined Se export for local system
// as the SID)
//
aclSize = sizeof(ACL);
aclSize += RtlLengthSid (SeExports ->SeLocalSystemSid);
aclSize += RtlLengthSid(SeExports->SeAliasAdminsSid);
aclSize += RtlLengthSid(SeExports->SeAliasUsersSid);
//
// Room for 3 ACEs (one for each SID above); note we don't
// include the end of the structure as we've accounted for that
// length in the SID lengths already.
//
aclSize += 3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
pAcl = (PACL) ExAllocatePoolWithTag(PagedPool, aclSize, TAG);
if (pAcl == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
status = RtlCreateAcl (pAcl, aclSize, ACL_REVISION);
if (!NT_SUCCESS(status)) {
goto Exit;
}
status = RtlAddAccessAllowedAce (pAcl,
ACL_REVISION,
GENERIC_READ | GENERIC_WRITE | DELETE,
SeExports->SeLocalSystemSid);
if (!NT_SUCCESS(status)) {
goto Exit;
}
status = RtlAddAccessAllowedAce(pAcl,
ACL_REVISION,
GENERIC_READ | GENERIC_WRITE | DELETE,
SeExports->SeAliasAdminsSid );
if (!NT_SUCCESS(status)) {
goto Exit;
}
status = RtlAddAccessAllowedAce(pAcl,
ACL_REVISION,
GENERIC_READ,
SeExports->SeAliasUsersSid );
if (!NT_SUCCESS(status)) {
goto Exit;
}
//
// Create a security descriptor
//
status = RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(status)) {
goto Exit;
}
//
// Associate the above pAcl with the security descriptor
//
status = RtlSetDaclSecurityDescriptor (&sd, TRUE, pAcl, FALSE);
if (!NT_SUCCESS(status)) {
goto Exit;
}
//
// Set security on the object
//
status = ZwSetSecurityObject (fileHandle, DACL_SECURITY_INFORMATION, &sd);
if (!NT_SUCCESS(status)) {
goto Exit;
}
Exit:
ZwClose(fileHandle);
fileHandle = NULL;
if (pAcl != NULL) {
ExFreePool(pAcl);
pAcl = NULL;
}
return status;
}
===========================================================================
PS: 翻译的比较差,一方面因为我的水平有限,另一方面是因为原话确实很难翻译。
原文为: