Как настроить контроль аудита для файлов, принадлежащих TrustedInstaller, с помощью Powershell?

Я пытаюсь установить контроль аудита для нескольких файлов (перечисленных в ACLsWin.txt) находится в \%Windows%\System32 (например, aaclient.dll) используя следующий скрипт Powershell:

$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?

1 ответ

Решение

Единственный поддерживаемый способ изменения файлов, защищенных защитой ресурсов Windows (учетная запись TrustedInstaller является частью WRP), заключается в использовании службы установщика модулей Windows, которая на самом деле является просто способом сказать: "Вы не можете изменять эти файлы в самостоятельно поддерживаемым способом; только путем установки исправлений и пакетов обновления эти файлы могут быть изменены поддерживаемым способом. "

sfc.exe Утилита также является частью Windows Resource Protection. С помощью sfc.exe Вы можете, чтобы файл был изменен, и он заменит его на копию из хранилища WinSxS.

Вы должны будете сами стать владельцем этих файлов, прежде чем сможете их изменить. Самый простой способ сделать это с takeown.exe,

Но дело в том, что вы не должны изменять эти файлы.

Разработчики приложений могут использовать SfcIsFileProtected или же SfcIsKeyProtected API-интерфейсы для проверки того, находится ли файл под защитой 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

Я бесстыдно украл функцию Enable-Privilege из этой ветки форума TechNet.

Другие вопросы по тегам