Конфигурационный скрипт WMI

Этот скрипт используется для массового конфигурирования удаленного доступа к WMI.

# 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"}