我必须更改已创建目录的目录权限。 如果该目录不存在,我可以使用CreateDirectoryEx创建具有给定安全访问属性的新目录,但是当该目录已经存在时,我必须更改该目录的安全访问属性,例如:admin-full access user=read access
首先检查目录是否存在,如果目录存在,则更改安全属性
为了在内核对象上设置安全性,需要使用NTSetSecurityObject
或SetKernelObjectSecurity
(这是对NTSetSecurityObject
非常薄的shell),特别是如果您已经有了具有Write_DAC
和Write_Owner
的对象句柄,如果您还想设置label_Security_Information
。
需要理解的是,在对象上设置安全性没有任何其他方法--任何其他api,如SetSecurityInfo
或SetNamedSecurityInfo
,总之内部调用SetKernelObjectSecurity
或NtSetSecurityObject
。
如果我们需要open_if逻辑-如果它还不存在则创建新文件夹,如果它已经存在则打开-需要使用或ntcreatefile
和file_open_if
配置。 然后需要查找io_status_block
的信息成员-是file_opened
还是file_created
。 如果file_opened
调用NTSetSecurityObject
,因为在这种情况下,SecurityDescriptor将在调用NTCreateFile
中被忽略。 否则,我们将SecurityDescriptor设置在NTCreateFile
中。 代码可以是下一个:
NTSTATUS CreateFolderWithSD(PCWSTR lpNewDirectory, PSECURITY_ATTRIBUTES psa)
{
UNICODE_STRING ObjectName;
NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(lpNewDirectory, &ObjectName, 0, 0);
if (0 <= status)
{
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName, 0, psa->lpSecurityDescriptor };
status = NtCreateFile(&oa.RootDirectory, WRITE_DAC|WRITE_OWNER, &oa, &iosb, 0,
FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF,
FILE_DIRECTORY_FILE, 0, 0);
RtlFreeUnicodeString(&ObjectName);
if (0 <= status)
{
switch (iosb.Information)
{
case FILE_OPENED:
status = NtSetSecurityObject(oa.RootDirectory,
DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION, oa.SecurityDescriptor);
case FILE_CREATED:
break;
default: __debugbreak();
}
NtClose(oa.RootDirectory);
}
}
return status;
}
void TestNF(PCWSTR lpNewDirectory)
{
SECURITY_ATTRIBUTES sa = { sizeof(sa) };
if (ConvertStringSecurityDescriptorToSecurityDescriptor(
L"D:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FRFX;;;BU)S:(ML;;NWNX;;;HI)",
SDDL_REVISION_1, &sa.lpSecurityDescriptor, 0))
{
CreateFolderWithSD(lpNewDirectory, &sa);
LocalFree(sa.lpSecurityDescriptor);
}
}
在SetKernelObjectSecurity函数的msdn页面上存在下一个注意事项
注意在文件系统对象上设置安全描述符时不应使用此函数。 相反,请使用SetSecurityInfo或SetNamedSecurityInfo函数。
现在我在这张纸条上的说明--为什么不应该使用? (这并不是说不能用--当然可以)。 我不认为有任何理由或解释。 而且在任何情况下,当我们在文件上设置安全性时都将使用这个api-直接或间接。 所以认为需要忽略这张纸条,这张纸条没有任何解释。
还要注意本机api的使用--这既是内核也是用户模式api(而不是像许多人认为的那样只是内核),并且像任何其他api一样容易(或难)使用它。 没有任何不同(只需使用ntdllp.lib或ntdll.lib)。 我使用NtCreateFile
是因为任何win 32 api都不提供这样功能-文件夹上的open_if逻辑和返回结果-是文件实际打开或创建的。 CreateFilew
不能创建文件夹,即使是文件也不能创建--尽管存在选项Open_Always
(用于File_Open_If
),api不返回的信息是File_Open
或File_Create
--它只是删除它。 createdirectory
根本没有open_if逻辑-如果指定的目录已经存在,它将以error_already_exists
失败。 所以真的NTCreateFile
在这里有最好的,没有模拟功能,因为正是它和使用。 使用的NTSetSecurityObject
而不是SetKernelObjectSecurity
给出了相同的错误类型(NTStatus
)like和NTCreateFile