2017-07-10 3 views
1

Ich muss einen Ausschlusspfad zum Windows Defender-Registrierungsschlüssel hinzufügen. Mir ist bewusst, dass von Windows Defender Cmdlets bereitgestellt werden, um sie direkt für diese Zwecke zu verwenden. Leider sind sie in Windows   7 und PowerShell v2 nicht verfügbar. Ich versuche also, ein Skript zu erstellen, das den Wert für den Registrierungsschlüssel manuell eingibt. Bei der Online - Recherche habe ich ein Skript zusammengestellt, das zuerst den Besitzer in Administratoren umstellt (Da nur die Benutzer SYSTEM, WinDefend und TrustedInstaller Zugriff auf diesen Schlüssel haben), dann füge den Wert hinzu und setze den Besitzer auf den ursprünglichen Besitzer dieser Fall SYSTEM) wieder. Mein Code ist unten angegeben:Setzen Sie den Eigentümer des Registrierungsschlüssels auf SYSTEM user

-Code über die erforderliche Berechtigung zu aktivieren:

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) 
} 

Der Code Teil, wo ich die Änderungen durchführen:

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 

Aber bis der Wert Einstellung Teil, funktioniert alles einwandfrei . Ich kann den Wert im Registrierungsschlüssel sehen, der Besitzer wird zu "Administratoren" mit vollen Rechten geändert. Nur wenn ich versuche, den ursprünglichen Besitzer "SYSTEM" erneut zu setzen, erhalte ich die folgende Ausnahme. Dies ist das erste Mal, dass ich mit PowerShell scripte. Und ich bin völlig unfähig, das Problem zu verstehen/zu lösen. Übrigens funktioniert es, wenn der ursprüngliche Benutzer ein anderer Benutzer als "SYSTEM" war. Vielleicht fehlen mir hier einige Privilegien.

Ausgang:

 
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

Was meinst du * "Windows 7 und PowerShell v1" *? Windows 7 wird mit PowerShell v2 ausgeliefert und kann mindestens PowerShell v4 ausführen. Aber selbst mit PowerShell v2 sollten Sie 'Get-Acl' und' Set-Acl' auf Registrierungspfaden verwenden können. –

+0

@AnsgarWiechers Entschuldigung mein Schlechter! Es ist Powershell v2. Ja, "Get-Acl" und "Set-Acl" sind verfügbar. Aber das Problem liegt nicht dort. Das Problem besteht darin, dass es funktioniert, wenn ich den Besitzer des Registrierungsschlüssels von SYSTEM zu Administratoren ändere. Aber dann versuche ich, es auf SYSTEM zurückzusetzen, es wirft die Ausnahme, die ich zur Verfügung gestellt habe: _System.InvalidOperationException: Die Sicherheitskennung darf nicht der Besitzer dieses Objekts sein_. Was lustig ist, da SYSTEM vorher der Besitzer war. – ShaDooW

Antwort

0

Schließlich habe ich gefunden, was im Drehbuch fehlte. Der Administratorbenutzer benötigt zusätzliche Berechtigungen zum Wiederherstellen der Berechtigung. Schon ein einfacher Aufruf der Funktion enable-privilege SeRestorePrivilege vor dem Setzen des ursprünglichen Besitzers zurück, gibt dem aktuellen Prozess die erforderliche Berechtigung.

Verwandte Themen