次の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
ユーティリティもWindowsResourceProtectionの一部です。 sfc.exe
を使用すると、ファイルが変更されていることがわかり、WinSxSストアからのコピーに置き換えられます。
これらのファイルを変更する前に、自分でこれらのファイルの所有権を取得する必要があります。これを行う最も簡単な方法は、takeown.exe
を使用することです。
しかし、実際のところ、これらのファイルを変更することは想定されていません。
アプリケーション開発者は、SfcIsFileProtected
またはSfcIsKeyProtected
APIを使用して、ファイルがWRPの保護下にあるかどうかを確認できます。
誰かがこれを行うためのスクリプトを書かない理由は、これらのファイルを変更することがサポートされていないためです。専門家として、誰かがシステムをサポートされていない状態にするのを良心的に助けることができませんでした。 ;) 編集:くそー、私はちょうどやった...
編集:それでもハッキングを主張する場合、技術的には1つのオプションは 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では、次のようにdot-sourceEnable-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