HostUtilities.psm1
Function Reset-WindowsUpdate { <# .SYNOPSIS The cmdlet resets all of the windows update components and re-registers the dlls. .DESCRIPTION Several services are stopped, the log files and directories are renamed, several dlls are re-registered, and then the services are restarted. .PARAMETER AutomaticReboot Specify whether the computer should automatically reboot after completing the reset. .INPUTS System.Management.Automation.SwitchParameter .OUTPUTS None .EXAMPLE Reset-WindwsUpdate Resets windows update and does not automatically reboot. .EXAMPLE Reset-WindowsUpdate -AutomaticReboot Resets windows update and automatically reboots the machine. .NOTES The command should be run with administrative credentials. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [switch]$AutomaticReboot = $false ) Begin { if(!(Test-IsLocalAdmin)) { throw "This cmdlet must be run with admin credentials." } } Process { try { Stop-Service -Name BITS -ErrorAction Stop } catch [Exception] { Write-Warning "Could not stop the BITS service" Exit 1 } try { Stop-Service -Name wuauserv -ErrorAction Stop } catch [Exception] { Write-Warning "Could not stop the wuauserv service" Exit } try { Stop-Service -Name AppIDSvc -ErrorAction Stop } catch [Exception] { Write-Warning "Could not stop the AppIDSvc service" Exit 1 } try { Stop-Service -Name CryptSvc -ErrorAction Stop } catch [Exception] { Write-Warning "Could not stop the CryptSvc service" Exit 1 } try { Clear-DnsClientCache -ErrorAction Stop } catch [Exception] { Write-Warning "Could not clear the dns client cache" } Remove-Item -Path "$env:ALLUSERSPROFILE\Application Data\Microsoft\Network\Downloader\qmgr*.dat" if (Test-Path -Path "$env:SYSTEMROOT\winsxs\pending.xml.bak") { Remove-Item -Path "$env:SYSTEMROOT\winsxs\pending.xml.bak" -Recurse -Force } if (Test-Path -Path "$env:SYSTEMROOT\winsxs\pending.xml") { Rename-Item -Path "$env:SYSTEMROOT\winsxs\pending.xml" -NewName "$env:SYSTEMROOT\winsxs\pending.xml.bak" } if (Test-Path -Path "$env:SYSTEMROOT\SoftwareDistribution.bak") { Remove-Item -Path "$env:SYSTEMROOT\SoftwareDistribution.bak" -Recurse -Force } if (Test-Path -Path "$env:SYSTEMROOT\SoftwareDistribution") { Rename-Item -Path "$env:SYSTEMROOT\SoftwareDistribution" -NewName "$env:SYSTEMROOT\SoftwareDistribution.bak" } if (Test-Path -Path "$env:SYSTEMROOT\system32\Catroot2.bak") { Remove-Item -Path "$env:SYSTEMROOT\system32\Catroot2.bak" -Recurse -Force } if (Test-Path -Path "$env:SYSTEMROOT\system32\Catroot2") { Rename-Item -Path "$env:SYSTEMROOT\system32\Catroot2" -NewName "$env:SYSTEMROOT\system32\Catroot2.bak" } if (Test-Path -Path "$env:SYSTEMROOT\WindowsUpdate.log.bak") { Remove-Item -Path "$env:SYSTEMROOT\WindowsUpdate.log.bak" -Recurse -Force } if (Test-Path -Path "$env:SYSTEMROOT\WindowsUpdate.log") { Rename-Item -Path "$env:SYSTEMROOT\WindowsUpdate.log" -NewName "$env:SYSTEMROOT\WindowsUpdate.log.bak" } & "$env:SYSTEMROOT\system32\sc.exe" sdset "BITS" "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" | Out-Null & "$env:SYSTEMROOT\system32\sc.exe" sdset "wuauserv" "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" | Out-Null regsvr32.exe /s atl.dll regsvr32.exe /s urlmon.dll regsvr32.exe /s mshtml.dll regsvr32.exe /s shdocvw.dll regsvr32.exe /s browseui.dll regsvr32.exe /s jscript.dll regsvr32.exe /s vbscript.dll regsvr32.exe /s scrrun.dll regsvr32.exe /s msxml.dll regsvr32.exe /s msxml3.dll regsvr32.exe /s msxml6.dll regsvr32.exe /s actxprxy.dll regsvr32.exe /s softpub.dll regsvr32.exe /s wintrust.dll regsvr32.exe /s dssenh.dll regsvr32.exe /s rsaenh.dll regsvr32.exe /s gpkcsp.dll regsvr32.exe /s sccbase.dll regsvr32.exe /s slbcsp.dll regsvr32.exe /s cryptdlg.dll regsvr32.exe /s oleaut32.dll regsvr32.exe /s ole32.dll regsvr32.exe /s shell32.dll regsvr32.exe /s initpki.dll regsvr32.exe /s wuapi.dll regsvr32.exe /s wuaueng.dll regsvr32.exe /s wuaueng1.dll regsvr32.exe /s wucltui.dll regsvr32.exe /s wups.dll regsvr32.exe /s wups2.dll regsvr32.exe /s wuweb.dll regsvr32.exe /s qmgr.dll regsvr32.exe /s qmgrprxy.dll regsvr32.exe /s wucltux.dll regsvr32.exe /s muweb.dll regsvr32.exe /s wuwebv.dll regsvr32 /s wudriver.dll netsh winsock reset | Out-Null netsh winsock reset proxy | Out-Null Start-Service -Name BITS Start-Service -Name wuauserv Start-Service -Name AppIDSvc Start-Service -Name CryptSvc Write-Host "Successfully reset Windows Update" -ForegroundColor Green } End { if ($AutomaticReboot) { Restart-Computer -Force } else { $Title = "Reboot Now" $Message = "A reboot is required to complete the reset, reboot now?" $Yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", ` "Reboots the computer immediately." $No = New-Object System.Management.Automation.Host.ChoiceDescription "&No", ` "Does not reboot the computer." $Options = [System.Management.Automation.Host.ChoiceDescription[]]($Yes, $No) $Result = $host.ui.PromptForChoice($Title, $Message, $Options, 0) if ($Result -eq 0) { Restart-Computer -Force } } } } Function Get-GroupsFromToken { <# .SYNOPSIS Enumerates the SIDs that are maintained in a user's access token issued at logon and translates the SIDs to group names. .DESCRIPTION The function gets the access token for the user that was issued at their logon. It reads the TOKEN_GROUPS from the access token and retrieves their SIDs from unmanaged memory. It then attempts to translate these SIDs to group names. The function includes all group memberships inherited from nested grouping. .INPUTS None .OUTPUTS System.String[] .EXAMPLE Get-GroupsFromToken Returns an array of group names and/or SIDs in the access token for the current user. .NOTES AUTHOR: Michael Haken LAST UPDATED: 2/27/2016 #> Begin {} Process { $Job = Start-Job -ScriptBlock { Add-Type -Assembly System.ComponentModel $Signatures = @" [DllImport("advapi32.dll", SetLastError=true)] public static extern bool GetTokenInformation( IntPtr TokenHandle, int TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength ); [DllImport("advapi32", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool ConvertSidToStringSid( IntPtr pSID, [In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid ); "@ $AdvApi32 = Add-Type -MemberDefinition $Signatures -Name "AdvApi32" -Namespace "PsInvoke.NativeMethods" -PassThru -ErrorAction SilentlyContinue $TokenClasses = @" using System; using System.Runtime.InteropServices; namespace TokenServices { public enum TOKEN_INFORMATION_CLASS { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, TokenElevationType, TokenLinkedToken, TokenElevation, TokenHasRestrictions, TokenAccessInformation, TokenVirtualizationAllowed, TokenVirtualizationEnabled, TokenIntegrityLevel, TokenUiAccess, TokenMandatoryPolicy, TokenLogonSid, MaxTokenInfoClass } public enum TOKEN_ELEVATION_TYPE { TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited } public struct TOKEN_USER { public SID_AND_ATTRIBUTES User; } [StructLayout(LayoutKind.Sequential)] public struct SID_AND_ATTRIBUTES { public IntPtr Sid; public UInt32 Attributes; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_GROUPS { public UInt32 GroupCount; [MarshalAs(UnmanagedType.ByValArray)] public SID_AND_ATTRIBUTES[] Groups; } } "@ Add-Type $TokenClasses -ErrorAction SilentlyContinue $CloseHandleSignature = @" [DllImport( "kernel32.dll", CharSet = CharSet.Auto )] public static extern bool CloseHandle( IntPtr handle ); "@ $Kernel32 = Add-Type -MemberDefinition $CloseHandleSignature -Name "Kernel32" -Namespace "PsInvoke.NativeMethods" -PassThru -ErrorAction SilentlyContinue [UInt32]$TokenInformationLength = 0 $Success = $AdvApi32::GetTokenInformation( [System.Security.Principal.WindowsIdentity]::GetCurrent().Token, [TokenServices.TOKEN_INFORMATION_CLASS]::TokenGroups, [IntPtr]::Zero, $TokenInformationLength, [Ref]$TokenInformationLength) if ($TokenInformationLength -gt 0) { [IntPtr]$TokenInformation = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenInformationLength) $Success = $AdvApi32::GetTokenInformation( [System.Security.Principal.WindowsIdentity]::GetCurrent().Token, [TokenServices.TOKEN_INFORMATION_CLASS]::TokenGroups, $TokenInformation, $TokenInformationLength, [Ref]$TokenInformationLength ) if ($TokenInformationLength -gt 0) { $GroupArray = @() try { [TokenServices.TOKEN_GROUPS]$Groups = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenInformation, [System.Type][TokenServices.TOKEN_GROUPS]) $SidAndAttrs = New-Object -TypeName TokenServices.SID_AND_ATTRIBUTES [int]$SidAndAttrsSize = [System.Runtime.InteropServices.Marshal]::SizeOf($SidAndAttrs) for ($i = 0; $i -lt $Groups.GroupCount; $i++) { [TokenServices.SID_AND_ATTRIBUTES]$SidAndAttrsGroup = [System.Runtime.InteropServices.Marshal]::PtrToStructure([IntPtr]($TokenInformation.ToInt64() + ($i * $SidAndAttrsSize) + [IntPtr]::Size), [System.Type][TokenServices.SID_AND_ATTRIBUTES]); [string]$SidString = "" $Success = $AdvApi32::ConvertSidToStringSid($SidAndAttrsGroup.Sid, [Ref]$SidString) try { $Group = (New-Object System.Security.Principal.SecurityIdentifier($SidString)).Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value $GroupArray += $Group } catch [Exception] { $GroupArray += $SidString Write-Warning $_.Exception.Message } } Write-Output $GroupArray } catch [Exception] { Write-Warning $_.Exception.Message } finally { $Kernel32::CloseHandle($TokenInformation) | Out-Null } } else { $Kernel32::CloseHandle($TokenInformation) | Out-Null Write-Host (New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message } } else { Write-Host (New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message } } } End { Wait-Job -Job $Job | Out-Null Write-Output (Receive-Job $Job) } } Function Update-TokenGroupMembership { <# .SYNOPSIS The command refreshes the user's token and clears their current Kerberos tickets in order to pick up Active Directory group membership changes since their last logon. .DESCRIPTION The current group membership of the user is recorded. Then, the user's Kerberos tickets are purged. After that, the explorer.exe process is stopped and restarted, which refreshes the logon token for the user. The user will be required to enter a set of credentials and then required to enter their password to restart the explorer.exe process. .PARAMETER Credential The credentials of the current user. These are used to launch a new powershell process to get the updated token group membership. Without using credentials, the new process won't be started with the new token and won't reflect the updates in group membership. .PARAMETER UseSmartcard If the user only has a Smartcard and does not know their windows password, utilize this switch to enable prompting for Smartcard credentials when explorer.exe restarts. However, they will need to specify a credential object to start a new process to check the token changes. .INPUTS System.Management.Automation.PSCredential, System.Management.Automation.SwitchParameter .OUTPUTS None .EXAMPLE Update-TokenGroupMembership -Credential (Get-Credential) Updates the group membership for the current user. .EXAMPLE Update-TokenGroupMembership -UseSmartcard Updates the groups membership for the current user, but prompts for Smartcard credentials to restart explorer.exe. Because the Credential parameter was not specified, the changes in the group membership in the token are not displayed. .NOTES AUTHOR: Michael Haken LAST UPDATED: 2/27/2016 #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [PSCredential]$Credential = [PSCredential]::Empty, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [switch]$UseSmartcard = $false ) Begin { if ($Credential -eq $null) { $Credential = [PSCredential]::Empty } } Process { $CurrentGroups = @() [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value | ForEach-Object { if ($_ -ne $null -and $_ -ne "") { $CurrentGroups += $_ } } #The ampersand signifies to execute the following scriptblock and treat each value as a parameter & "$env:SYSTEMROOT\system32\klist.exe" purge | Out-Null & "$env:SYSTEMROOT\system32\klist.exe" tgt | Out-Null & "$env:SYSTEMROOT\system32\taskkill.exe" "/F" "/IM" "explorer.exe" | Out-Null if (!$UseSmartcard) { & "$env:SYSTEMROOT\system32\runas.exe" "/user:$env:USERDOMAIN\$env:USERNAME" "explorer.exe" } else { & "$env:SYSTEMROOT\system32\runas.exe" "/user:$env:USERDOMAIN\$env:USERNAME" "/smartcard" "explorer.exe" } if ($Credential -ne [PSCredential]::Empty) { $Command = @" `$Groups = whoami /groups /FO CSV | ConvertFrom-Csv | Select-Object -ExpandProperty "Group Name" `$Groups2 = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value `$Groups += `$Groups2 `$Groups | Select-Object -Unique "@ #Encode the command because it does not like the Open and Close parentheses $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Command) $EncodedCommand = [Convert]::ToBase64String($Bytes) #Because Start-Process does not capture the standard out as part of the object, it can only be redirected to a file #Use the .NET object in order to capture the standard out without writing to file $ProcessInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo $ProcessInfo.FileName = "$env:SYSTEMROOT\System32\windowspowershell\v1.0\powershell.exe" $ProcessInfo.CreateNoWindow = $true $ProcessInfo.Verb = "runas" $ProcessInfo.RedirectStandardError = $true $ProcessInfo.RedirectStandardOutput = $true $ProcessInfo.UseShellExecute = $false $ProcessInfo.LoadUserProfile = $false $ProcessInfo.Domain = $Credential.UserName.Substring(0, $Credential.UserName.IndexOf("\")) $ProcessInfo.UserName = $Credential.UserName.Substring($Credential.UserName.IndexOf("\") + 1) $ProcessInfo.Password = $Credential.Password $ProcessInfo.Arguments = "-EncodedCommand $EncodedCommand" $Process = New-Object -TypeName System.Diagnostics.Process $Process.StartInfo = $ProcessInfo $Process.Start() | Out-Null $Process.WaitForExit() if ($Process.ExitCode -eq 0) { $NewGroups = @() $Process.StandardOutput.ReadToEnd().Split("`r`n") | ForEach-Object { if ($_ -ne $null -and $_ -ne [System.String]::Empty) { $NewGroups += $_ } } Write-Host "" foreach ($OldGroup in $CurrentGroups) { if (!$NewGroups.Contains($OldGroup) -and $OldGroup -ne "CONSOLE LOGON") { Write-Host "REMOVED : $OldGroup" -ForegroundColor Red } } Write-Host "" foreach ($NewGroup in $NewGroups) { if (!($CurrentGroups.Contains($NewGroup)) -and !$NewGroup.StartsWith("Mandatory Label\")) { Write-Host "ADDED : $NewGroup" -ForegroundColor Green } } } else { throw $Process.StandardError.ReadToEnd() } } } End {} } Function Start-WithImpersonation { <# .SYNOPSIS Runs a scriptblock while impersonating another user. .DESCRIPTION The user enters credentials and a scriptblock to execute. The scriptblock is executed while impersonating the entered credentials. .PARAMETER Credential The credentials that will be impersonated. .PARAMETER Scriptblock The scriptblock that will be executed with the impersonated credentials .PARAMETER LogonType The type of logon that will be used for impersonation. This parameter defaults to "INTERACTIVE" .INPUTS System.Management.Automation.Scriptblock, System.String, System.Management.Automation.PSCredential .OUTPUTS System.Management.Automation.PSObject The object returned is whatever the scriptblock from the input returns. .EXAMPLE Start-WithImpersonation -Credential (Get-Credential) -Scriptblock {Get-Service} -LogonType INTERACTIVE Runs the get-service command using the impersonated credentials received from the Credential parameter. .NOTES AUTHOR: Michael Haken LAST UPDATED: 2/27/2016 #> [CmdletBinding()] Param( [Parameter(Position=2,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [PSCredential]$Credential, [Parameter(Position=0,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [Scriptblock]$Scriptblock, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [ValidateSet("INTERACTIVE","NETWORK","NETWORK_CLEARTEXT","NEW_CREDENTIALS","SERVICE","BATCH","UNLOCK")] [string]$LogonType = "INTERACTIVE" ) Begin {} Process { $Job = Start-Job -ArgumentList @($Credential, $Scriptblock) -ScriptBlock { Add-Type -AssemblyName System.ComponentModel [PSCredential]$Credential = $args[0] [Scriptblock]$Scriptblock = [Scriptblock]::Create($args[1]) $Signatures = @" [DllImport( "advapi32.dll" )] public static extern bool LogonUser( String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken ); "@ $AdvApi32 = Add-Type -MemberDefinition $Signatures -Name "AdvApi32" -Namespace "PsInvoke.NativeMethods" -PassThru $CloseHandleSignature = @" [DllImport( "kernel32.dll", CharSet = CharSet.Auto )] public static extern bool CloseHandle( IntPtr handle ); "@ $Kernel32 = Add-Type -MemberDefinition $CloseHandleSignature -Name "Kernel32" -Namespace "PsInvoke.NativeMethods" -PassThru try { #Logon Types [int]$LOGON32_LOGON_INTERACTIVE = 2 [int]$LOGON32_LOGON_NETWORK = 3 [int]$LOGON32_LOGON_BATCH = 4 [int]$LOGON32_LOGON_SERVICE = 5 [int]$LOGON32_LOGON_UNLOCK = 7 [int]$LOGON32_LOGON_NETWORK_CLEARTEXT = 8 #Win2K or higher [int]$LOGON32_LOGON_NEW_CREDENTIALS = 9 #Win2K or higher #Logon Providers [int]$LOGON32_PROVIDER_DEFAULT = 0 [int]$LOGON32_PROVIDER_WINNT35 = 1 [int]$LOGON32_PROVIDER_WINNT40 = 2 [int]$LOGON32_PROVIDER_WINNT50 = 3 [int]$Logon [int]$Provider = $LOGON32_PROVIDER_DEFAULT switch ($LogonType) { "INTERACTIVE" { $Logon = $LOGON32_LOGON_INTERACTIVE break } "NETWORK" { $Logon = $LOGON32_LOGON_NETWORK break } "NETWORK_CLEARTEXT" { $Logon = $LOGON32_LOGON_NETWORK_CLEARTEXT break } "NEW_CREDENTIALS" { $Logon = $LOGON32_LOGON_NEW_CREDENTIALS $Provider = $LOGON32_PROVIDER_WINNT50 break } "SERVICE" { $Logon = $LOGON32_LOGON_SERVICE break } "BATCH" { $Logon = $LOGON32_LOGON_BATCH break } "UNLOCK" { $Logon = $LOGON32_LOGON_UNLOCK break } default { $Logon = $LOGON32_LOGON_INTERACTIVE break } } $TokenHandle = [IntPtr]::Zero if ($Credential.UserName.Contains("\")) { $UserName = $Credential.UserName.Substring($Credential.UserName.IndexOf("\") + 1) $Domain = $Credential.UserName.Substring(0, $Credential.UserName.IndexOf("\")) } else { $UserName = $Credential.UserName $Domain = $env:COMPUTERNAME } $Success = $AdvApi32::LogonUser($UserName, $Domain, $Credential.Password, $Logon, $Provider, [Ref]$TokenHandle) if (!$Success) { $ReturnValue = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() $Message = (New-Object -TypeName System.ComponentModel.Win32Exception($ReturnValue)).Message Write-Warning "LogonUser was unsuccessful. Error code: $ReturnValue - $Message" return } $NewIdentity = New-Object System.Security.Principal.WindowsIdentity($TokenHandle) $IdentityName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name Write-Host "Current Identity: $IdentityName" $Context = $NewIdentity.Impersonate() $IdentityName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name Write-Host "Impersonating: $IdentityName" Write-Host "Executing custom script" $Result = & $Scriptblock return $Result } catch [System.Exception] { Write-Host $_.Exception.ToString() } finally { if ($Context -ne $null) { $Context.Undo() } if ($TokenHandle -ne [System.IntPtr]::Zero) { $Kernel32::CloseHandle($TokenHandle) | Out-Null } } } } End { Wait-Job -Job $Job | Out-Null return (Receive-Job -Job $Job) } } Function Enable-WinRM { <# .SYNOPSIS Enables WinRM on a host. .DESCRIPTION The function enables PowerShell remoting, sets WinRM to automatically start, adds the provided to trusted hosts (which defaults to all hosts), and creates the firewall rule to allow inbound WinRM. .PARAMETER TrustedHosts The hosts that are trusted for remote mamangement. This can be an IP range, a subnet, or a wildcard. This defaults to all hosts: "*". .INPUTS System.String The value can be piped to Enable-WinRM. .OUTPUTS None .EXAMPLE Enable-WinRM -TrustedHosts "192.168.100.0-192.168.100.255" .NOTES This command should be run with administrative credentials AUTHOR: Michael Haken LAST UPDATED: 2/27/2016 #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [string]$TrustedHosts = "*" ) Begin { if (!(Test-IsLocalAdmin)) { throw "This cmdlet must be run with admin credentials." } } Process { Set-NetConnectionProfile -NetworkCategory Private Enable-PSRemoting -Force Set-Service -Name WinRM -StartupType Automatic Start-Service -Name WinRM Set-Item WSMan:\localhost\Client\TrustedHosts -Value $TrustedHosts -Force Restart-Service -Name WinRM New-NetFirewallRule -Name "Allow_WinRM" -DisplayName "Windows Remote Management (WinRM)" -Description "Allows WinRM ports 5985-5986 inbound." -Protocol TCP -LocalPort 5985,5986 -Enabled True -Action Allow -Profile Any Write-Host "WinRM Enabled" -ForegroundColor Green } End {} } Function New-EmptyTestFile { <# .SYNOPSIS Creates an empty file of the specified size. .DESCRIPTION Creates a file of the provided size in the provided location to test against. .PARAMETER FilePath The location the file should be created. This defaults to the user's desktop with a filename of Test.txt. .PARAMETER Size The size of the file to be created. Can be specified in bytes or with units, such as 64GB or 32MB. .INPUTS System.String, System.UInt64 .OUTPUTS None .EXAMPLE New-EmptyTestFile -FilePath "c:\test.cab" -Size 15MB Creates an empty 15MB cab file at c:\test.cab. .NOTES AUTHOR: Michael Haken LAST UPDATED: 2/27/2016 .FUNCTIONALITY This cmdlet is used to create empty test files to perform tests on. #> [CmdletBinding()] Param( [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [string]$FilePath = "$env:USERPROFILE\Desktop\Test.txt", [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [UInt64]$Size ) Begin {} Process { $Writer = [System.IO.File]::Create($FilePath) $Bytes = New-Object Byte[] ($Size) $Writer.Write($Bytes, 0, $Bytes.Length) $Writer.Close() Write-Host "$Size file created at $FilePath" } End {} } Function Start-PortScan { <# .SYNOPSIS Conducts a port scan on the selected computer. .DESCRIPTION Tries to connect to common ports on a targetted system and reports back the port status of each. Each connection is scheduled as a job; the function waits for all jobs to exit the running status before returning scan information. .PARAMETER ComputerName The name of the computer to scan. The parameter defaults to "localhost" .INPUTS System.String The input can be piped to Start-PortScan .OUTPUTS PSCustomObject[] Each custom object has a property of Service, Port, and Status. Status is either Open or Closed. .EXAMPLE Start-PortScan -ComputerName remotecomputer.net Returns an array of open and closed ports on remotecomputer.net .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to conduct a security scan of ports on a computer. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [string]$ComputerName = "localhost" ) Begin { $Ports = $script:Ports | Sort-Object -Property Port } Process { $Jobs = @() $i = 1 foreach ($Item in $Ports) { Write-Progress -Activity "Running Port Scan" -Status "Scanning Port $($Item.Port) $($Item.Service)" -PercentComplete (($i++ / $Ports.Count) * 100) $Jobs += Start-Job -ArgumentList @($ComputerName,$Item) -ScriptBlock { $ComputerName = $args[0] $Service = $args[1].Service $Port = $args[1].Port $Socket = New-Object Net.Sockets.TcpClient $ErrorActionPreference = 'SilentlyContinue' $Socket.Connect($ComputerName, $Port) $ErrorActionPreference = 'Continue' if ($Socket.Connected) { $Socket.Close() return [PSCustomObject]@{"Service"="$Service";"Port"=$Port;"Status"="Open"} } else { return [PSCustomObject]@{"Service"="$Service";"Port"=$Port;"Status"="Closed"} } } } } End { Write-Progress -Completed -Activity "Running Port Scan" Write-Host "Waiting for jobs to complete..." $RunningJobs = @() $RunningJobs = Get-Job | Where-Object {$_.Id -in ($Jobs | Select-Object -ExpandProperty Id)} while (($RunningJobs | Where {$_.State -eq "Running"}).Length -gt 0) { $Completed = ($RunningJobs | Where {$_.State -eq "Completed"}).Length Write-Progress -Activity "Completing Jobs" -Status ("Waiting for connections to complete: " + (($Completed / $RunningJobs.Length) * 100) + "% Complete") -PercentComplete (($Completed / $RunningJobs.Length) * 100) Start-Sleep -Milliseconds 500 } Wait-Job -Job $Jobs | Out-Null $Data = @() Receive-Job -Job $Jobs | ForEach-Object { $Data += $_ } Remove-Job -Job $Jobs Write-Output ($Data | Select-Object -Property * -ExcludeProperty RunspaceId) } } Function Set-NetAdapterToDHCP { <# .SYNOPSIS Changes an adapter from a static IP address to DHCP. .DESCRIPTION Gets net adapter configurations from WMI and filters the results based on either matching thet interface index or net adaper name/description. Then the function enables DHCP on the matching network adapter. The adapter must be IP Enabled and currently not be configured to use DHCP. .PARAMETER InterfaceIndex The interface index to enable DHCP on. .PARAMETER InterfaceName The Network Adapter Description value to match against and enale DHCP on. .PARAMETER InputObject A MSFT_NetAdapter CIM Instance. .PARAMETER PassThru Passes the discovered WMI object back. .INPUTS System.Int32 System.String Microsoft.Management.Infrastructure.CimInstance All of the parameters can be piped to Set-NetAdapterToDHCP .OUTPUTS Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/NetAdapter The Microsoft.Management.Infrastructure.CimInstance object is a wrapper class that displays Windows Management Instrumentation (WMI) objects. The path after the pound sign (#) provides the namespace and class name for the underlying WMI object. This is only returned if the PassThru parameter is specified. .EXAMPLE Set-NetAdapterToDHCP -InterfaceIndex 3 Changes the interface with an Index 3 to DHCP. .EXAMPLE Set-NetAdapterToDHCP -InterfaceName "Hyper-V Virtual Ethernet Adapter #1" Changes the interface with a description of Hyper-V Virtual Ethernet Adapter #1 to use DHCP .EXAMPLE Get-NetAdapter -InterfaceIndex 3 | Set-NetAdapterToDHCP Gets the network adapter with index 3 and pipes it to Set-NetAdapterToDHCP in order to enable DHCP on the interface. .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to set network adapters to DHCP easily. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropetyName=$true,ParameterSetName="Index",Mandatory=$true)] [int]$InterfaceIndex, [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="Name",Mandatory=$true)] [string]$InterfaceName, [Parameter(Position=0,ValueFromPipeline=$true,ParameterSetName="InputObject",Mandatory=$true)] [ValidateScript({$_.CimClass.CimClassName -eq "MSFT_NetAdapter"})] [Microsoft.Management.Infrastructure.CimInstance]$InputObject, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [switch]$PassThru ) Begin { switch ($PSCmdlet.ParameterSetName) { "Index" { $Filter = ("IPEnabled = $true AND DHCPEnabled = $false AND Index = $InterfaceIndex") break } "Name" { $Filter = ("IPEnabled = $true AND DHCPEnabled = $false AND Description = `"$InterfaceName`"") break } "InputObject" { $Filter = ("IPEnabled = $true AND DHCPEnabled = $false AND Index = $($InputObject.ifIndex)") break } } } Process { $wmi = Get-WmiObject -Class win32_networkadapterconfiguration -Filter $Filter $wmi.EnableDHCP() } End { Write-Host "DHCP Enabled on $($wmi.Description)" if ($PassThru) { Write-Output (Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter $Filter) } } } Function Remove-JavaInstallations { <# .SYNOPSIS Removes old versions of Java JRE or does a complete removal. .DESCRIPTION The function identifies well-known directories, registry keys, and registry key entries. Then based on the type of cleanup and architecture targetted, it removes those files, directories, registry keys, and registry key entries. During a cleanup, the current version of Java is specified so that it is not removed. .PARAMETER MajorVersion The current major version of Java, for example 7 or 8. .PARAMETER MinorVersion The current minor version of Java, this is almost always 0. .PARAMETER ReleaseVersion The current release version of Java, this is the update number, for example 15, 45, or 73. .PARAMETER PluginVersion The major version of the Java web plugin, for example 10 or 11. .PARAMETER Architecture The architecture to target, either x86, x64, or All. This defaults to All. .PARAMETER FullRemoval Specifies that a full removal of Java should be conducted. .INPUTS System.Int32, System.Int32, System.Int32, System.In32, System.String System.Management.Automation.SwitchParameter All valid parameters can be piped to Remove-JavaInstallations by property name. .OUTPUTS None .EXAMPLE Remove-JavaInstallations -MajorVersion 8 -ReleaseVersion 15 -PluginVersion 11 -Architecture All Removes all versions previous to JRE 8u15. .EXAMPLE Remove-JavaInstallations -MajorVersion 8 -ReleaseVersion 15 -PluginVersion 11 -Architecture x64 Removes all versions previous to JRE 8u15 that are x64 installations. .EXAMPLE Remove-JavaInstallations -FullRemoval Removes all versions of JRE from the system. .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to conduct complete removals of the Java JRE software. #> [CmdletBinding(DefaultParameterSetName="Cleanup")] Param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$true,ParameterSetName="Cleanup",Mandatory=$true)] [int]$MajorVersion, [Parameter(Position=1,ValueFromPipelineByPropteryName=$true,ParameterSetName="Cleanup")] [int]$MinorVersion = 0, [Parameter(Position=2,ValueFromPipelineByPropertyName=$true,ParameterSetName="Cleanup",Mandatory=$true)] [int]$ReleaseVersion, [Parameter(Position=3,ValueFromPipelineByPropertyName=$true,ParameterSetName="Cleanup",Mandatory=$true)] [int]$PluginVersion, [Parameter(Position=4,ValueFromPipelineByPropertyName=$true,ParameterSetname="Cleanup")] [ValidateSet("x86,x64,All")] [string]$Architecture = "All", [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="Removal",Mandatory=$true)] [switch]$FullRemoval ) Begin { if ((Get-PSDrive | Where-Object {$_.Root -eq "HKEY_CLASSES_ROOT"})) { Get-PSDrive | Where-Object {$_.Root -eq "HKEY_CLASSES_ROOT"} | Remove-PSDrive } New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null #These keys are used to cleanup HKLM:\\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\UNINSTALL $64BIT_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8641*FF*" # 26A24AE4-039D-4CA4-87B4-2F46417015FF - Java 7u15 x64 $32BIT_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8321*FF*" $GENERIC_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8*1*FF*" #These keys are used to cleanup HKCR:\\Installer\Products $64BIT_HKCR_INSTALLER_PRODUCTS_KEY = "*4EA42A62D9304AC4784BF23812*FF*" # 4EA42A62D9304AC4784BF238120683FF - Java 6u38 x86 $32BIT_HKCR_INSTALLER_PRODUCTS_KEY = "*4EA42A62D9304AC4784BF26814*FF*" $GENERIC_HKCR_INSTALLER_PRODUCTS_KEY = "*4EA42A62D9304AC4784BF2*81*FF*" #Java AutoUpdate $HKCR_JAVA_AUTOUPDATER = "F60730A4A66673047777F5728467D401" $HKLM_JAVA_AUTOUPDATER = "F60730A4A66673047777F5728467D401" #Build the software version [string]$LONG_PUNCTUATED_VERSION = "" [string]$NON_PUNCTUATED_VERSION = "" [string]$SHORT_VERSION = "1." + $MajorVersion # 1.7 [string]$BASE_VERSION = "1." + $MajorVersion + "." + $MinorVersion + ".0" # 1.7.0 [string]$FULL_VERSION = "" [string]$PLUGIN_VERSION = $PluginVersion.ToString() $Temp = $ReleaseVersion.ToString().ToCharArray() [System.Array]::Reverse($Temp) [string]$REVERSE_RELEASE = $Temp.ToString() $Temp = ($MajorVersion.ToString() + $MinorVersion.ToString()).ToCharArray() [System.Array]::Reverse($Temp) [string]$REVERSE_VERSION = $Temp.ToString() #Make the current release string two characters long if ($ReleaseVersion.ToString().Length -eq 1) { $ReleaseVersion = "0" + $ReleaseVersion.ToString() } switch ($ReleaseVersion) { "00" { $FULL_VERSION = "1." + $MajorVersion + (& if($MinorVersion -gt 0) {"." + $MinorVersion } else {""}) # 1.7 or 1.7.1 $NON_PUNCTUATED_VERSION = "1" + $MajorVersion + $MinorVersion # 170 $LONG_PUNCTUATED_VERSION = "1." + $MajorVersion + "." + $MinorVersion # 1.7.0 break } default { $FULL_VERSION = "1." + $MajorVersion + "." + $MinorVersion + "_" + $ReleaseVersion # 1.7.0_15 $NON_PUNCTUATED_VERSION = "1" + $MajorVersion + $MinorVersion + "_" + $ReleaseVersion # 170_15 $LONG_PUNCTUATED_VERSION = $FULL_VERSION # 1.7.0_15 break } } $REVERSE_VERSION_REGISTRY_KEY = $REVERSE_VERSION + $REVERSE_RELEASE + "FF*" $NON_PUNCTUATED_REGISTRY_KEY = $MajorVersion.ToString() + $MinorVersion.ToString() + $ReleaseVersion.ToString() + "FF*" #Create the registry strings to match Java in HKCR and HKLM $UNINSTALL_REGISTRY_KEY = "" $HKCR_REGISTRY_KEY = "" switch ($Architecture) { # HKLM:\SOFTWARE\Wow6432Node\ "x86" { $UNINSTALL_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8321" + $NON_PUNCTUATED_REGISTRY_KEY # 3217000 or 3217015 $HKCR_REGISTRY_KEY = "*4EA42A62D9304AC4784BF23812" + $REVERSE_VERSION_REGISTRY_KEY + "*" #38120751 break } # HKLM:\SOFTWARE\ "x64" { $UNINSTALL_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8641" + $NON_PUNCTUATED_REGISTRY_KEY # 6417000 or 6417015 $HKCR_REGISTRY_KEY = "*4EA42A62D9304AC4784BF26814" + $REVERSE_VERSION_REGISTRY_KEY +"*" #68140751 break } "All" { $UNINSTALL_REGISTRY_KEY = "*26A24AE4-039D-4CA4-87B4-2F8*1" + $NON_PUNCTUATED_REGISTRY_KEY # *17000 or *17015 $HKCR_REGISTRY_KEY = "*4EA42A62D9304AC4784BF2*81*" + $REVERSE_VERSION_REGISTRY_KEY + "*" #*81*0751 break } } $FilePaths = @() $UserProfiles = Get-ChildItem -Path "$env:SystemDrive\Users" Write-Host "[INFO] Getting All User Profiles" -ForegroundColor Green foreach ($Profile in $UserProfiles) { $FilePaths += "$env:SystemDrive\Users\" + $Profile.Name + "\AppData\LocalLow\Sun" $FilePaths += "$env:SystemDrive\Users\" + $Profile.Name + "\AppData\Local\Temp\java_install_reg.log" $FilePaths += "$env:SystemDrive\Users\" + $Profile.Name + "\AppData\Local\Temp\java_install.log" } Write-Host "[INFO] Adding file paths" -ForegroundColor Green $FilePaths += "$env:SYSTEMROOT\Temp\java_install.log" $FilePaths += "$env:SYSTEMROOT\Temp\java_install_reg.log" if ($PSCmdlet.ParameterSetName -eq "Removal") { $FilePaths += "$env:ALLUSERSPROFILE\Sun" if ($Architecture -eq "x86" -or $Architecture -eq "All") { $FilePaths += "$env:SystemDrive\Program Files (x86)\Java" $FilePaths += "$env:SYSTEMROOT\System32\java.exe" $FilePaths += "$env:SYSTEMROOT\System32\javaw.exe" $FilePaths += "$env:SYSTEMROOT\System32\javaws.exe" } if ($Architecture -eq "x64" -or $Architecture -eq "All") { $FilePaths += "$env:SystemDrive\Program Files\Java" $FilePaths += "$env:SYSTEMROOT\SysWow64\java.exe" $FilePaths += "$env:SYSTEMROOT\SysWow64\javaw.exe" $FilePaths += "$env:SYSTEMROOT\SysWow64\javaws.exe" } } if ($PSCmdlet.ParameterSetName -eq "Cleanup") { if ($Architecture -eq "x86" -or $Architecture -eq "All") { $FilePaths += @(Get-ChildItem "$env:SystemDrive\program files (x86)\Java" | Where-Object {$_.name -notlike "jre" + $MajorVersion}) } if ($Architecture -eq "x64" -or $Architecture -eq "All") { $FilePaths += @(Get-ChildItem "$env:SystemDrive\program files\Java" | Where-Object {$_.name -notlike "jre" + $MajorVersion}) } } Write-Host "[INFO] Getting Registry Keys" -ForegroundColor Green $ErrorActionPreference = "SilentlyContinue" $RegistryKeys = @() $RegistryKeys += 'HKCU:\Software\AppDataLow\Software\Javasoft' $RegistryKeys += 'HKCU:\Software\Javasoft\Java Update' $RegistryKeys += 'HKCU:\Software\Microsoft\Protected Storage System Provider\S-1-5-21-1292428093-1275210071-839522115-1003\Data' $RegistryKeys += 'HKLM:\SOFTWARE\MozillaPlugins\@java.com' $RegistryKeys += 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0357E4991DA5FF14F9615B3312070F06' $RegistryKeys += 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0357E4991DA5FF14F9615B3512070F06' $RegistryKeys += 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\4EA42A62D9304AC4784BF238120652FF' $RegistryKeys += 'HKLM:\SOFTWARE\Classes\JavaSoft.JavaBeansBridge' $RegistryKeys += 'HKLM:\SOFTWARE\Classes\JavaSoft.JavaBeansBridge.1' $RegistryKeys += 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0357E4991DA5FF14F9615B3312070F07' $RegistryKeys += 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0357E4991DA5FF14F9615B3312070F08' $RegistryKeys += 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0357E4991DA5FF14F9615B3312070F09' $RegistryKeys += 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\4EA42A62D9304AC4784BF2381206220F' if ($PSCmdlet.ParameterSetName -eq "Cleanup") { $RegistryKeys += @((Get-ChildItem -Path "HKCR:\" | Where-Object {($_.Name -like "*JavaPlugin*") -and ($_.Name -notlike "*JavaPlugin." + $NON_PUNCTUATED_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCR:\" | Where-Object {($_.name -like "*JavaWebStart.isInstalled.*") -and ($_.Name -notlike "*JavaWebStart.isInstalled." + $BASE_VERSION +"*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCR:\Installer\Products" | Where-Object {($_.Name -like $GENERIC_HKCR_INSTALLER_PRODUCTS_KEY) -and ($_.Name -notlike $HKCR_REGISTRY_KEY)}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCU:\Software\JavaSoft\Java Runtime Environment" | Where-Object {($_.Name -notlike "*" + $FULL_VERSION +"*") -and ($_.name -notlike "*" + $LONG_PUNCTUATED_VERSION +"*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCU:\Software\JavaSoft\Java2D" | Where-Object {($_.Name -notlike "*" + $LONG_PUNCTUATED_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCU:\Software\Classes" | Where-Object {($_.Name -like "*JavaPlugin*") -and ($_.Name -notlike "*JavaPlugin." + $NON_PUNCTUATED_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Products" | Where-Object {($_.Name -like $GENERIC_HKCR_INSTALLER_PRODUCTS_KEY) -and ($_.Name -notlike $HKCR_REGISTRY_KEY) }).PSPath) if ($Architecture -eq "x86" -or $Architecture -eq "All") { $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Features\" | Where-Object {$_.Name -like $32BIT_REGISTRY_KEY}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\wow6432node\Microsoft\Windows\CurrentVersion\Uninstall\" | Where-Object {($_.Name -like $32BIT_REGISTRY_KEY) -and ($_.Name -notlike $UNINSTALL_REGISTRY_KEY)}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {($_.Name -notlike "*JavaPlugin." + $NON_PUNCTUATED_VERSION + "*") -and ($_.Name -like "*JavaPlugin*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {($_.Name -notlike "*JavaWebStart.isInstalled." + $BASE_VERSION + "*") -and ($_.Name -like "*JavaWebStart.isInstalled.*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environemt" | Where-Object {($_.Name -notlike "*" + $FULL_VERSION + "*") -and ($_.Name -notlike "*" + $SHORT_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Wow6432Node\JavaSoft\Java Plug-in" | Where-Object {($_.Name -notlike "*" + $PLUGIN_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Wow6432Node\JavaSoft\Java Web Start" | Where-Object {($_.Name -notlike "*" + $FULL_VERSION +"*") -and ($_.name -notlike "*" + $SHORT_VERSION +"*")}).PSPath) } if ($Architecture -eq "x64" -or $Architecture -eq "All") { $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Features\" | Where-Object {$_.Name -like $64BIT_REGISTRY_KEY}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" | Where-Object {($_.Name -like $64BIT_REGISTRY_KEY) -and ($_.Name -notlike $UNINSTALL_REGISTRY_KEY)}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {($_.Name -notlike "*JavaWebStart.isInstalled." + $BASE_VERSION + "*") -and ($_.Name -like "*JavaWebStart.isInstalled.*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {($_.Name -notlike "*JavaPlugin." + $NON_PUNCTUATED_VERSION + "*") -and ($_.Name -like "*JavaPlugin*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\JavaSoft\Java Runtime Environemt" | Where-Object {($_.Name -notlike "*" + $FULL_VERSION + "*") -and ($_.Name -notlike "*" + $SHORT_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\JavaSoft\Java Plug-in" | Where-Object {($_.Name -notlike "*" + $PLUGIN_VERSION + "*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\JavaSoft\Java Web Start" | Where-Object {($_.Name -notlike "*" + $FULL_VERSION +"*") -and ($_.name -notlike "*" + $SHORT_VERSION +"*")}).PSPath) } } if ($PSCmdlet.ParameterSetName -eq "Removal") { $RegistryKeys += "HKLM:\SOFTWARE\Classes\jarfile" $RegistryKeys += @((Get-ChildItem -Path "HKCR:\" | Where-Object {($_.Name -like "*JavaPlugin*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCR:\" | Where-Object {($_.Name -like "*JavaScript*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCR:\" | Where-Object {($_.Name -like "*JavaWebStart*")}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKCR:\Installer\Products" | Where-Object {($_.Name -like $GENERIC_HKCR_INSTALLER_PRODUCTS_KEY)}).PSPath) $RegistryKeys += "HKCU:\Software\JavaSoft\Java Runtime Environment" $RegistryKeys += "HKCU:\Software\JavaSoft\Java2D" $RegistryKeys += "HKCR:\Installer\Products\$HKCR_JAVA_AUTOUPDATER" if ($Architecture -eq "x86" -or $Architecture -eq "All") { $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Features\" | Where-Object {$_.Name -like $32BIT_REGISTRY_KEY -or $_.Name -like $HKLM_JAVA_AUTOUPDATER}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\wow6432node\Microsoft\Windows\CurrentVersion\Uninstall\" | Where-Object {$_.Name -like $32BIT_REGISTRY_KEY}).PSPath) $RegistryKeys += "HKLM:\SOFTWARE\Wow6432Node\JavaSoft" $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {$_.Name -like "*JavaWebStart*"}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {$_.Name -like "*JavaPlugin*"}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Products" | Where-Object {$_.Name -like $32BIT_HKCR_INSTALLER_PRODUCTS_KEY}).PSPath) $RegistryKeys += "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe" } if ($Architecture -eq "x64" -or $Architecture -eq "All") { $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Features\" | Where-Object {$_.Name -like $64BIT_REGISTRY_KEY -or $_.Name -like $HKLM_JAVA_AUTOUPDATER}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" | Where-Object {$_.Name -like $64BIT_REGISTRY_KEY -or $_.Name -like $HKLM_JAVA_AUTOUPDATER}).PSPath) $RegistryKeys += "HKLM:\SOFTWARE\JavaSoft" $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes" | Where-Object {$_.Name -like "*JavaWebStart*"}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\Software\Classes" | Where-Object {$_.Name -like "*JavaPlugin*"}).PSPath) $RegistryKeys += @((Get-ChildItem -Path "HKLM:\SOFTWARE\Classes\Installer\Products" | Where-Object {$_.Name -like $64BIT_HKCR_INSTALLER_PRODUCTS_KEY}).PSPath) $RegistryKeys += "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe" } } Write-Host "[INFO] Getting Registry Key Properties" -ForegroundColor Green $RegistryKeyProperties = @() $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\System\ControlSet001\Control\Session Manager\Environment") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\System\ControlSet002\Control\Session Manager\Environment") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\System\ControlSet003\Control\Session Manager\Environment") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\System\CurrentControlSet\Control\Session Manager\Environment") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Classes\jarfile\shell\open\command") $EntriesToKeep = @() if ($PSCmdlet.ParameterSetName -eq "Cleanup") { switch ($Architecture) { "x86" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $NOT_LIKE_1 = "$env:SystemDrive\program files (x86)\*\jre" + $majorbuild + "\*" $NOT_LIKE_2 = "$env:SystemDrive\program files (x86)\*\jre" + $shortversion + "\*" $LIKE = "$env:SystemDrive\program files (x86)\*\jre*" break } "x64" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $NOT_LIKE_1 = "$env:SystemDrive\program files\*\jre" + $majorbuild + "\*" $NOT_LIKE_2 = "$env:SystemDrive\program files\*\jre" + $shortversion + "\*" $LIKE = "$env:SystemDrive\program files\*\jre*" break } "All" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $NOT_LIKE_1 = "$env:SystemDrive\program files*\*\jre" + $majorbuild + "\*" $NOT_LIKE_2 = "$env:SystemDrive\program files*\*\jre" + $shortversion + "\*" $LIKE = "$env:SystemDrive\program files*\*\jre*" break } } foreach ($Property in $RegistryKeyProperties) { if ((($Property.Property -like $LIKE) -and ($Property.Property -notlike $NOT_LIKE_1) -and ($Property.Property -notlike $NOT_LIKE_2)) -or (($Property.Value -like $LIKE) -and ($Property.Value -notlike $NOT_LIKE_1) -and ($Property.Value -notlike $NOT_LIKE_2))) { $EntriesToKeep += $Property } } } if ($PSCmdlet.ParameterSetName -eq "Removal") { switch ($Architecture) { "x86" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $LIKE = "$env:SystemDrive\program files (x86)\*\jre*" break } "x64" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $LIKE = "$env:SystemDrive\program files\*\jre*" break } "All" { $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $RegistryKeyProperties += @(Get-RegistryKeyEntries -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\javaws.exe") $LIKE = "$env:SystemDrive\program files*\*\jre*" break } } foreach ($Property in $RegistryKeyProperties) { if (($Property.Property -like $LIKE) -or ($Property.Value -like $LIKE)) { $EntriesToKepp += $Property } } } $RegistryKeyProperties = $EntriesToKeep $ErrorActionPreference = "Continue" } Process { [int]$DirectoryCount = 0 [int]$RegistryKeyCount = 0 [int]$RegistryEntryCount = 0 Write-Host "[INFO] Removing Directories and Files" -ForegroundColor Yellow foreach ($Item in $FilePaths) { if (Test-Path -Path $Item) { $DirectoryCount++ Remove-Item -Path $Item -Force -Recurse } } Write-Host "[INFO] Removing Registry Keys" -ForegroundColor Yellow foreach ($Item in $RegistryKeys) { if (Test-Path -Path $Item) { $RegistryKeyCount++ Remove-Item -Path $Item -Force -Recurse } } Write-Host "[INFO] Removing Registry Key Entries" -ForegroundColor Yellow foreach ($Item in $RegistryKeyProperties) { if (Test-Path -Path $Item.Path) { $RegistryEntryCount++ Remove-ItemProperty -Path $Item.Path -Name $Item.Property -Force } } } End { Write-Host "[INFO] Java cleanup removed $DirectoryCount directories, $RegistryKeyCount registry keys, and $RegistryEntryCount registry key entries." -ForegroundColor Yellow } } Function Get-RegistryKeyEntries { <# .SYNOPSIS Gets all of the properties and their values associated with a registry key. .DESCRIPTION The Get-RegistryKeyEntries cmdlet gets each entry and its value for a specified registry key. .PARAMETER Path The registry key path in the format that PowerShell can process, such as HKLM:\Software\Microsoft or Registry::HKEY_LOCAL_MACHINE\Software\Microsoft .INPUTS System.String You can pipe a registry path to Get-RegistryKeyEntries. .OUTPUTS System.Management.Automation.PSCustomObject[] .EXAMPLE Get-RegistryEntries -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall Gets all of the entries associated with the registry key. It does not get any information about subkeys. .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to supplement the Get-ItemProperty cmdlet to get the values for every entry in a registry key. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [ValidateScript({Test-Path -Path $_})] [string]$Path ) Begin {} Process { Get-Item -Path $Path | Select-Object -ExpandProperty Property | ForEach-Object { Write-Output ([PSCustomObject]@{"Path"=$Path;"Property"="$_";"Value"=(Get-ItemProperty -Path $Path -Name $_ | Select-Object -ExpandProperty $_)}) } } End {} } Function Remove-AppxProvisionedPackageSet { <# .SYNOPSIS Removes the default App Store provisioned packages. .DESCRIPTION The Remove-AppxProvisionedPackageSet cmdlet removes the default provisioned packages. .PARAMETER Ignore An array of Provisioned Package names to ignore. The dynamic params will automatically populate accepted values. .INPUTS System.String[] You can pipe an array of Provisioned Package names to ignore removal of to Remove-AppxProvisionedPackageSet. .OUTPUTS None .EXAMPLE PS C:\>Remove-AppxProvisionedPackageSet This command removes all of the default provisioned packages. .EXAMPLE PS C:\>Remove-AppxProvisionedPackageSet -Ignore Microsoft.Bing,Microsoft.BingNews This command removes all of the default provisioned packages except Bing and BingNews. .NOTES The default packages removed by this command are included in the following array: @("Microsoft.Bing" , "Microsoft.BingFinance" , "Microsoft.BingMaps" , "Microsoft.BingNews",` "Microsoft.BingSports" , "Microsoft.BingTravel" , "Microsoft.BingWeather" , "Microsoft.Camera",` "microsoft.microsoftskydrive" , "Microsoft.Reader" , "microsoft.windowscommunicationsapps",` "microsoft.windowsphotos" , "Microsoft.XboxLIVEGames" , "Microsoft.ZuneMusic",` "Microsoft.ZuneVideo" , "Microsoft.Media.PlayReadyClient") AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to remove the default Appx Provisioned Packages. #> [CmdletBinding()] Param () DynamicParam { [System.Management.Automation.ParameterAttribute]$Attributes = New-Object -TypeName System.Management.Automation.ParameterAttribute $Attributes.ParameterSetName = "__AllParameterSets" $Attributes.Mandatory = $false $Attributes.Position = 0 $Attributes.ValueFromPipeline = $true $Attributes.ValueFromPipelineByPropertyName = $true $AttributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] $AttributeCollection.Add($Attributes) $Values = @("Microsoft.Bing" , "Microsoft.BingFinance" , "Microsoft.BingMaps" , "Microsoft.BingNews",` "Microsoft.BingSports" , "Microsoft.BingTravel" , "Microsoft.BingWeather" , "Microsoft.Camera",` "microsoft.microsoftskydrive" , "Microsoft.Reader" , "microsoft.windowscommunicationsapps",` "microsoft.windowsphotos" , "Microsoft.XboxLIVEGames" , "Microsoft.ZuneMusic",` "Microsoft.ZuneVideo" , "Microsoft.Media.PlayReadyClient") [System.Management.Automation.ValidateSetAttribute]$ValidateSet = New-Object -TypeName System.Management.Automation.ValidateSetAttribute($Values) $AttributeCollection.Add($ValidateSet) [System.Management.Automation.RuntimeDefinedParameter]$DynParam1 = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter("Ignore", [string[]], $AttributeCollection) [System.Management.Automation.RuntimeDefinedParameterDictionary]$ParamDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary $ParamDictionary.Add("Ignore", $DynParam1) return $ParamDictionary } Begin {} Process { foreach ($App in $Values) { if (!$PSBoundParameters.Ignore.Contains($App)) { $PackageFullName = (Get-AppxPackage $App).PackageFullName if ((Get-AppxPackage $App).PackageFullName) { Write-Host "Removing Package: $App" try { Remove-AppxProvisionedPackage -Online -Packagename $PackageFullName Remove-AppxPackage -Package $PackageFullName } catch [Exception] { Write-Warning $_.Exception.Message } } else { Write-Warning "Unable to find package: $App" } } } } End {} } Function Start-TaskSchedulerHistory { <# .SYNOPSIS Enables the Task Scheduler log history. .DESCRIPTION The Start-TaskSchedulerHistory cmdlet enables the windows event logs for the Task Scheduler. The command should be used to correct the issue of Scheduled Tasks' history showing as "Disabled" in Task Scheduler. .INPUTS None .OUTPUTS None .EXAMPLE PS C:\>Start-TaskSchedulerHistory This command starts the collection of scheduled task events. .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to turn on history for Scheduled Tasks. #> [CmdletBinding()] Param () Begin {} Process { $LogName = 'Microsoft-Windows-TaskScheduler/Operational' $EventLog = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $LogName $EventLog.IsEnabled = $true $EventLog.SaveChanges() } End{} } Function Start-KerberosTraceLog { <# .SYNOPSIS Starts a trace to troubleshoot Kerberos authentication issues. .DESCRIPTION The Start-KerberosTraceLog cmdlet starts a trace of logs and netsh to capture all Kerberos, NTLM, SSL, and Negotiation traffic. .PARAMETER Path Specify the directory to store the log files during the trace. This defaults to the module root. The directory is created if it does not already exist. .INPUTS System.String You can pipe a directory path string to Start-KerberosTraceLog. .OUTPUTS None .EXAMPLE PS C:\>Start-KerberosTraceLog This command starts the trace log and logs to $PSScriptRoot\Logs. .EXAMPLE PS C:\>Start-KerberosTraceLog -Path C:\Logs This command starts the trace log and logs to C:\Logs. The directory is created if it doesn't already exist. .NOTES This command must be run with local administrator credentials. The output from the individual logman.exe, nltest.exe, and netsh.exe commands are written to $PSScriptRoot\StartOutput\. AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to assist in troubleshooting Kerberos authentication issues. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias("DirectoryPath","LogDirectory")] [string]$Path = "$PSScriptRoot\Logs" ) Begin { if (!(Test-IsLocalAdmin)) { throw "This cmdlet must be run with admin credentials." } $KerberosbDebugFlags = "0x40243" $NtlmDebugFlags = "0x15003" $NegoExtsDebugFlags = "0xFFFF" $Pku2uDebugFlags = "0xFFFF" $SslDebugFlags= "0x0000FDFF" if (!(Test-Path -Path "$PSScriptRoot\StartOutput")) { New-Item -Path "$PSScriptRoot\StartOutput" -ItemType Directory -Force | Out-Null } } Process { if (!(Test-Path -Path $Path)) { New-Item -Path $Path -ItemType Directory | Out-Null } $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("start","kerb","-p {6B510852-3583-4e2d-AFFE-A67F9F223438}",$KerberosbDebugFlags,"-o `"$Path\kerb.etl`"","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\kerb.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\kerb_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("start","ntlm","-p {5BBB6C18-AA45-49b1-A15F-085F7ED0AA90}",$NtlmDebugFlags,"-o `"$Path\ntlm.etl`"","-ets")-NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\ntlm.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\ntlm_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("start","negoexts","-p {5AF52B0D-E633-4ead-828A-4B85B8DAAC2B}",$NegoExtsDebugFlags,"-o `"$Path\negoexts.etl`"","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\negoexts.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\negoexts_error.txt" $NegoExtender = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\NegoExtender\Parameters" if (!(Test-Path -Path $NegoExtender )) { New-Item -Path $NegoExtender -Force | Out-Null $Counter = 0 while (!(Test-Path -Path $NegoExtender)) { Start-Sleep -Seconds 1 $Counter++ if ($Counter -gt 30) { throw "Timeout waiting for registry key $NegoExtender to be created." } } } Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\NegoExtender\Parameters" -Name InfoLevel -Value ([System.Convert]::ToInt32($NegoExtsDebugFlags, 16)) -Type ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("start","pku2u","-p {2A6FAF47-5449-4805-89A3-A504F3E221A6}",$Pku2uDebugFlags,"-o `"$Path\pku2u.etl`"","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\pku2u.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\pku2u_error.txt" $Pku2u = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Pku2u\Parameters" if (!(Test-Path -Path $Pku2u)) { New-Item -Path $Pku2u -Force | Out-Null $Counter = 0 while (!(Test-Path -Path $Pku2u)) { Start-Sleep -Seconds 1 $Counter++ if ($Counter -gt 30) { throw "Timeout waiting for registry key $Pku2u to be created." } } } Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Pku2u\Parameters" -Name InfoLevel -Value ([System.Convert]::ToInt32($Pku2uDebugFlags, 16)) -Type ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("start","ssl","-p {37D2C3CD-C5D4-4587-8531-4696C44244C8}",$SslDebugFlags,"-o `"$Path\ssl.etl`"","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\ssl.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\ssl_error.txt" Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name SPMInfoLevel -Value ([System.Convert]::ToInt32("0x101F", 16)) -Type ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name LogToFile -Value 1 -Type ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name NegEventMask -Value ([System.Convert]::ToInt32("0xF", 16)) -Type ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\nltest.exe" -ArgumentList @("/dbflag:0x2080FFFF") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\nltest.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\nltest_error.txt" $PRocess = Start-Process -FilePath "$env:SYSTEMROOT\System32\netsh.exe" -ArgumentList @("trace","stop") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\netshstop.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\netshstop_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\netsh.exe" -ArgumentList @("trace","start","scenario=NetConnection","capture=yes","persistent=no","traceFile=`"$Path\Tracefile.ETL`"","overwrite=yes") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StartOutput\netsh.txt" -RedirectStandardError "$PSScriptRoot\StartOutput\netsh_error.txt" } End { Write-Host "Kerberos trace log started." -ForegroundColor Green } } Function Stop-KerberosTraceLog { <# .SYNOPSIS Stops a trace that was started to troubleshoot Kerberos authentication issues. .DESCRIPTION The Stop-KerberosTraceLog cmdlet stops the trace of logs and netsh to capture all Kerberos, NTLM, SSL, and Negotiation traffic. The required remaining logs are copied to the specified directory and then compressed into a zip file. .PARAMETER Path Specify the directory that was used during the Start-KerberosTraceLog to collect logs. This defaults to the module root. .INPUTS System.String You can pipe a directory path string to Stop-KerberosTraceLog. .OUTPUTS None .EXAMPLE PS C:\>Stop-KerberosTraceLog This command stops the trace log. .EXAMPLE PS C:\>Stop-KerberosTraceLog -Path C:\Logs This command stops the trace log and and copies additional required information to C:\Logs. Then, a zip file is written to C:\Logs containing the logs files. .NOTES This command must be run with local administrator credentials. The output from the individual logman.exe, nltest.exe, and netsh.exe commands are written to $PSScriptRoot\StopOutput\. AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to assist in troubleshooting Kerberos authentication issues. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [ValidateScript({Test-Path -Path $_})] [string]$Path = "$PSScriptRoot\Logs" ) Begin { if (!(Test-IsLocalAdmin)) { throw "This cmdlet must be run with admin credentials." } if (!(Test-Path -Path "$PSScriptRoot\StopOutput")) { New-Item -Path "$PSScriptRoot\StopOutput" -ItemType Directory | Out-Null } Add-Type -AssemblyName System.IO.Compression.FileSystem } Process { $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("stop","kerb","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\kerb.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\kerb_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("stop","ntlm","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\ntlm.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\ntlm_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("stop","negoexts","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\negoexts.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\negoexts_error.txt" Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\NegoExtender\Parameters" -Name "InfoLevel" -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("stop","pku2u","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\pku2u.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\pku2u_error.txt" Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Pku2u\Parameters" -Name "InfoLevel" -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\logman.exe" -ArgumentList @("stop","ssl","-ets") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\ssl.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\ssl_error.txt" Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "SPMInfoLevel" -Force | Out-Null Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "LogToFile" -Force | Out-Null Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "NegEventMask" -Force | Out-Null $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\nltest.exe" -ArgumentList @("/dbflag:0x0") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\nltest.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\nltest_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\netsh.exe" -ArgumentList @("wfp","capture","stop") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\netsh_wfp.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\netsh_wfp_error.txt" $Process = Start-Process -FilePath "$env:SYSTEMROOT\System32\netsh.exe" -ArgumentList @("trace","stop") -NoNewWindow -RedirectStandardOutput "$PSScriptRoot\StopOutput\netsh_tracestop.txt" -RedirectStandardError "$PSScriptRoot\StopOutput\netsh_tracestop_error.txt" if (Test-Path -Path "$env:SYSTEMROOT\debug\netlogon.log") { try { Copy-Item -Path "$env:SYSTEMROOT\debug\netlogon.log" -Destination $Path -Force | Out-Null } catch [Exception] { Write-Warning $_.Exception.Message } } if (Test-Path -Path "$env:SYSTEMROOT\system32\lsass.log") { try { Copy-Item -Path "$env:SYSTEMROOT\system32\lsass.log" -Destination $Path -Force | Out-Null } catch [Exception] { Write-Warning $_.Exception.Message } } Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "BuildLabEx" | Select-Object -ExpandProperty BuildLabEx | Out-File -FilePath "$Path\build.txt" Add-Type -AssemblyName System.IO.Compression.FileSystem $CompressionLevel = [System.IO.Compression.CompressionLevel]::Optimal try { $FileName = ("$Path\Logs_" + (Get-Date).ToString("yyyy-MM-dd-HH-mm") + ".zip") [System.IO.Compression.ZipFile]::CreateFromDirectory($Path,$FileName,$CompressionLevel,$false) $Path = $FileName } catch [Exception] { Write-Warning "Possible error creating zip file at $FileName : $($_.Exception.Message). The zip file may still have been created." } } End { Write-Host "Kerberos trace logs collected at $Path. Please share these for analysis." -ForegroundColor Green } } Function Test-IsLocalAdmin { <# .SYNOPSIS Tests is the current user has local administrator privileges. .DESCRIPTION The Test-IsLocalAdmin cmdlet tests the user's current Windows Identity for inclusion in the BUILTIN\Administrators role. .INPUTS None .OUTPUTS None .EXAMPLE PS C:\>Test-IsLocalAdmin This command returns true if the current is running the session with local admin credentials and false if not. .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to test for administrative credentials before running other commands that require them. #> [CmdletBinding()] Param() Begin {} Process { Write-Output ([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } End {} } Function Write-CCMLogFormat { <# .SYNOPSIS Writes a log file formatted to be read by the CMTrace tool. .DESCRIPTION The Write-CCMLogFormat cmdlet takes a message and writes it to a file in the format that can be read by CMTrace. .PARAMETER Message The message to be written to the file. .PARAMETER FilePath The path of the file to write the log information. .PARAMETER LogLevel The log level of the message. 1 is Informational, 2 is Warning, and 3 is Error. This defaults to Informational. .PARAMETER Component The component generating the log file. .PARAMETER Thread The thread ID of the process running the task. This defaults to the current managed thread ID. .EXAMPLE PS C:\>Write-CCMLogFormat -Message "Test Warning Message" -FilePath "c:\logpath.log" -LogLevel 2 -Component "PowerShell" This command writes "Test Warning Message" to c:\logpath.log and sets it as a Warning message in the CMTrace log viewer tool. .INPUTS System.String, System.String, System.Int32, System.String, System.Int32 .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/27/2016 .FUNCTIONALITY The intended use of this cmdlet is to write CMTrace formatted log files to be used with the viewer tool. #> [CmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [string]$Message, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [string]$FilePath, [Parameter(Position=2,ValueFromPipelineByPropertyName=$true)] [ValidateSet(1,2,3)] [Int32]$LogLevel = 1, [Parameter(Position=3,ValueFromPipelineByPropertyName=$true)] [string]$Component = [System.String]::Empty, [Parameter(Position=4,ValueFromPipelineByPropertyName=$true)] [Int32]$Thread = 0 ) Begin { if ($Thread -eq 0) { $Thread = [System.Threading.Thread]::CurrentThread.ManagedThreadId } $Date = Get-Date $Time = ($Date.ToString("HH:mm:ss.fff") + "+" + ([System.TimeZone]::CurrentTimeZone.GetUtcOffset((Get-Date)).TotalMinutes * -1)) $Day = $Date.ToString("MM-dd-yyyy") $File = $FilePath.Substring($FilePath.LastIndexOf("\") + 1) } Process { [string]$Log = "<![LOG[" + $Message + "]LOG]!><time=`"$Time`" date=`"$Day`" component=`"$Component`" context=`"`" type=`"$LogLevel`" thread=`"$Thread`" file=`"$File`">`r`n" } End { Add-Content -Path $FilePath -Value $Log -Force } } Function Get-IPv6ConfigurationOptions { <# .SYNOPSIS Writes the HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters DisabledComponents key property possible options. .DESCRIPTION The Get-IPv6ConfigurationOptions cmdlet writes the HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters DisabledComponents key property possible options. This registry key entry determines which components of IPv6 are enabled or disabled. The cmdlet writes the possible values to enter in this key entry. .EXAMPLE PS C:\>Get-IPv6ConfigurationOptions This command returns the possible registry key settings as an array of PSCustomObjects. .INPUTS None .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 2/28/2016 #> [CmdletBinding()] Param() Begin {} Process { Write-Output $script:IPv6Configs } End {} } Function Get-ProcessToken { <# .SYNOPSIS Gets the token handle for a specified process. .DESCRIPTION The Get-ProcessToken cmdlet gets a token handle pointer for a specified process. The CmdLet must be run with elevated permissions. .PARAMETER ProcessName The name of the process to get a token handle for. .PARAMETER ProcessId The Id of the process to get a token handle for. .PARAMETER CloseHandle Specifies if the handle to the token should be closed. Do not close the handle if you want to duplicate the token in another process. .EXAMPLE Get-ProcessToken -ProcessName lsass Gets the token handle for the lsass process. .INPUTS System.String System.Int32 .OUTPUTS IntPtr .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/25/2016 #> [CmdletBinding()] Param( [Parameter(Position=1)] [switch]$CloseHandle ) DynamicParam { # Create the dictionary $RuntimeParameterDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary #region Name # Create the collection of attributes $AttributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] # Create and set the parameters' attributes $ParameterAttribute = New-Object -TypeName System.Management.Automation.PARAMETERAttribute $ParameterAttribute.Mandatory = $true $ParameterAttribute.Position = 0 $ParameterAttribute.ParameterSetName ="Name" # Add the attributes to the attributes collection $AttributeCollection.Add($ParameterAttribute) # Generate and set the ValidateSet $Set = Get-Process | Select-Object -ExpandProperty Name $ValidateSetAttribute = New-Object -TypeName System.Management.Automation.ValidateSetAttribute($Set) $AttributeCollection.Add($ValidateSetAttribute) #Add Alias $AliasAttribute = New-Object -TypeName System.Management.Automation.AliasAttribute("Name") $AttributeCollection.Add($AliasAttribute) # Create and return the dynamic parameter $RuntimeParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter("ProcessName", [string], $AttributeCollection) $RuntimeParameterDictionary.Add("ProcessName", $RuntimeParameter) #endregion #region Id # Create the collection of attributes $AttributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] # Create and set the parameters' attributes $ParameterAttribute = New-Object -TypeName System.Management.Automation.PARAMETERAttribute $ParameterAttribute.Mandatory = $true $ParameterAttribute.Position = 0 $ParameterAttribute.ParameterSetName ="Id" # Add the attributes to the attributes collection $AttributeCollection.Add($ParameterAttribute) # Generate and set the ValidateSet $Set = Get-Process | Select-Object -ExpandProperty Id $ValidateSetAttribute = New-Object -TypeName System.Management.Automation.ValidateSetAttribute($Set) $AttributeCollection.Add($ValidateSetAttribute) #Add Alias $AliasAttribute = New-Object -TypeName System.Management.Automation.AliasAttribute("Id") $AttributeCollection.Add($AliasAttribute) # Create and return the dynamic parameter $RuntimeParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter("ProcessId", [Int32], $AttributeCollection) $RuntimeParameterDictionary.Add("ProcessId", $RuntimeParameter) #endregion return $RuntimeParameterDictionary } Begin { if (!([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Run the cmdlet with elevated credentials." } } Process { [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero [IntPtr]$ProcessTokenHandle = [IntPtr]::Zero if (!([System.Management.Automation.PSTypeName]"AdjPriv").Type) { Add-Type -MemberDefinition $script:TokenSignature -Name AdjPriv -Namespace AdjPriv } $AdjPriv = [AdjPriv.AdjPriv] try { switch ($PSCmdlet.ParameterSetName) { "Name" { $Process = Get-Process -Name $PSBoundParameters.ProcessName break } "Id" { $Process = Get-Process -Id $PSBoundParameters.ProcessId break } default { throw "Cannot determine parameter set." } } $ReturnValue = $AdjPriv::OpenProcessToken($Process.Handle, ([AdjPriv.AdjPriv]::TOKEN_IMPERSONATE -BOR [AdjPriv.AdjPriv]::TOKEN_DUPLICATE), [ref]$ProcessTokenHandle) $ReturnValue = $AdjPriv::DuplicateToken($ProcessTokenHandle, [AdjPriv.AdjPriv+SECURITY_IMPERSONATION_LEVEL]::SecurityImpersonation, [ref]$DulicateTokenHandle) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.marshal]::GetLastWin32Error())) } } finally { $AdjPriv::CloseHandle($ProcessTokenHandle) | Out-Null if ($CloseHandle) { $AdjPriv::CloseHandle($DulicateTokenHandle) | Out-Null } } } End { Write-Output $DulicateTokenHandle } } Function Set-ProcessToken { <# .SYNOPSIS Replaces the process token for the current process thread with a token from another process. .DESCRIPTION The Set-ProcessToken cmdlet takes a token handle from another process and then sets the process thread to use that token. Then it closes the token handle. The passed token handle must not be closed before it is passed. The CmdLet must be run with elevated permissions. .PARAMETER TokenHandle The Token Handle pointer that will replace the current process thread token. .PARAMETER ElevatePrivileges Adds the SeDebugPrivilege to the current process thread, which may be needed to replace the current process thread token. .EXAMPLE Get-ProcessToken -ProcessName lsass | Set-ProcessToken Gets the token handle for the lsass process and replaces the current process thread token. .INPUTS System.IntPtr .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/25/2016 #> [CmdletBinding()] Param( [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)] [IntPtr]$TokenHandle, [Parameter(Position=1)] [switch]$ElevatePrivileges ) Begin { if (!([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Run the cmdlet with elevated credentials." } } Process { if (!([System.Management.Automation.PSTypeName]"AdjPriv").Type) { Add-Type -MemberDefinition $script:TokenSignature -Name AdjPriv -Namespace AdjPriv } $AdjPriv = [AdjPriv.AdjPriv] if ($ElevatePrivileges) { $TokenPrivilege1Luid = New-Object AdjPriv.AdjPriv+TokPriv1Luid $TokenPrivilege1Luid.Count = 1 $TokenPrivilege1Luid.Luid = 0 $TokenPrivilege1Luid.Attr = [AdjPriv.AdjPriv]::SE_PRIVILEGE_ENABLED [System.IntPtr]$TempToken = [System.IntPtr]::Zero $ReturnValue = $AdjPriv::LookupPrivilegeValue($null, "SeDebugPrivilege", [ref]$TokenPrivilege1Luid.Luid) $ReturnValue = $AdjPriv::OpenProcessToken($AdjPriv::GetCurrentProcess(), [AdjPriv.AdjPriv]::TOKEN_ALL_ACCESS, [ref]$TempToken) $TokenPrivileges = New-Object -TypeName AdjPriv.AdjPriv+TOKEN_PRIVILEGES $DisableAllPrivileges = $false $BufferLength = 12 $ReturnValue = $AdjPriv::AdjustTokenPrivileges($TempToken, $DisableAllPrivileges, [ref]$TokenPrivilege1Luid, $BufferLength, [IntPtr]::Zero, [IntPtr]::Zero) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marrshal]::GetLastWin32Error())) } } try { $ReturnValue = $AdjPriv::SetThreadToken([IntPtr]::Zero, $TokenHandle) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error())) } } finally { $AdjPriv::CloseHandle($TokenHandle) | Out-Null } } End { Write-Host "Successfully duplicated token to current process thread." } } Function Reset-ProcessToken { <# .SYNOPSIS Reverts to the process thread token to the current user. .DESCRIPTION The Reset-ProcessToken cmdlet needs to be called to end any process impersonation called through DdeImpersonateClient, ImpersonateDdeClientWindow, ImpersonateLoggedOnUser, ImpersonateNamedPipeClient, ImpersonateSelf, ImpersonateAnonymousToken or SetThreadToken. Underlying the cmdlet is a P/Invoke call to RevertToSelf() in AdvApi32.dll. The CmdLet must be run with elevated permissions. .EXAMPLE Reset-ProcessToken Reverts the process thread to use the token of the current user. .INPUTS None .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/25/2016 #> [CmdletBinding()] Param() Begin { if (!([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Run the cmdlet with elevated credentials." } } Process { if (!([System.Management.Automation.PSTypeName]"AdjPriv").Type) { Add-Type -MemberDefinition $script:TokenSignature -Name AdjPriv -Namespace AdjPriv } $AdjPriv = [AdjPriv.AdjPriv] #RevertToSelf is equivalent to SetThreadToken([System.IntPtr]::Zero, [System.IntPtr]::Zero) $ReturnValue = $AdjPriv::RevertToSelf() if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error())) } } End { Write-Host "Successfully executed RevertToSelf() and reset the process thread token." } } Function Get-LsaSecret { <# .SYNOPSIS Enumerates the content of the LSA Secrets registry hive. .DESCRIPTION The cmdlet first duplicates the lsass process token and sets it to the current process thread. Then it copies each secret stored in HKLM:\SECURITY\Policy\Secrets to a temporary location. After the content is copied over, Lsa functions from AdvApi32.dll are called to decrypt the content. When the cmdlet finishes, it leaves the registry area unchanged and reverts the process thread token. The CmdLet must be run with elevated permissions. .EXAMPLE Get-LsaSecret Retrieves all of the stored secrets in the registry using HKLM:\SECURITY\Policy\Secrets\<Generated GUID> to store the temporary information. .INPUTS None .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/27/2016 #> [CmdletBinding()] Param() Begin { if (!([System.Management.Automation.PSTypeName]"Lsa").Type) { Add-Type -MemberDefinition $script:LsaSignature -Name Lsa -Namespace Lsa } Get-ProcessToken -ProcessName lsass | Set-ProcessToken $TempKey = [System.Guid]::NewGuid().ToString() $Lsa = [Lsa.Lsa] $Destination = "HKLM:\SECURITY\Policy\Secrets\$TempKey" if ((Get-Item -Path $Destination -ErrorAction SilentlyContinue) -ne $null) { Remove-Item -Path $Destination -Recurse -Force | Out-Null } New-Item -Path $Destination | Out-Null } Process { $Secrets = @() #Get all sub keys in secrets, these are the accounts Get-ChildItem -Path "HKLM:\SECURITY\Policy\Secrets" | Where-Object {$_.Name -notmatch $TempKey -and $_.Property -ne $null} | ForEach-Object { $AccountName = $_.PSChildName #Get all the sub keys of the accounts, these are keys like CurrVal, OldVal, CupdTime, etc Get-ChildItem -Path $_.PSPath | ForEach-Object { $ItemName = $_.PSChildName if ((Test-Path -Path "$Destination\$ItemName")) { Remove-Item -Path "$Destination\$ItemName" -Recurse -Force | Out-Null } [System.Byte[]]$Property = Get-ItemProperty -Path $_.PSPath | Select-Object -ExpandProperty "(Default)" New-Item -Path "$Destination\$ItemName" | Out-Null Set-ItemProperty -Path "$Destination\$ItemName" -Name '(Default)' -Value $Property } #ObjectAttributes $ObjectAttributes = New-Object -TypeName Lsa.Lsa+LSA_OBJECT_ATTRIBUTES $ObjectAttributes.Length = 0; $ObjectAttributes.RootDirectory = [System.IntPtr]::Zero $ObjectAttributes.Attributes = 0; $ObjectAttributes.SecurityDescriptor = [System.IntPtr]::Zero $ObjectAttributes.SecurityQualityOfService = [System.IntPtr]::Zero #LocalSysem $Localsystem = New-Object -TypeName Lsa.Lsa+LSA_UNICODE_STRING $Localsystem.Buffer = [System.IntPtr]::Zero $Localsystem.Length = 0; $Localsystem.MaximumLength = 0; #SecretName $SecretName = New-Object -TypeName Lsa.Lsa+LSA_UNICODE_STRING $SecretName.Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($TempKey) $SecretName.Length = [System.UInt16]($TempKey.Length * [System.Text.UnicodeEncoding]::CharSize) $SecretName.MaximumLength = [System.UInt16](($TempKey.Length + 1) *[System.Text.UnicodeEncoding]::CharSize) #LSA Policy Handle [System.IntPtr]$LsaPolicyHandle = [System.IntPtr]::Zero [Lsa.Lsa+LSA_AccessPolicy]$AccessPolicy = [Lsa.Lsa+LSA_AccessPolicy]::POLICY_GET_PRIVATE_INFORMATION [System.UInt16]$OpenPolicyResut = [Lsa.Lsa]::LSAOpenPolicy([ref]$LocalSystem, [ref]$ObjectAttributes, $AccessPolicy, [ref]$LsaPolicyHandle) [System.UInt16]$OpenPolicyErrorCode = [Lsa.Lsa]::LsaNtStatusToWinError($OpenPolicyResut) if ($OpenPolicyErrorCode -ne 0) { Write-Warning (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error())) } # Retrieve Private Data [System.IntPtr]$PrivateDataHandle = [System.IntPtr]::Zero $RetrievePrivateDataResult = [Lsa.Lsa]::LsaRetrievePrivateData($LsaPolicyHandle, [ref]$SecretName, [ref]$PrivateDataHandle) [System.UInt16]$RetrievePrivateDataErroCode = [Lsa.Lsa]::LsaNtStatusToWinError($RetrievePrivateDataResult) [System.UInt16]$CloseResult = [Lsa.Lsa]::LsaClose($LsaPolicyHandle) [System.UInt16]$CloseErrorCode = [Lsa.Lsa]::LsaNtStatusToWinError($CloseResult) if ($CloseErrorCode -ne 0) { Write-Warning (New-Object -TypeName System.Exception(New-Object -TypeName System.ComponentModel.Win32Exception($CloseErrorCode)) | Format-List) } if ($RetrievePrivateDataErroCode -ne 0) { Write-Warning (New-Object -TypeName System.Exception(New-Object -TypeName System.ComponentModel.Win32Exception($RetrievePrivateDataErroCode))) } try { [Lsa.Lsa+LSA_UNICODE_STRING]$SecretData = [Lsa.Lsa+LSA_UNICODE_STRING][System.Runtime.InteropServices.Marshal]::PtrToStructure($PrivateDataHandle, [System.Type][Lsa.Lsa+LSA_UNICODE_STRING]) [System.String]$Value = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($SecretData.Buffer) } catch [Exception] { $Value = [System.String]::Empty } if ($AccountName -match "^_SC_") { # Get Service Account $Service = $AccountName -Replace "^_SC_" Try { # Get Service Account $Service = Get-WmiObject -Query "SELECT StartName FROM Win32_Service WHERE Name = '$Service'" -ErrorAction Stop $Account = $Service.StartName } catch [Exception] { $Account = [System.String]::Empty } } else { $Account = [System.String]::Empty } $Secrets += (New-Object -TypeName PSObject -Property @{Name = $AccountName; Secret = $Value; Account = $Account; EncryptedBinary = [System.Byte[]](Get-ItemProperty -Path "$Destination\CurrVal" -Name "(Default)" | Select-Object -ExpandProperty "(Default)")}) [System.UInt16]$FreeMemoryResult = [Lsa.Lsa]::LsaFreeMemory($PrivateDataHandle) [System.UInt16]$FreeMemoryErrorCode = [Lsa.Lsa]::LsaNtStatusToWinError($FreeMemoryResult) if ($FreeMemoryErrorCode -ne 0) { Write-Warning (New-Object -TypeName System.Exception(New-Object -TypeName System.ComponentModel.Win32Exception($FreeMemoryErrorCode)) | Format-List) } } } End { Remove-Item -Path "$Destination" -Force -Recurse Reset-ProcessToken Write-Output $Secrets } } $script:IPv6Configs = @( [PSCustomObject]@{Name="IPv6 Disabled On All Interfaces";Value="0xFFFFFFFF"}, [PSCustomObject]@{Name="IPv6 Enabled only on tunnel interfaces";Value="0xFFFFFFFE"}, [PSCustomObject]@{Name="IPv6 Disabled On Tunnel Interfaces, Enabled On All Others";Value="0xFFFFFFEF"}, [PSCustomObject]@{Name="IPv6 Disabled On Loopback Interface, Enabled On All Others";Value="0xFFFFFFEE"}, [PSCustomObject]@{Name="IPv6 Disabled, Prefer IPv6 over IPv4";Value="0xFFFFFFDF"}, [PSCustomObject]@{Name="IPv6 Enabled Only On Tunnel Interfaces, Prefer IPv6 of IPv4";Value="0xFFFFFFDE"}, [PSCustomObject]@{Name="IPv6 Enabled On All Non Tunnel Interfaces, Prefer IPv6 over IPv4";Value="0xFFFFFFCF"}, [PSCustomObject]@{Name="IPv6 Disabled On Loopback Interface, Prefer IPv6 over IPv4";Value="0xFFFFFFCE"}, [PSCustomObject]@{Name="IPv6 Disabled On All Interfaces";Value="0x000000FF"}, [PSCustomObject]@{Name="IPv6 Prefer IPv4 over IPv6 by changing entries in prefix policy table";Value="0x00000020"}, [PSCustomObject]@{Name="IPv6 Disabled on LAN and PPP interfaces ";Value="0x00000010"}, [PSCustomObject]@{Name="Disable Teredo";Value="0x00000008"}, [PSCustomObject]@{Name="Disable ISATAP";Value="0x00000004"}, [PSCustomObject]@{Name="Disable 6to4";Value="0x00000002"}, [PSCustomObject]@{Name="IPv6 Disabled on Tunnel Interfaces including ISATAP, 6to4 and Teredo";Value="0x00000001"} ) $script:Ports = @( [PSCustomObject]@{"Service"="FTP Data";"Port"=20}, [PSCustomObject]@{"Service"="FTP Command";"Port"=21}, [PSCustomObject]@{"Service"="SSH";"Port"=22}, [PSCustomObject]@{"Service"="TelNet";"Port"=23}, [PSCustomObject]@{"Service"="SMTP";"Port"=25}, [PSCustomObject]@{"Service"="WINS";"Port"=42}, [PSCustomObject]@{"Service"="DNS";"Port"=53}, [PSCustomObject]@{"Service"="DHCP Server";"Port"=67}, [PSCustomObject]@{"Service"="DHCP Client";"Port"=68}, [PSCustomObject]@{"Service"="TFTP";"Port"=69}, [PSCustomObject]@{"Service"="HTTP";"Port"=80}, [PSCustomObject]@{"Service"="Kerberos";"Port"=88}, [PSCustomObject]@{"Service"="POP3";"Port"=110}, [PSCustomObject]@{"Service"="SFTP";"Port"=115}, [PSCustomObject]@{"Service"="NetBIOS Name Service";"Port"=137}, [PSCustomObject]@{"Service"="NetBIOS Datagram Service";"Port"=138}, [PSCustomObject]@{"Service"="NetBIOS Session Service";"Port"=139}, [PSCustomObject]@{"Service"="SNMP";"Port"=161}, [PSCustomObject]@{"Service"="LDAP";"Port"=389}, [PSCustomObject]@{"Service"="SSL";"Port"=443}, [PSCustomObject]@{"Service"="SMB";"Port"=445}, [PSCustomObject]@{"Service"="Syslog";"Port"=514}, [PSCustomObject]@{"Service"="RPC";"Port"=135}, [PSCustomObject]@{"Service"="LDAPS";"Port"=636}, [PSCustomObject]@{"Service"="SOCKS";"Port"=1080}, [PSCustomObject]@{"Service"="MSSQL";"Port"=1433}, [PSCustomObject]@{"Service"="SQL Browser";"Port"=1434}, [PSCustomObject]@{"Service"="Oracle DB";"Port"=1521}, [PSCustomObject]@{"Service"="NFS";"Port"=2049}, [PSCustomObject]@{"Service"="RDP";"Port"=3389}, [PSCustomObject]@{"Service"="XMPP";"Port"=5222}, [PSCustomObject]@{"Service"="HTTP Proxy";"Port"=8080}, [PSCustomObject]@{"Service"="Global Catalog";"Port"=3268}, [PSCustomObject]@{"Service"="Global Catalog/SSL";"Port"=3269}, [PSCustomObject]@{"Service"="POP3/SSL";"Port"=995}, [PSCustomObject]@{"Service"="IMAP/SSL";"Port"=993}, [PSCustomObject]@{"Service"="IMAP";"Port"=143} ) $script:TokenSignature = @" public enum SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous = 0, SecurityIdentification = 1, SecurityImpersonation = 2, SecurityDelegation = 3 } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } public const int SE_PRIVILEGE_ENABLED = 0x00000002; public const int TOKEN_QUERY = 0x00000008; public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; public const UInt32 TOKEN_DUPLICATE = 0x0002; public const UInt32 TOKEN_IMPERSONATE = 0x0004; public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID); public const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; public const int ANYSIZE_ARRAY = 1; [StructLayout(LayoutKind.Sequential)] public struct LUID { public UInt32 LowPart; public UInt32 HighPart; } [StructLayout(LayoutKind.Sequential)] public struct LUID_AND_ATTRIBUTES { public LUID Luid; public UInt32 Attributes; } public struct TOKEN_PRIVILEGES { public UInt32 PrivilegeCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)] public LUID_AND_ATTRIBUTES [] Privileges; } [DllImport("advapi32.dll", SetLastError=true)] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle); [DllImport("advapi32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetThreadToken( IntPtr PHThread, IntPtr Token ); [DllImport("advapi32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("kernel32.dll", ExactSpelling = true)] public static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] public static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); [DllImport( "kernel32.dll", CharSet = CharSet.Auto )] public static extern bool CloseHandle( IntPtr handle ); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool RevertToSelf(); "@ $script:LsaSignature = @" [StructLayout(LayoutKind.Sequential)] public struct LSA_UNICODE_STRING { public UInt16 Length; public UInt16 MaximumLength; public IntPtr Buffer; } [StructLayout(LayoutKind.Sequential)] public struct LSA_OBJECT_ATTRIBUTES { public int Length; public IntPtr RootDirectory; public LSA_UNICODE_STRING ObjectName; public uint Attributes; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; } public enum LSA_AccessPolicy : long { POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L, POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L, POLICY_GET_PRIVATE_INFORMATION = 0x00000004L, POLICY_TRUST_ADMIN = 0x00000008L, POLICY_CREATE_ACCOUNT = 0x00000010L, POLICY_CREATE_SECRET = 0x00000020L, POLICY_CREATE_PRIVILEGE = 0x00000040L, POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L, POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L, POLICY_AUDIT_LOG_ADMIN = 0x00000200L, POLICY_SERVER_ADMIN = 0x00000400L, POLICY_LOOKUP_NAMES = 0x00000800L, POLICY_NOTIFICATION = 0x00001000L } [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaRetrievePrivateData( IntPtr PolicyHandle, ref LSA_UNICODE_STRING KeyName, out IntPtr PrivateData ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaStorePrivateData( IntPtr policyHandle, ref LSA_UNICODE_STRING KeyName, ref LSA_UNICODE_STRING PrivateData ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaOpenPolicy( ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaNtStatusToWinError( uint status ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaClose( IntPtr policyHandle ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaFreeMemory( IntPtr buffer ); "@ |