Windows-7

如何使用 Powershell 對 TrustedInstaller 擁有的文件設置審核控制?

  • December 12, 2013

我正在嘗試使用以下 Powershell 腳本對ACLsWin.txt位於\%Windows%\System32(例如)中的多個文件(在 中列出)設置審核控制:aaclient.dll

$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. 我以管理員身份執行這些腳本(即使我使用的是內置管理員帳戶),但它仍然失敗。我可以使用“安全”選項卡手動設置這些審核控制,但至少有 200 個文件手動操作可能會導致人為錯誤。

如何TrustedInstaller使用 Powershell 繞過和設置這些審計控制?

修改受 Windows 資源保護(TrustedInstaller 帳戶是 WRP 的一部分)保護的文件的唯一受支持的方法是使用 Windows 模組安裝程序服務,這實際上只是一種說“您不能在自己支持的方式;只有通過安裝更新檔和服務包才能以支持的方式修改這些文件。”

sfc.exe實用程序也是 Windows 資源保護的一部分。您可以使用sfc.exe該文件已被修改,並將其替換為 WinSxS 商店中的副本。

在修改它們之前,您必須自己擁有這些文件的所有權。最簡單的方法是使用takeown.exe.

但事實是您不應該修改這些文件。

應用程序開發人員可以使用SfcIsFileProtectedSfcIsKeyProtectedAPI 檢查文件是否受 WRP 保護。

我不會為某人編寫腳本來執行此操作的原因是因為不支持修改這些文件,並且作為專業人士,我不能憑良心幫助某人將他們的系統置於不受支持的狀態。;)編輯:該死,我剛剛…

編輯:如果您仍然堅持破解它,那麼從技術上講,一種選擇Powershell.exe使用TrustedInstaller.exe.

或者,更簡單的做法是使用 Try/Catch 塊編寫腳本,如果 catch 塊由 觸發[UnauthorizedAccessException],則獲取文件的所有權並重試。

C:\Windows\system32>takeown /A /F C:\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)

啟用 SeRestorePrivilege:

PS C:\> Enable-Privilege SeRestorePrivilege

重新應用修改後的 ACL。如果您沒有明確設置 SeRestorePrivilege 權限,這部分即使對於本地系統帳戶也會失敗:

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

我無恥地從這個 TechNet 論壇執行緒中竊取了 Enable-Privilege 功能。

引用自:https://serverfault.com/questions/551429