提问者:小点点

如何使用Windows API C++更改已创建的文件夹/目录安全权限


我必须更改已创建目录的目录权限。 如果该目录不存在,我可以使用CreateDirectoryEx创建具有给定安全访问属性的新目录,但是当该目录已经存在时,我必须更改该目录的安全访问属性,例如:admin-full access user=read access

首先检查目录是否存在,如果目录存在,则更改安全属性


共1个答案

匿名用户

为了在内核对象上设置安全性,需要使用NTSetSecurityObjectSetKernelObjectSecurity(这是对NTSetSecurityObject非常薄的shell),特别是如果您已经有了具有Write_DACWrite_Owner的对象句柄,如果您还想设置label_Security_Information

需要理解的是,在对象上设置安全性没有任何其他方法--任何其他api,如SetSecurityInfoSetNamedSecurityInfo,总之内部调用SetKernelObjectSecurityNtSetSecurityObject

如果我们需要open_if逻辑-如果它还不存在则创建新文件夹,如果它已经存在则打开-需要使用或ntcreatefilefile_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_OpenFile_Create--它只是删除它。 createdirectory根本没有open_if逻辑-如果指定的目录已经存在,它将以error_already_exists失败。 所以真的NTCreateFile在这里有最好的,没有模拟功能,因为正是它和使用。 使用的NTSetSecurityObject而不是SetKernelObjectSecurity给出了相同的错误类型(NTStatus)like和NTCreateFile

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(windows|api|c++|更改|创建|文件夹|目录|权限)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?