Clear System Center End Point Protection Exclusions without SCCM

Defining the problem

Recently had a requirement to install / configure / modify Microsoft's System Center End Point Protection software on around 1000 servers without using System Center Configuration Manager.

Installing, performing scans, changing the policy, and gathering data on the system health are trivial.

However, when changing the policy via ConfigSecurityPolicy.exe, it was noticed that the old exclusions were not removed from the registry.

Figured we must be building our policy XML files incorrectly, and started a Bing search, which led to a similar question in the Forefront forums: FEP Policy not applying completely.

Registry Keys of interest

Created the following program, which when run from the target server, clears out the following registry keys:
SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Extensions
SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Paths
SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Processes
SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\TemporaryPaths

The program first grants Ownership of the key SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions to the local Administrators group, then takes ownership of the subkeys, before clearing out the values.

We run the program remotely just before changing policies.

Code

 

      using Microsoft.Win32;
      using System;
      using System.Diagnostics;
      using System.Runtime.InteropServices;
      using System.Security.AccessControl;
   
      namespace modifyRegistry
      {  
                    class Program  
                    {      
                        [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 TOKEN_QUERY = 0x00000008;  
                        internal const  int TOKEN_ADJUST_PRIVILEGES = 0x00000020;  
                        static System.Security.Principal.NTAccount adminAccount =  new  System.Security.Principal.NTAccount("Administrators");   
                        static RegistryAccessRule rule = new RegistryAccessRule(adminAccount, RegistryRights.FullControl, AccessControlType.Allow);  
                        static string  exclusionKey = @"SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions";  
                        static RegistryKeyPermissionCheck permissionCheck = RegistryKeyPermissionCheck.ReadWriteSubTree;  
                        static RegistryRights rights = RegistryRights.TakeOwnership;  
                        static void  Main(string[] args)  
                        {      
                            EnablePrivilege();      
                            using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(exclusionKey, permissionCheck, rights))  
                            {      
                                if (rk != null)  
                                {      
                                    TakeOwnershipOfKey(rk,       "Extensions"      );      
                                    ClearKey(rk,       "Extensions"      );      
                                    TakeOwnershipOfKey(rk,       "Paths"      );      
                                    ClearKey(rk,       "Paths"      );      
                                    TakeOwnershipOfKey(rk,       "Processes"      );      
                                    ClearKey(rk,       "Processes"      );      
                                    TakeOwnershipOfKey(rk,       "TemporaryPaths"      );      
                                    ClearKey(rk,       "TemporaryPaths"      );      
                                }      
                            }      
                        }      
                        public static  void TakeOwnershipOfKey(RegistryKey rootKey,string subKey)  
                        {      
                            using (RegistryKey myKey = rootKey.OpenSubKey(subKey, permissionCheck, rights))  
                            {      
                                RegistrySecurity acl = myKey.GetAccessControl(AccessControlSections.None);      
                                acl.SetOwner(adminAccount);      
                                myKey.SetAccessControl(acl);      
                                acl = myKey.GetAccessControl(AccessControlSections.Access);      
                                acl.SetAccessRule(rule);      
                                acl.SetAccessRuleProtection(      true      ,       true      );      
                                myKey.SetAccessControl(acl);      
                                myKey.Close();      
                          }      
                        }      
                        public static  void ClearKey(RegistryKey rootKey, string subKey)  
                        {      
                            foreach (string registryValue in rootKey.OpenSubKey(subKey).GetValueNames())  
                            {      
                                Console.WriteLine(      "deleting the value " + registryValue);  
                                rootKey.CreateSubKey(subKey).DeleteValue(registryValue);      
                            }      
                        }      
                        public static  void EnablePrivilege()  
                        {      
                            Process currentProcess = Process.GetCurrentProcess();      
                            IntPtr hproc = currentProcess.Handle;      
                            TokPriv1Luid tp;      
                            IntPtr htok = IntPtr.Zero;      
                            OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,       ref  htok);  
                            tp.Count = 1;      
                            tp.Luid = 0;      
                            tp.Attr = SE_PRIVILEGE_ENABLED;      
                            LookupPrivilegeValue(      null      ,       "SeTakeOwnershipPrivilege"      ,       ref  tp.Luid);  
                            AdjustTokenPrivileges(htok,       false      ,       ref  tp, 0, IntPtr.Zero, IntPtr.Zero);  
                        }      
                    }      
      }  

Running the program

Copy the program to the $admin\temp path on remote computers, and run it from a central console. Use the Create method of the Win32_Process class.

Output

Before running the program

The image below is representative of the Paths key before running the program:

During program execution

As the program is running, it displays the values that are removed:
deleting the value C:\Windows\Security\Database\.jrs
deleting the value C:\Windows\Security\Database\.log
deleting the value C:\Windows\Security\Database\.sdb
deleting the value C:\Windows\SoftwareDistribution\Datastore\Datastore.edb
deleting the value C:\Windows\SoftwareDistribution\Datastore\Logs\Edb.chk
deleting the value C:\Windows\SoftwareDistribution\Datastore\Logs\Res*.jrs
deleting the value C:\Windows\SoftwareDistribution\Datastore\Logs\Res*.log
deleting the value C:\Windows\SoftwareDistribution\Datastore\Logs\Tmp.edb
deleting the value C:\Windows\system32\spool\PRINTERS\.shd
deleting the value C:\Windows\system32\spool\PRINTERS\.spl
deleting the value C:\pagefile.sys

After running the program

Once the program is finished, the keys are empty:

See Also