2017-07-10 3 views
1

Windows Defenderのレジストリキーに除外パスを追加する必要があります。私は、Windows Defenderから提供されたコマンドレットには、これらの目的に直接使用するコマンドレットがあることを認識しています。しかし残念ながら、Windows   7とPowerShell v2では、それらは利用できません。だから私は手動でレジストリキーに値を入力するスクリプトを構築しようとしています。オンラインで調べることで、まず所有者をAdministratorsに変更するスクリプトを作成しました(SYSTEM、WinDefend、およびTrustedInstallerユーザーのみがこのキーにアクセスできるため)、値を追加して、最終的に所有者を初期所有者に設定しますこの場合はSYSTEM)を再度実行します。レジストリキーの所有者をSYSTEMユーザーに設定する

Param([string]$targetPath) 

function enable-privilege { 
    Param(
    ## The privilege to adjust. This set is taken from 
    ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx 
    [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, 
    ## The process on which to adjust the privilege. Defaults to the current process. 
    $ProcessId = $pid, 
    ## Switch to disable the privilege, rather than enable it. 
    [Switch] $Disable 
) 

    ## Taken from P/Invoke.NET with minor adjustments. 
    $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) 
} 

私は変更実行コード部:

function getRegKeyOwner([string]$keyPath){ 
    $regRights=[System.Security.AccessControl.RegistryRights]::ReadPermissions 
    $permCheck=[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree 

    $Key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $permCheck, $regRights) 
    $acl = $Key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::Owner) 
    $owner = $acl.GetOwner([type]::GetType([System.Security.Principal.NTAccount])) 
    $key.Close() 
    return $owner 
} 

function setValueToKey([string]$keyPath, [string]$name, [System.Object]$value, [Microsoft.Win32.RegistryValueKind]$regValueKind){ 
    $regRights=[System.Security.AccessControl.RegistryRights]::SetValue 
    $permCheck=[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree 

    $Key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $permCheck, $regRights) 

    "Setting value with properties [name:$name, value:$value, value type:$regValueKind]" 
    $Key.SetValue($name, $value, $regValueKind) 
    $key.Close() 
} 

function changeRegKeyOwner([string]$keyPath, [System.Security.Principal.NTAccount]$user){ 
    try { 
     $regRights=[System.Security.AccessControl.RegistryRights]::TakeOwnership 
     $permCheck=[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree 
     $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $permCheck, $regRights) 
     # You must get a blank acl for the key b/c you do not currently have access 
     $acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None) 

     if([string]::IsNullOrEmpty($user)){ 
      $user = [System.Security.Principal.NTAccount]"$env:userdomain\$env:username" 
     } 

     "Changing owner of Registry key: HKEY_LOCAL_MACHINE\$keyPath to `"$user`"" 
     $acl.SetOwner($user) 
     $key.SetAccessControl($acl) 
    } catch { 
     $_.Exception.toString() 
     $key.Close() 
     return 
    } 
    giveFullControlToUser -userName "$user" -key $key 

    $key.Close() 
} 

function giveFullControlToUser([String]$userName,[Microsoft.Win32.RegistryKey] $key){ 
    "giving full access to $userName for key $key" 
    # After you have set owner you need to get the acl with the perms so you can modify it. 
    $acl = $key.GetAccessControl() 
    $rule = New-Object System.Security.AccessControl.RegistryAccessRule ($userName, "FullControl", @("ObjectInherit", "ContainerInherit"), "None", "Allow") 
    $acl.SetAccessRule($rule) 
    $key.SetAccessControl($acl) 
} 

function getAdminUser { 
    $windowsKey = "SOFTWARE\Microsoft\Windows" 
    return getRegKeyOwner -keyPath $windowsKey 
} 

enable-privilege SeTakeOwnershipPrivilege 

$exclussionsPathsKey = "SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" 
$adminGroupName = gwmi win32_group -filter "LocalAccount = $TRUE And SID = 'S-1-5-32-544'" | 
        select -expand name 

$originalOwner = getRegKeyOwner -keyPath $exclussionsPathsKey 

"original Owner to the key `"$exclussionsPathsKey`" is: `"$originalOwner`"" 
changeRegKeyOwner -keyPath $exclussionsPathsKey -user ([System.Security.Principal.NTAccount]"$adminGroupName") 

if (!([string]::IsNullOrEmpty($targetPath))) { 
    $valueName = $targetPath 
    $vaue = 0 
    $regValueKind = [Microsoft.Win32.RegistryValueKind]::DWord 
    setValueToKey -keyPath $exclussionsPathsKey -name $valueName -value $vaue -regValueKind $regValueKind 
} 

changeRegKeyOwner -keyPath $exclussionsPathsKey -user $originalOwner 

をしかし、一部の設定値まで、すべてが正常に動作に必要な権限を有効にするために

コード:私のコードを以下に示します。 。私はレジストリキーの値を見ることができます、所有者は完全な権利を持つ "管理者"に変更されます。元のオーナー "SYSTEM"を再度設定しようとするときに限り、私は次の例外を受け取ります。 PowerShellを使った初めてのスクリプトです。そして私は完全に問題を理解/解決することができません。ちなみに、元のユーザーが "SYSTEM"以外のユーザーであった場合は、これが機能します。多分私はここにいくつかの必要な権限を逃しています。

出力:

 
True 
original Owner to the key "SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" is: "NT AUTHORITY\SYSTEM" 
Changing owner of Registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths to "Administrators" 
giving full access to Administrators for key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths 
Changing owner of Registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths to "NT AUTHORITY\SYSTEM" 

System.Management.Automation.MethodInvocationException: Exception calling "SetAccessControl" with "1" argument(s): "The security identifier is not allowed to be the owner of this object." ---> System.InvalidOperationException: The security identifier is not allowed to be the owner of this object. 
    at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle handle, AccessControlSections includeSections, Object exceptionContext) 
    at System.Security.AccessControl.NativeObjectSecurity.Persist(SafeHandle handle, AccessControlSections includeSections, Object exceptionContext) 
    at System.Security.AccessControl.NativeObjectSecurity.Persist(SafeHandle handle, AccessControlSections includeSections) 
    at System.Security.AccessControl.RegistrySecurity.Persist(SafeRegistryHandle hKey, String keyName) 
    at Microsoft.Win32.RegistryKey.SetAccessControl(RegistrySecurity registrySecurity) 
    at SetAccessControl(Object , Object[]) 
    at System.Management.Automation.MethodInformation.Invoke(Object target, Object[] arguments) 
    at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments) 
    --- End of inner exception stack trace --- 
    at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments) 
    at System.Management.Automation.ParserOps.CallMethod(Token token, Object target, String methodName, Object[] paramArray, Boolean callStatic, Object valueToSet) 
    at System.Management.Automation.MethodCallNode.InvokeMethod(Object target, Object[] arguments, Object value) 
    at System.Management.Automation.MethodCallNode.Execute(Array input, Pipe outputPipe, ExecutionContext context) 
    at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context) 
    at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context) 
+0

*「Windows 7とPowerShell v1」*は何を意味していますか? Windows 7にはPowerShell v2が付属しており、少なくともPowerShell v4を実行できます。しかし、PowerShell v2だけでも、レジストリパスに 'Get-Acl'と' Set-Acl'を使用できるはずです。 –

+0

@AnsgarWiechers申し訳ありませんが、私の悪い!それはPowershell v2です。はい、 'Get-Acl'と' Set-Acl'が利用できます。しかし問題はそこにはない。問題は、レジストリキーの所有者をSYSTEMからAdministratorsに変更するとうまくいきます。しかし、私はそれをSYSTEMに戻そうとします。それは私が提供した例外をスローします:_System.InvalidOperationException:セキュリティ識別子はこのオブジェクトの所有者であることができません。以前はSYSTEMだったので面白いです。 – ShaDooW

答えて

0

最後に、私はスクリプトに欠けていたものを発見しました。管理者ユーザーは、特権を復元するための特別な権限が必要でした。元の所有者を元に戻す前に関数enable-privilege SeRestorePrivilegeを呼び出すだけで、現在のプロセスに必要な権限が与えられます。

関連する問題