如何使用Powershell对TrustedInstaller拥有的文件设置审核控制?

我正在尝试使用以下Powershell脚本在位于\%Windows%\System32 (例如, aaclient.dll )中的许多文件(列在ACLsWin.txt )上设置审核控制:

 $FileList = Get-Content ".\ACLsWin.txt" $ACL = New-Object System.Security.AccessControl.FileSecurity $AccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule("Everyone", "Delete", "Failure") $ACL.AddAuditRule($AccessRule) foreach($File in $FileList) { Write-Host "Changing audit on $File" $ACL | Set-Acl $File } 

每当我运行脚本,我得到错误PermissionDenied [Set-Acl] UnauthorizedAccessException

这似乎来自于这些文件的所有者是TrustedInstaller 。 我以pipe理员身份运行这些脚本(即使我在内置的pipe理员帐户中),但仍然失败。 我可以使用“安全”选项卡手动设置这些审计控制,但至less有200个手动执行的文件可能会导致人为错误。

如何绕过TrustedInstaller并使用Powershell设置这些审核控件?

修改受Windows资源保护(TrustedInstaller帐户是WRP的一部分)的文件的唯一受支持的方法是使用Windows模块安装程序服务,这实际上只是一种说法,“您不能在这些文件中修改这些文件自己支持的方式;只有通过安装补丁和服务包,才能以支持的方式修改这些文件。“

sfc.exe实用程序也是Windows资源保护的一部分。 使用sfc.exe你可以确定该文件已经被修改了,并且将会用WinSxS存储中的一个副本来replace它。

在修改这些文件之前,您必须自己掌握这些文件的所有权。 最简单的方法是使用takeown.exe

但事实是你不应该修改这些文件。

应用程序开发人员可以使用SfcIsFileProtectedSfcIsKeyProtected API来检查文件是否受WRP保护。

之所以我不写脚本是因为不支持修改这些文件,作为专业人员,我不能很好地帮助别人将他们的系统置于不受支持的状态。 ;)编辑:Damnit,我只是…

编辑:如果你仍然坚持黑客攻击,那么从技术上讲,一个select是使用TrustedInstaller.exe的安全令牌启动Powershell.exe

或者,更简单的做法是编写一个带有Try / Catch块的脚本,并且如果catch块由[UnauthorizedAccessException]触发,则获取该文件的所有权并再次尝试。

 C:\Windows\system32>takeown /A /FC:\Windows\System32\aaclient.dll SUCCESS: The file (or folder): "C:\Windows\System32\aaclient.dll" now owned by the administrators group. 

您还可以使用筛选器驱动程序监视对这些文件的修改。 这就是防病毒产品如何实现的。 但是呃…那可能比你现在要做的还要多

再次编辑!:哦,您想要将所有者设置回TrustedInstaller? 你需要SeRestorePrivilege权限。

复制粘贴到。\ Enable-Privilege.ps1:

 Function Enable-Privilege { param([ValidateSet("SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]$Privilege, $ProcessId = $pid, [Switch]$Disable) $Definition = @' using System; using System.Runtime.InteropServices; public class AdjPriv { [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } internal const int SE_PRIVILEGE_ENABLED = 0x00000002; internal const int SE_PRIVILEGE_DISABLED = 0x00000000; internal const int TOKEN_QUERY = 0x00000008; internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; public static bool EnablePrivilege(long processHandle, string privilege, bool disable) { bool retVal; TokPriv1Luid tp; IntPtr hproc = new IntPtr(processHandle); IntPtr htok = IntPtr.Zero; retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; } else { tp.Attr = SE_PRIVILEGE_ENABLED; } retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); return retVal; } } '@ $ProcessHandle = (Get-Process -id $ProcessId).Handle $type = Add-Type $definition -PassThru $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable) } 

在Powershell中,点源Enable-Privilege.ps1是这样的:

 PS C:\> . .\Enable-Privilege.ps1 PS C:\> [System.Security.Principal.NTAccount]$TrustedInstaller = "NT SERVICE\TrustedInstaller" 

保存当前ACL:

 PS C:\> $ACL = Get-Acl C:\Windows\System32\aaclient.dll 

将所有者更改为TrustedInstaller:

 PS C:\> $ACL.SetOwner($TrustedInstaller) 

启用S​​eRestorePrivilege:

 PS C:\> Enable-Privilege SeRestorePrivilege 

重新应用修改的ACL。 如果您没有明确设置SeRestorePrivilege权限,则即使对于本地系统帐户,这也是失败的部分:

 PS C:\> Set-Acl -Path C:\Windows\System32\aaclient.dll -AclObject $ACL 

我无耻地偷走了这个TechNet论坛主题的Enable-Privilegefunction。