我创建了一个CreateDirectoryW
的文件夹,我无法访问该文件夹。我使用nullptr
作为安全描述符,但由于某种原因,它没有复制父文件夹的ACL,而是使文件夹无法访问。
我无法查看或更改所有者。 takeown,icacls,SetNamedSecurityInfoW
,所有来自提升的流程或命令提示,都会失败并显示ERROR_ACCESS_DENIED
。
在尝试使用Linux live CD之前,我是否有机会在Windows(Shell或C ++)中删除此文件夹?希望这些CD不关心ACL?
答案 0 :(得分: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;
}
请注意,为了简明起见,省略了一些错误处理。另请注意,AdjustTokenPrivileges()是少数特殊情况之一,即使调用成功,调用GetLastError()也是有意义的;它将返回ERROR_SUCCESS
或ERROR_NOT_ALL_ASSIGNED
,具体取决于您是否具有您尝试启用的所有权限。
这是绕过文件安全权限的相当普遍的解决方案。它适用于大多数API调用,但在某些情况下(最值得注意的是CreateFile),您必须提供特殊标志才能使用备份权限。除了删除文件或删除您没有权限的目录外,您还可以更改属性,更改权限,甚至将所有权分配给其他人,这是不允许的。
答案 1 :(得分:2)
假设文件未打开且与删除共享标志不兼容且文件中没有任何部分。
删除文件足够2件事 - 我们在父文件夹上有FILE_DELETE_CHILD
。和文件不是只读的。在这种情况下,请调用ZwDeleteFile
(但不是DeleteFile
或RemoveDirectory
- 如果文件空 DACL ),则此api将失败。如果文件具有只读属性 - ZwDeleteFile
失败,代码为STATUS_CANNOT_DELETE
。在这种情况下,我们首先需要删除只读。为此需要打开FILE_WRITE_ATTRIBUTES
访问权限的文件。如果我们在调用ZwOpenFile
时SE_RESTORE_PRIVILEGE
并设置FILE_OPEN_FOR_BACKUP_INTENT
选项,我们就可以执行此操作。所以删除文件的代码可以是下一个:
NTSTATUS DeleteEx(POBJECT_ATTRIBUTES poa)
{
NTSTATUS status = ZwDeleteFile(poa);
if (status == STATUS_CANNOT_DELETE)
{
BOOLEAN b;
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &b);
HANDLE hFile;
IO_STATUS_BLOCK iosb;
if (0 <= (status = NtOpenFile(&hFile, FILE_WRITE_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT)))
{
static FILE_BASIC_INFORMATION fbi = {{},{},{},{}, FILE_ATTRIBUTE_NORMAL};
status = ZwSetInformationFile(hFile, &iosb, &fbi, sizeof(fbi), FileBasicInformation);
NtClose(hFile);
if (0 <= status)
{
status = ZwDeleteFile(poa);
}
}
}
return status;
}