I have created a folder with CreateDirectoryW to which I haven't got access. I used nullptr as a security descriptor, but for some reason it didn't copy the parent folder's ACLs, but instead made the folder inaccessible.
I can't view or change the owner. takeown, icacls, SetNamedSecurityInfoW, all from elevated processes or command prompts, fail with ERROR_ACCESS_DENIED.
Do I have any chance of deleting this folder in Windows (Shell or C++) before trying a Linux live CD which hopefully doesn't care about the ACLs?
You just need to enable backup (or restore) privilege:
#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;
}
Note that in the interests of conciseness, some error handling has been omitted. Also note that AdjustTokenPrivileges() is one of the few special cases where calling GetLastError() is meaningful even though the call succeeded; it will return ERROR_SUCCESS or ERROR_NOT_ALL_ASSIGNED depending on whether you actually have all of the privileges you were attempting to enable.
This is a fairly general solution for bypassing security permissions on files. It works for most API calls, although in some cases (most notably CreateFile) you must provide a special flag in order to make use of backup privilege. As well as deleting files or removing directories that you don't have permission to, you can change attributes, change permissions, and even assign ownership to somebody else, which is not otherwise permitted.
assume that file not open with incompatible to delete share flags and no section on file.
for delete file enough 2 things - we have FILE_DELETE_CHILD on parent folder. and file is not read only. in this case call ZwDeleteFile (but not DeleteFile or RemoveDirectory - both this api will fail if file have empty DACL) is enough. in case file have read-only attribute - ZwDeleteFile fail with code STATUS_CANNOT_DELETE. in this case we need first remove read only. for this need open file with FILE_WRITE_ATTRIBUTES access. we can do this if we have SE_RESTORE_PRIVILEGE and set FILE_OPEN_FOR_BACKUP_INTENT option in call to ZwOpenFile. so code for delete file can be next:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With