如何在不获得 SeRestorePrivilege 的情况下将文件的所有权更改为另一个用户?

How to change ownership of a file to another user without obtaining SeRestorePrivilege?

如果进程具有 SeRestorePrivilege,它可以使用 win32security.SetNamedSecurityInfo 更改文件的所有权。 根据Windows API documentation,

SeRestorePrivilege:

causes the system to grant all write access control to any file, regardless of the ACL specified for the file. Any access request other than write is still evaluated with the ACL. The following access rights are granted if this privilege is held: WRITE_DAC, WRITE_OWNER, ACCESS_SYSTEM_SECURITY, FILE_GENERIC_WRITE, FILE_ADD_FILE, FILE_ADD_SUBDIRECTORY, DELETE

我已将上述所有访问权限授予文件所有者,但更改所有权失败并出现错误 1307:'This security ID may not be assigned as the owner of this object.'。为什么?

代码:

import ntsecuritycon
import win32security
import win32api
import sys
import os

# grant access rights of SeRestorePrivilege
def simulate_se_restore_privilege(path):
    sd = win32security.GetNamedSecurityInfo(path, win32security.SE_FILE_OBJECT, win32security.OWNER_SECURITY_INFORMATION)
    owner_sid = sd.GetSecurityDescriptorOwner()

    dacl = win32security.ACL()
    dacl.SetEntriesInAcl([
        {'AccessPermissions': ntsecuritycon.WRITE_DAC
            | ntsecuritycon.WRITE_OWNER
            | ntsecuritycon.ACCESS_SYSTEM_SECURITY
            | ntsecuritycon.FILE_GENERIC_WRITE
            | ntsecuritycon.FILE_ADD_FILE
            | ntsecuritycon.FILE_ADD_SUBDIRECTORY
            | ntsecuritycon.DELETE,
         'AccessMode': win32security.GRANT_ACCESS,
         'Inheritance': 0,
         'Trustee': {
             'MultipleTrustee': None,
             'MultipleTrusteeOperation': 0,
             'TrusteeForm': win32security.TRUSTEE_IS_SID,
             'TrusteeType': win32security.TRUSTEE_IS_UNKNOWN,
             'Identifier': owner_sid,
         }
        }
    ])

    win32security.SetNamedSecurityInfo(
        path,
        win32security.SE_FILE_OBJECT,
        win32security.DACL_SECURITY_INFORMATION,
        None,
        None,
        dacl,
        None,
    )

def enable_se_restore_privilege():
    tok = win32security.OpenProcessToken(
        win32api.GetCurrentProcess(), win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
    )
    luid = win32security.LookupPrivilegeValue(None, win32security.SE_RESTORE_NAME)
    new_state = [(luid, win32security.SE_PRIVILEGE_ENABLED)]
    win32security.AdjustTokenPrivileges(tok, 0, new_state)
    win32api.CloseHandle(tok)

def change_ownership(path):
    win32security.SetNamedSecurityInfo(
        path,
        win32security.SE_FILE_OBJECT,
        win32security.OWNER_SECURITY_INFORMATION,
        win32security.ConvertStringSidToSid("S-1-0-0"),
        None,
        None,
        None,
    )


path = sys.argv[1]
try:
    os.unlink(path)
except OSError:
    pass

with open(path, "w"):
    pass

print("Adding access rights from SeRestorePrivilege")
simulate_se_restore_privilege(path)
try:
    change_ownership(path)
except Exception as e:
    print(f"Changing ownership failed: {e}")

print("Enabling SeRestorePrivilege")
enable_se_restore_privilege()
change_ownership(path)
print("Changing ownership succeeded")

提升控制台中的输出:

> python .\chown.py file
Adding access rights from SeRestorePrivilege
Changing ownership failed: (1307, 'SetNamedSecurityInfo', 'This security ID may not be assigned as the owner of this object.')
Enabling SeRestorePrivilege
Changing ownership succeeded

根据SeRestorePrivilege的documentation

Additionally, this privilege enables you to set any valid user or group SID as the owner of a file.