使用ERROR_ACCESS_DENIED删除每个API调用失败的文件夹

Fel*_*bek 2 c++ winapi access-denied delete-file windows-10

我创建了一个CreateDirectoryW我无法访问的文件夹.我用作nullptr安全描述符,但由于某种原因,它没有复制父文件夹的ACL,而是使文件夹不可访问.

我无法查看或更改所有者.takeown,icacls,SetNamedSecurityInfoW全部来自提升的进程或命令提示,失败ERROR_ACCESS_DENIED.

在尝试Linux live CD之前,我是否有机会在Windows(Shell或C++)中删除此文件夹,希望这些CD不关心ACL?

Har*_*ton 6

您只需启用备份(或恢复)权限:

#include <Windows.h>

#include <stdio.h>

int wmain(int argc, wchar_t ** argv)
{
    // argv[1] must contain the directory to remove

    HANDLE hToken;
    struct 
    {    
        DWORD PrivilegeCount;
        LUID_AND_ATTRIBUTES Privileges[1];    
    } tkp;

    if (OpenProcessToken(GetCurrentProcess(), 
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
    {
        LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tkp.Privileges[0].Luid);

        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (!AdjustTokenPrivileges(hToken, FALSE, 
            (PTOKEN_PRIVILEGES)&tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
        {
            printf("AdjustTokenPrivileges: %u\n", GetLastError());
            return 1;
        }

        if (GetLastError() != ERROR_SUCCESS)
        {
            // This happens if you don't have the privilege
            printf("AdjustTokenPrivileges: %u\n", GetLastError());
            return 1;
        }

        CloseHandle(hToken);
    }

    if (!RemoveDirectory(argv[1]))
    {
        printf("RemoveDirectory: %u\n", GetLastError());
        return 1;
    }

    printf("OK\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意,为了简明起见,省略了一些错误处理.另请注意,AdjustTokenPrivileges()是少数特殊情况之一,即使调用成功,调用GetLastError()也是有意义的; 它将返回ERROR_SUCCESSERROR_NOT_ALL_ASSIGNED取决于您是否确实拥有您尝试启用的所有权限.

这是绕过文件安全权限的相当普遍的解决方案.它适用于大多数API调用,但在某些情况下(最值得注意的是CreateFile),您必须提供特殊标志才能使用备份权限.除了删除文件或删除您没有权限的目录外,您还可以更改属性,更改权限,甚至将所有权分配给其他人,否则不允许这样做.