# Usage: # 1. Edit computers.txt referred by $ComputerListFile parameter # 2. Set $account parameter to the name of user those credentials will be used for monitoring # 3. Run the script # 4. Check the log file for results $account = "administrator@dc1" $ComputerListFile = "C:\wmi\computers.txt" $LogFile = "C:\wmi\wmi_setup.log" #--------------------------------------------- Function for print messages to $LogFile and screen ------------------------------------------------------------------------------------------------------------------------------ function print_message($File, [string]$Text) { Write-Host $Text Add-Content $File $Text } #--------------------------------------------- Function for check open DCOM port (135) ----------------------------------------------------------------------------------------------------------------------------------------- function check_open_port($ip, $port, $con_timeout) { $tcpclient = new-object Net.Sockets.TcpClient $Connection = $tcpclient.BeginConnect($ip, $port, $null, $null) $TimeOut = $Connection.AsyncWaitHandle.WaitOne($con_timeout,$false) if(!$TimeOut) { $TCPclient.Close() return 0 } else { try { $TCPclient.EndConnect($Connection) | out-Null $TCPclient.Close() return 1 } catch { ## Machine actively refused the connection. The port is not open but $TimeOut was still true return 0 } } } #--------------------------------------------- Function for enable privilege to change CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6} permissions ----------------------------------------------------------------------------- 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) } #--------------------------------------------- First stage (get account sid, open file computers.txt, initialization permission constants)------------------------------------------------------------ function get-sid { Param ( $DSIdentity ) $ID = new-object System.Security.Principal.NTAccount($DSIdentity) return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString() } $sid = get-sid $account $SDDL = "A;;CCWP;;;$sid" $DCOMSDDLDefaultLaunchPermission = "A;;CCDCLCSWRP;;;$sid" $DCOMSDDLDefaultAccessPermission = "A;;CCDCLC;;;$sid" $DefaultSDDLAccess = "O:BAG:BAD:(A;;CCDCLC;;;PS)(A;;CCDC;;;SY)(A;;CCDCLC;;;BA)" $DefaultSDDLLaunch = "O:BAG:BAD:(A;;CCDCLCSWRP;;;BA)(A;;CCDCSW;;;IU)(A;;CCDCSW;;;SY)(A;;CCDCLCSWRP;;;LA)" $computers = Get-Content $ComputerListFile $timeNow = get-date print_message $LogFile $timeNow #--------------------------------------------- Main loop ---------------------------------------------------------------------------------------------------------------------------------------------- foreach ($strcomputer in $computers) { print_message $LogFile $strcomputer $Port135Open = check_open_port $strcomputer "135" "1000" if ($Port135Open) { try{ $Reg = [WMIClass]"\\$strcomputer\root\default:StdRegProv" } catch { $message = "Error: " + [string]$Error[0] print_message $LogFile $message continue } } else { print_message $LogFile "Error! The RPC server is unavailable. No ping." continue } #-------------------------- apply group policy ------------------------------------------------------------------------------------------------------------------------------------------------ try{ $Win32_OS = Get-WmiObject Win32_OperatingSystem -computer $strcomputer } catch { $message = "Error: " + [string]$Error[0] print_message $LogFile $message continue } print_message $LogFile $Win32_OS.caption $str_version = [regex]::Replace($Win32_OS.version, "(\d.\d).*", '$1'); #6.1.7601 -> 6.1 $version = [decimal]$str_version print_message $LogFile "Applying group policies..." If ($version -ge 5.1) { Invoke-WmiMethod -ComputerName $strcomputer -Path win32_process -Name create -ArgumentList "gpupdate /target:Computer /force /wait:0" | Out-Null } Else { Invoke-WmiMethod -ComputerName $strcomputer -Path win32_process -Name create –ArgumentList "secedit /refreshpolicy machine_policy /enforce" | Out-Null } print_message $LogFile "Applying group policies completed" #--------------------------------------- If Windows 2008 or 7 set CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6} permissions to BUILTIN\Administrators ------------------------------------------ If ($version -ge 6.1) { print_message $LogFile "Set CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6} permissions..." $RemoteKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::ClassesRoot, $strcomputer) enable-privilege SeTakeOwnershipPrivilege $key = $RemoteKey.OpenSubKey("CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}",[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership) # 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) $me = [System.Security.Principal.NTAccount]"BUILTIN\Administrators" $acl.SetOwner($me) $key.SetAccessControl($acl) $TrustedInstaller = [System.Security.Principal.NTAccount]"NT Service\TrustedInstaller" $acl.SetOwner($TrustedInstaller) # 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 ("BUILTIN\Administrators","FullControl","Allow") $acl.SetAccessRule($rule) $key.SetAccessControl($acl) $key.Close() #http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/e718a560-2908-4b91-ad42-d392e7f8f1ad } #--------------------------------------- Enable DCOM, Set authentication (to "Connect") and impersonation (to "Identify") levels ----------------------------------------------------------------- $Result = $Reg.SetStringValue(2147483650,"software\microsoft\ole","EnableDCOM","Y") if ($Result) {print_message $LogFile "EnableDCOM -> Y"} $Result = $Reg.SetDWORDValue(2147483650,"software\microsoft\ole","LegacyAuthenticationLevel","2") if ($Result) {print_message $LogFile "LegacyAuthenticationLevel -> Connect"} $Result = $Reg.SetDWORDValue(2147483650,"software\microsoft\ole","LegacyImpersonationLevel","2") if ($Result) {print_message $LogFile "LegacyImpersonationLevel -> Identify"} #-------------------------------------- Set wmi namespace root/CIMV2 permissions, set COM security permissions ---------------------------------------------------------------------------------- $converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper $security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity $binarySD = @($null) $result = $security.PsBase.InvokeMethod("GetSD",$binarySD) $outsddl = $converter.BinarySDToSDDL($binarySD[0]) $newSDDL = $outsddl.SDDL += "(" + $SDDL + ")" $WMIbinarySD = $converter.SDDLToBinarySD($newSDDL) $WMIconvertedPermissions = ,$WMIbinarySD.BinarySD $result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions) print_message $LogFile "ROOT\cimv2 permissions should be granted" $COMAccess = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","DefaultAccessPermission").uValue if ($COMAccess) { $outCOMAccessSDDL = $converter.BinarySDToSDDL($COMAccess) $newCOMAccessSDDL = $outCOMAccessSDDL.SDDL += "(" + $DCOMSDDLDefaultAccessPermission + ")" } else { $newCOMAccessSDDL = $DefaultSDDLAccess + "(" + $DCOMSDDLDefaultAccessPermission + ")" } $COMAccessbinarySD = $converter.SDDLToBinarySD($newCOMAccessSDDL) $COMAccessconvertedPermissions = ,$COMAccessbinarySD.BinarySD $result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","DefaultAccessPermission", $COMAccessbinarySD.binarySD) if ($result.Returnvalue -eq 0) {print_message $LogFile "DefaultAccessPermission granted"} $COMLaunch = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","DefaultLaunchPermission").uValue if ($COMLaunch) { $outCOMLaunchSDDL = $converter.BinarySDToSDDL($COMLaunch) $newCOMLaunchSDDL = $outCOMLaunchSDDL.SDDL += "(" + $DCOMSDDLDefaultLaunchPermission + ")" } else { $newCOMLaunchSDDL = $DefaultSDDLLaunch + "(" + $DCOMSDDLDefaultLaunchPermission + ")" } $COMLaunchbinarySD = $converter.SDDLToBinarySD($newCOMLaunchSDDL) $COMLaunchconvertedPermissions = ,$COMLaunchbinarySD.BinarySD $result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","DefaultLaunchPermission", $COMLaunchbinarySD.binarySD) if ($result.Returnvalue -eq 0) {print_message $LogFile "DefaultLaunchPermission granted"} } |