Beaver.psm1
#Requires -Version 5.0 #Requires -RunAsAdministrator function Get-StringHash { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateSet('MD5','RIPEMD160','SHA1','SHA256','SHA384','SHA512')] [ValidateNotNullorEmpty()] [string] $hashAlgorithm ) process { $strBuilder = New-Object System.Text.StringBuilder [System.Security.Cryptography.HashAlgorithm]::Create($hashAlgorithm).ComputeHash(` [System.Text.Encoding]::UTF8.GetBytes($text)) | ForEach-Object { [void]$strBuilder.Append($_.ToString("x2")) } return $strBuilder.ToString() } } function Test-CurrentUserInGroup { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $groupName ) process { return ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).` IsInRole($groupName) } } function Get-MaskLength { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [Net.IPAddress] $mask ) process { $bits = "$($mask.GetAddressBytes() | ForEach-Object { [Convert]::ToString($_, 2)})" -replace '[\s0]' return $bits.Length } } function Test-IPInSubnet { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*/*'})] [string] $cidr, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*'})] [string] $ipAddress ) process { $network, [int]$subnetlen = $cidr.Split('/') $a = [uint32[]]$network.Split('.') [uint32] $unetwork = ($a[0] -shl 24) + ($a[1] -shl 16) + ($a[2] -shl 8) + $a[3] $mask = (-bnot [uint32]0) -shl (32 - $subnetlen) $a = [uint32[]]$ipAddress.split('.') [uint32] $uip = ($a[0] -shl 24) + ($a[1] -shl 16) + ($a[2] -shl 8) + $a[3] return ($unetwork -eq ($mask -band $uip)) } } function Add-SignatureToFile { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $fileMask ) begin { [System.Security.Cryptography.X509Certificates.X509Certificate2] $signingCert = $null } process { try { Write-Verbose 'Finding signing certificate' $signingCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Sort-Object NotAfter | Select-Object -Last 1 if ($signingCert) { Write-Verbose ('Found signing certificate: subjectCert = {0} | issuedBy = {1}'` -f $signingCert.Subject, $signingCert.Issuer) $chooseFiles = Get-ChildItem $fileMask foreach ($oneFile in $chooseFiles) { if ((Get-AuthenticodeSignature $oneFile).Status -ne 'Valid') { Write-Verbose ("Sign file: {0}" -f $oneFile) [void] (Set-AuthenticodeSignature $oneFile -Certificate $signingCert ` -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll) } } } else { throw 'Error: no signing certificate found' } } catch { throw; } } } function Send-WakeOnLan { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*'})] [string] $broadcastAddress, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*-*-*-*-*-*'})] [string] $macAddress ) begin { try { Write-Verbose ('Loading assembly "System.Net"') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Net") Write-Verbose ('Loading assembly "System.Net.Sockets"') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Net.Sockets") Write-Verbose ('Creating UDP socket') $udpClient = New-Object System.Net.Sockets.UdpClient $endPoint = New-Object System.Net.IPEndPoint $([System.Net.IPAddress]::Parse($broadCastAddress)),10000 } catch { throw; } } process { if($udpClient -and $endPoint) { try { [byte[]]$macBytes = $macAddress.split("-") | ForEach-Object { [byte]"0x$_" } [byte[]]$bytes = New-Object "byte[]" $(6 + 16 * $($macBytes.length)) for ($i = 0; $i -lt 6; $i++) { $bytes[$i] = [byte] 0xff } for ($i = 6; $i -lt $bytes.length; $i += $macBytes.length) { for($j = 0; $j -lt $macBytes.length; $j++) { $bytes[$i + $j] = $macBytes[$j] } } Write-Verbose ('Connect to endpoint') $udpClient.connect($endPoint) Write-Verbose ('Sending magic packet') [void]$udpClient.Send($bytes, $bytes.length) Write-Verbose ('Magic packet was sent') $udpClient.Close() } catch { throw; } } } } function Get-ExpireCertificate { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [ValidateRange(1, 365)] [int] $expireInDays ) process { return ( Get-Childitem cert: -Recurse | ` Where-Object { ($_.NotAfter -gt (Get-Date).AddDays(-1)) -and ($_.NotAfter -lt (Get-Date).AddDays($expireInDays)) } | ` Select-Object Subject,Thumbprint,@{Name="Expires in (Days)";` Expression={($_.NotAfter).subtract([DateTime]::Now).days}}, ` PSParentPath,SerialNumber,HasPrivateKey,Issuer,Archived,` EnhancedKeyUsageList,NotAfter,NotBefore,DnsNameList | ` Sort-Object "Expires in (Days)" | Format-List ) } } function New-Password { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNull()] [ValidateRange(1, 128)] [int] $passwordLength, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [ValidateRange(1, 128)] [int] $numbersNonAlphaNumeric ) process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Generate random new password with length $passwordLength")) { Write-Verbose ('Loading assembly "System.Web"') Add-Type -AssemblyName System.Web Write-Verbose ('Generate random passwords with length {0}' -f $passwordLength) return [System.Web.Security.Membership]::GeneratePassword($passwordLength, $numbersNonAlphaNumeric) } } catch { throw; } } } function Send-FileOnFTP { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $url, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $localFileName, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [Management.Automation.PSCredential] $credentials, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [bool] $enableTls = $true ) begin { $fileWithoutPath = Split-Path -Leaf $localFileName $remotePath = $url + '/' + $fileWithoutPath } process { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' Write-Verbose ('Create FtpWebRequest object') try { $ftpWebRequest = [System.Net.FtpWebRequest]::Create($remotePath) $ftpWebRequest = [System.Net.FtpWebRequest]$ftpWebRequest $ftpWebRequest.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $ftpWebRequest.UseBinary = $true $ftpWebRequest.UsePassive = $true $ftpWebRequest.EnableSsl = $enableTls $ftpWebRequest.KeepAlive = $false if($ftpWebRequest) { Write-Verbose ('Add client credentials') $ftpWebRequest.Credentials = $credentials.GetNetworkCredential() #New-Object System.Net.NetworkCredential($username, $password) Write-Verbose ('Copy file to request stream') $fileContents = [System.IO.File]::ReadAllBytes($localFileName) $ftpWebRequest.ContentLength = $fileContents.Length Write-Verbose ('Transfer file: {0}' -f $localFileName) $reqStream = $ftpWebRequest.GetRequestStream() $reqStream.Write($fileContents, 0, $fileContents.Length) $reqStream.Close() $response = $ftpWebRequest.GetResponse() Write-Verbose ('Transfer status: {0}' -f $response.StatusDescription) $response.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Uninstall-MSIPackage { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $fqdn, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $appName, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [Management.Automation.PSCredential] $credentials ) begin { $wmiApp = $null $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { Write-Verbose ('WMI Query: {0}' -f $fqdn) try { if($credentials) { $wmiApp = Get-WmiObject -ComputerName $fqdn -Query ` "SELECT * FROM Win32_Product WHERE Name LIKE '%$appName%'" -Credential $credentials } else { $wmiApp = Get-WmiObject -ComputerName $fqdn -Query ` "SELECT * FROM Win32_Product WHERE Name LIKE '%$appName%'" } if($wmiApp) { Write-Verbose ('WMI uninstalling: {0} | {1}' -f $wmiApp.Name, $wmiApp.Version) $wmiApp.Uninstall() } else { throw "WMI finding $appName on $fqdn failed" } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Save-PptAsFormat { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $pptFile, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('PDF','XPS','PNG','JPG','HTML','WMV')] [string] $saveAs ) begin { [string] $outFile = '' $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ('Open PowerPoint application') $ppt = New-Object -ComObject PowerPoint.Application $withWindow = [Microsoft.Office.Core.MsoTriState]::msoFalse Write-Verbose ('Get the slide deck: {0}' -f $pptFile) $slideDeck = $ppt.Presentations.Open($pptFile, [Microsoft.Office.Core.MsoTriState]::msoTrue, ` [Microsoft.Office.Core.MsoTriState]::msoTrue, $withWindow) Write-Verbose ('Presentation has slides: {0}' -f $slideDeck.Slides.Count) Add-Type -AssemblyName Microsoft.Office.Interop.PowerPoint $saveOptions = [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::"ppSaveAs$saveAs" $outFile = [System.IO.Path]::ChangeExtension($pptFile, $saveAs.ToLower()) if (Test-Path $outFile) { Remove-Item $outFile -Force } Write-Verbose ('Save the file: {0}' -f $outFile) $slideDeck.SaveAs($outFile, $saveOptions) Write-Verbose ('Close the slide deck') $slideDeck.Close() $slideDeck = $null Write-Verbose ('Quit the PowerPoint application') $ppt.Quit() $ppt = $null [GC]::Collect(); [GC]::WaitForPendingFinalizers(); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outFile } } function Save-DocAsPdf { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $docFile ) begin { [string] $outFile = '' $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ('Open Word application') $word = New-Object -ComObject Word.Application Write-Verbose ('Open Word document') $doc = $word.Documents.Open($docFile) $outFile = [System.IO.Path]::ChangeExtension($docFile, 'pdf') if (Test-Path $outFile) { Remove-Item $outFile -Force } Write-Verbose ('Save the file: {0}' -f $outFile) $doc.SaveAs($outFile, 17) Write-Verbose ('Close Word document') $doc.Close() $doc = $null Write-Verbose ('Quit the Word application') $word.Quit() $word = $null [GC]::Collect(); [GC]::WaitForPendingFinalizers(); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outFile } } function Add-SignatureInISE { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $signingCertSubject ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [System.Security.Cryptography.X509Certificates.X509Certificate2] $signingCert = $null } process { try { if([string]::IsNullOrEmpty($signingCertSubject)) { $signingCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Sort-Object NotAfter | Select-Object -Last 1 } else { $signingCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Subject -like "*E=$signingCertSubject*" | ` Sort-Object NotAfter | Select-Object -Last 1 } } Write-Verbose ('Found certificate: {0} | {1}' -f ` $signingCert.FriendlyName, $signingCert.SerialNumber) if($signingCert) { $openFiles = $psISE.CurrentPowerShellTab | ForEach-Object { $_.Files } foreach ($oneOpenFile in $openFiles) { $oneFilePath = $oneOpenFile.FullPath $oneFileLine = $oneOpenFile.Editor.CaretLine $oneFileColumn = $oneOpenFile.Editor.CaretColumn if (-not $oneOpenFile.IsSaved) { [void] $oneOpenFile.Save() } if ((@('.ps1','.psm1','.psd1') -contains [System.IO.Path]::GetExtension($oneFilePath)) -and ` ((Get-AuthenticodeSignature $oneFilePath).Status -ne 'Valid')) { [void] $psISE.CurrentPowerShellTab.Files.Remove($oneOpenFile) Write-Verbose ('Sign file: {0}' -f $oneFilePath) [void] (Set-AuthenticodeSignature $oneFilePath -Certificate $signingCert ` -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll) $reloadedFile = $psISE.CurrentPowerShellTab.Files.Add($oneFilePath) $reloadedFile.Editor.SetCaretPosition($oneFileLine, $oneFileColumn) } } } else { throw 'Error: no signing certificate found' } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Clear-ISEHistory { [CmdletBinding(SupportsShouldProcess = $false)] param() process { $count = $psIse.Options.MruCount $psIse.Options.MruCount = 0 $psIse.Options.MruCount = $count } } function Clear-EventLog { [CmdletBinding(SupportsShouldProcess = $false)] param() process { Get-WinEvent -ListLog * | ForEach-Object { Write-Verbose ('Clear windows event log: {0}' -f $_.LogName) Clear-EventLog -LogName $_.LogName -ErrorAction SilentlyContinue } } } function Set-RegistryValue { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $keyPath, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $value, [Parameter(Mandatory = $true, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('string','expandstring','multistring','dword')] [string] $type ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set registry key $keyPath\$name to $value")) { Write-Verbose ("Ensure the key exists") if (Test-Path $keyPath) { Write-Verbose ("Key already exists: {0}" -f $keyPath) } else { Write-Verbose ("Creating the whole registry path: {0}" -f $keyPath) [void] (New-Item -Path $keyPath -ItemType Registry -Force) } Write-Verbose ("Set the value") Set-ItemProperty -Path $keyPath -Name $name -Value $value -Type $type -Force } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Add-SybaseODBCProfile { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [Management.Automation.PSCredential] $credentials, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $srvName, [Parameter(Mandatory = $true, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $dbName, [Parameter(Mandatory = $true, Position = 4, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet(12, 16, 17)] [int] $version ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $odbcRootKey = 'HKCU:\SOFTWARE\ODBC\ODBC.INI' } process { try { $sqlAnyLocation = ('HKLM:\SOFTWARE\Sybase\SQL Anywhere\{0}.0' -f $version) Write-Verbose ('Read SQL Anywhere registry key: {0}' -f $sqlAnyLocation) if (Test-Path $sqlAnyLocation) { $installDir = (Get-ItemProperty -Path $sqlAnyLocation -Name Location).Location if (Test-Path $installDir) { Write-Verbose ('Found SQL Anywhere instalation folder: {0}' -f $installDir) Write-Verbose ('Creating ODBC registry values') Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name CommLinks -Value 'TCPIP{}' -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name DatabaseName -Value $dbName -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name Driver -Value ('{0}\Bin32\dbodbc{1}.dll' -f $installDir, $version) -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name Integrated -Value 'NO' -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name PWD -Value ($credentials.GetNetworkCredential().Password) -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name ServerName -Value $srvName -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name UID -Value $credentials.UserName -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\ODBC Data Sources' -f $odbcRootKey) -Name $name -Value ('SQL Anywhere {0}' -f $version) -Type String -Verbose:$VerbosePreference Write-Verbose ('Creating ODBC registry values done') } else { throw 'SQL Anywhere installation directory not found' } } else { throw 'SQL Anywhere installation not found' } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-DirectoryEntry { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $distinguishedName, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [Management.Automation.PSCredential] $credentials ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $outDE = $null } process { try { if ($distinguishedName -like 'ldap://*') { Write-Verbose ('Correct invalid DE: {0}' -f $distinguishedName) $distinguishedName = 'LDAP{0}' -f $distinguishedName.Substring(4) } elseif ($distinguishedName -like 'gc://*') { Write-Verbose ('Correct invalid DE: {0}' -f $distinguishedName) $distinguishedName = 'GC{0}' -f $distinguishedName.Substring(2) } if ([string]::IsNullOrEmpty($userName)) { Write-Verbose ('ADSI connecting') $outDE = [ADSI] $distinguishedName } else { Write-Verbose ('System.DirectoryServices.DirectoryEntry connecting') $outDE = New-Object System.DirectoryServices.DirectoryEntry ($distinguishedName, $credentials.UserName, ($credentials.GetNetworkCredential().Password)) } if ([string]::IsNullOrEmpty($outDE.Guid)) { if ($outDE) { Write-Verbose ('Disposing invalid DE') $outDE.Close() [GC]::Collect() [GC]::WaitForPendingFinalizers() } $outDE = $null } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } # if ($outDE) { # $outDE | Add-Member -MemberType NoteProperty -Name BeaverDEUserName -Value $userName -Force # $outDE | Add-Member -MemberType NoteProperty -Name BeaverDEPassword -Value $password -Force # } return $outDE } } function Get-LocalUser { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $psObj = $null } process { try { $adsiObj = Get-DirectoryEntry "WinNT://$computerName" -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $adsiObj.Path) $psObj = $adsiObj.Children | Where-Object {$_.SchemaClassName -eq 'user'} | ForEach-Object { $groups = $_.Groups() | ForEach-Object { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } $_ | Select-Object @{n = 'UserName';e = {$_.Name}},@{n = 'Groups';e = {$groups -join ';'}} } $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $psObj } } function Enable-LocalUser { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $adsiObjPath = 'WinNT://{0}/{1},user' -f $computerName, $name Write-Verbose ('Open local account with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose ('Enable local account {0}.' -f $name) $originalUAC = [int] $adsiObj.UserFlags.Value $newUAC = [int] ($originalUAC -band (-bnot ([int] 2))) $adsiObj.UserFlags.Value = $newUAC $adsiRs = $adsiObj.SetInfo() $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Disable-LocalUser { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $adsiObjPath = "WinNT://$computerName/{0},user" -f $name Write-Verbose ('Open local account with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose ('Disable local account {0}.' -f $name) $originalUAC = [int] $adsiObj.UserFlags.Value $adsiObj.UserFlags.Value = ($originalUAC -bor 2) $adsiRs = $adsiObj.SetInfo() $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-PasswordFromSecureString { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [System.Security.SecureString] $secureString ) process { return ([System.Runtime.InteropServices.Marshal]::PtrToStringAuto(` [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString))) } } function Set-LocalUserPassword { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [System.Security.SecureString] $oldPassword, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [System.Security.SecureString] $newPassword, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Change user passwords for $name")) { $adsiObjPath = 'WinNT://{0}/{1},user' -f $computerName, $name Write-Verbose ('Open local user with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose ('Local user ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose ('Change local user password.') $adsiRs = $adsiObj.ChangePassword((Get-PasswordFromSecureString -secureString $oldPassword), ` (Get-PasswordFromSecureString -secureString $newPassword)) $adsiObj.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Add-MemberLocalGroup { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $memberLogin, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $localGroup, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $localObjType, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ("Going to obtain local group: {0}" -f $localGroup) $localGroupDE = $null $localGroupDE = [ADSI] ('WinNT://{0}/{1},Group' -f $computerName, $localGroup) if($localGroupDE) { $memberADSIPath = 'WinNT://{0}/{1}' -f $computerName, $memberLogin $memberADSIPath = '{0},{1}' -f $memberADSIPath, $localObjType Write-Verbose ("Adding: {0} | {1}" -f $memberLogin, $memberADSIPath) $adsiRs = $null $adsiRs = $localGroupDE.Add($memberADSIPath) $localGroupDE.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function New-LocalObject { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [System.Security.SecureString] $password, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false, Position = 4, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $groups ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Create local $type $name")) { Write-Verbose ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}' -f $computerName) -Verbose:$VerbosePreference Write-Verbose ("Going to create or open the new object: {0} = {1}" -f $type, $name) Write-Verbose ("The object does not exist, going to create it.") $newObj = $null $newObj = $localSAM.Create($type, $name) if (-not ([string]::IsNullOrEmpty($newObj.Path))) { if ($type -eq 'user') { if (-not ([string]::IsNullOrEmpty((Get-PasswordFromSecureString -secureString $password)))) { Write-Verbose ("Setting password.") $adsiRs = $null $adsiRs = $newObj.SetPassword((Get-PasswordFromSecureString -secureString $password)) } } Write-Verbose ("Saving the newly created object.") $adsiRs = $null $adsiRs = $newObj.SetInfo() if (-not ([string]::IsNullOrEmpty($groups))) { $groupList = $groups.Split(',', [System.StringSplitOptions]::RemoveEmptyEntries) Write-Verbose ("Adding the new object to groups: {0}x" -f $groupList.Count) $groupList | ForEach-Object { $oneGroup = $_ Add-MemberLocalGroup -memberLogin $name -localGroup $oneGroup ` -localObjType $type -Verbose:$VerbosePreference } } } $localSAM.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Remove-LocalObject { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}' -f $computerName) -Verbose:$VerbosePreference Write-Verbose ("Going to delete object: {0} = {1}" -f $type, $name) $adsiRs = $localSAM.Delete($type, $name) $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Test-LocalUserEnabled { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Boolean])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'SilentContinue' [bool] $isEnabled = $false } process { try { Write-Verbose ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}/{1},user' -f $computerName, $name) -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $localSAM.Path) $isEnabled = -not ($originalUAC -band 2) $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $isEnabled } } function Rename-LocalObject { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $oldName, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $newName, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}/{1},user' -f $computerName, $oldName) -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $localSAM.Path) Write-Verbose ('Rename local object: from = {0} | to = {1}' -f $oldName, $newName) $localSAM.psbase.rename($newName) $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Protect-HmacSha256 { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [Security.SecureString] $password, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [byte[]] $bytesToHmac ) begin { [string] $outHmac = '' [IntPtr] $unmanagedString = [IntPtr]::Zero $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'SilentContinue' } process { try { Write-Verbose ('Signing bytes: {0}' -f $bytesToHmac.Count) $unmanagedString = [Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($password) $outHmac = [BitConverter]::ToString( (New-Object System.Security.Cryptography.HMACSHA256 @(,` ([Text.Encoding]::UTF8.GetBytes([Runtime.InteropServices.Marshal]::PtrToStringUni($unmanagedString)) * ` [Math]::Ceiling((64 / $password.Length))))).ComputeHash($bytesToHmac) ) [Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($unmanagedString) } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outHmac } } function Convert-UserNameToSid { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $userName, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $domain ) process { return ((New-Object System.Security.Principal.NTAccount($domain, $userName)).` Translate([System.Security.Principal.SecurityIdentifier])).Value } } function Convert-SidToUserName { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $sidString ) process { return ((New-Object System.Security.Principal.SecurityIdentifier($sidString)).` Translate( [System.Security.Principal.NTAccount])).Value } } function Compress-GZip { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $compressed = $null [byte[]] $sourceToZip = $encoding.GetBytes($text) } process { try { $zippedMem = New-Object IO.MemoryStream $zipper = New-Object IO.Compression.GZipStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Compress, $true) [void] $zipper.Write($sourceToZip, 0, $sourceToZip.Length) $zipper.Close() $zipper.Dispose() $compressed = $zippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return [Convert]::ToBase64String($compressed) } } function Expand-GZip { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $compressedInBase64, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToUnzip = [Convert]::FromBase64String($compressedInBase64) [byte[]] $decompressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream [void] $zippedMem.Write($sourceToUnzip, 0, $sourceToUnzip.Length) [void] $zippedMem.Seek(0, 'Begin') $unzip = New-Object IO.Compression.GZipStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Decompress, $true) $unzippedMem = New-Object IO.MemoryStream [byte[]] $buffer = New-Object byte[] 64 [int] $read = $unzip.Read($buffer, 0, $buffer.Length) while ($read -gt 0) { [void] $unzippedMem.Write($buffer, 0, $read) $read = $unzip.Read($buffer, 0, $buffer.Length) } $unzip.Close() $unzip.Dispose() $decompressed = $unzippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $encoding.GetString($decompressed) } } function Compress-Deflate { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToZip = $encoding.GetBytes($text) [byte[]] $compressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream $zipper = New-Object IO.Compression.DeflateStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Compress, $true) [void] $zipper.Write($sourceToZip, 0, $sourceToZip.Length) $zipper.Close() $zipper.Dispose() $compressed = $zippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return [Convert]::ToBase64String($compressed) } } function Expand-Deflate { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $compressedInBase64, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToUnzip = [Convert]::FromBase64String($compressedInBase64) [byte[]] $decompressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream [void] $zippedMem.Write($sourceToUnzip, 0, $sourceToUnzip.Length) [void] $zippedMem.Seek(0, 'Begin') $unzip = New-Object IO.Compression.DeflateStream ($zippedMem, [System.IO.Compression.CompressionMode]::Decompress, $true) $unzippedMem = New-Object IO.MemoryStream [byte[]] $buffer = New-Object byte[] 64 [int] $read = $unzip.Read($buffer, 0, $buffer.Length) while ($read -gt 0) { [void] $unzippedMem.Write($buffer, 0, $read) $read = $unzip.Read($buffer, 0, $buffer.Length) } $unzip.Close() $unzip.Dispose() $decompressed = $unzippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $encoding.GetString($decompressed) } } function Get-UserNameFromLogin { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $loginSamOrUpn ) process { if($loginSamOrUpn -like "*\*") { return $loginSamOrUpn.Split('\')[0] } elseif($loginSamOrUpn -like "*@*") { return $loginSamOrUpn.Split('@')[0] } else { return $loginSamOrUpn } } } function Get-DomainFromLogin { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $loginSamOrUpn ) process { if($loginSamOrUpn -like "*\*") { return $loginSamOrUpn.Split('\')[1] } elseif($loginSamOrUpn -like "*@*") { return $loginSamOrUpn.Split('@')[1] } else { return $null } } } function Enable-WindowsAutologon { [CmdletBinding(SupportsShouldProcess = $false)] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [Management.Automation.PSCredential] $credentials ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose 'Registering autologon.' Set-RegistryValue -keyPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` -Name AutoAdminLogon -Value 1 -Type Dword -Verbose:$VerbosePreference Set-RegistryValue -keyPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` -Name AutoLogonCount -Value 2 -Type DWord -Verbose:$VerbosePreference Set-RegistryValue -keyPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` -Name DefaultPassword -Value ($credentials.GetNetworkCredential().Password) -Type String -Verbose:$VerbosePreference Set-RegistryValue -keyPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` -Name DefaultUserName -Value (Get-UserNameFromLogin -loginSamOrUpn $credential.UserName) -Type String -Verbose:$VerbosePreference if (-not ([string]::IsNullOrEmpty((Get-DomainFromLogin -loginSamOrUpn $domain)))) { Set-RegistryValue -keyPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` -Name DefaultDomainName -Value $domain -Type String -Verbose:$VerbosePreference } Write-Verbose 'Autologon registered.' } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Disable-WindowsAutologon { [CmdletBinding(SupportsShouldProcess = $false)] param() begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose 'Removing autologon.' Remove-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` AutoAdminLogon -Force Remove-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` AutoLogonCount -Force Remove-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` DefaultPassword -Force Remove-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` DefaultUserName -Force Remove-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' ` DefaultDomainName -Force Write-Verbose 'Autologon removed.' } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-NextFreeDriveLetter { [CmdletBinding(SupportsShouldProcess = $false)] param() begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $drvLetter = [int][char]'C' $nextFDL = $null } process { try { while ((Get-PSDrive -PSProvider filesystem).Name -contains [char]$drvLetter) { $drvLetter++ } $nextFDL = ([char]$drvLetter) } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $nextFDL } } function Get-CurrentIdentityInformation { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([PSObject])] param() begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $out = New-Object PSObject } process { try { $currentPrincipal = [Security.Principal.WindowsIdentity]::GetCurrent($false) [Security.Principal.WindowsIdentity] $threadIdentityOnlyIfImpersonating = $null $threadIdentityOnlyIfImpersonating = [Security.Principal.WindowsIdentity]::GetCurrent($true) $runningIdentity = [Security.Principal.WindowsIdentity]::GetCurrent($false) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Running under username' ` -Value ($currentPrincipal.Name) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Running under SID' ` -Value ($currentPrincipal.User.Value) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Thread IsImpersonating' ` -Value ([bool] $threadIdentityOnlyIfImpersonating) Add-Member -InputObject $out -MemberType NoteProperty -Name 'RunningIdentity username' ` -Value ($runningIdentity.Name) Add-Member -InputObject $out -MemberType NoteProperty -Name 'RunningIdentity SID' ` -Value ($runningIdentity.User) Add-Member -InputObject $out -MemberType NoteProperty -Name 'AuthenticationType' ` -Value ($runningIdentity.AuthenticationType) Add-Member -InputObject $out -MemberType NoteProperty -Name 'IsSystem' ` -Value ($runningIdentity.IsSystem) Add-Member -InputObject $out -MemberType NoteProperty -Name 'IsAnonymous' ` -Value ($runningIdentity.IsAnonymous) Add-Member -InputObject $out -MemberType NoteProperty -Name 'IsAuthenticated' ` -Value ($runningIdentity.IsAuthenticated) Add-Member -InputObject $out -MemberType NoteProperty -Name 'IsGuest' ` -Value ($runningIdentity.IsGuest) foreach ($oneSID in ($runningIdentity.Groups | Select-Object -Expand Value )) { Add-Member -InputObject $out -MemberType NoteProperty -Name ('In GROUP: {0}' -f (Convert-SidToUserName $oneSid)) ` -Value $oneSID } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $out } } function Find-InDirectoryService { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [System.DirectoryServices.DirectoryEntry] $rootObj, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $filter, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string[]] $properties ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [ADSISearcher] $searcher = New-Object System.DirectoryServices.DirectorySearcher [System.DirectoryServices.SearchResultCollection] $searchRes = $null $returner = $null } process { try { Write-Verbose ('Search root DN: {0}' -f $rootObj.Path) $searcher.SearchRoot = $rootObj $searcher.CacheResults = $true #$searcher.PageSize = 5000 $searcher.SearchScope = 'subTree' $searcher.Asynchronous = $true $searcher.Filter = $filter if ($properties) { $properties | ForEach-Object { [void] $searcher.PropertiesToLoad.Add($_) } } $searchRes = $searcher.FindAll() $returner = New-Object PSCustomObject $returner | Add-Member -Member NoteProperty -Name searcher -Value $searcher $returner | Add-Member -Member NoteProperty -Name found -Value (($searchRes) -and ($searchRes.Count -gt 0)) $returner | Add-Member -Member NoteProperty -Name result -Value $searchRes Write-Verbose ('Found matching objects: {0} | {1}' -f $returner.found, $returner.result.Count) $searcher.Dispose() [GC]::Collect() [GC]::WaitForPendingFinalizers() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $returner } } function Get-DirectoryEntryObjectProperty { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [System.DirectoryServices.DirectoryEntry] $de ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $propObj = $null } process { try { Write-Verbose ('Getting list properties: {0}' -f $de.Path) $props = $de | Get-Member | Where-Object { $_.MemberType -eq 'Property'} | Select-Object -ExpandProperty Name $propObj = New-Object PSCustomObject foreach ($prop in $props) { $propObj | Add-Member -MemberType NoteProperty -Name $prop -Value $de.Properties[$prop] } $de.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $propObj } } function Test-IsComputerDomainMember { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Boolean])] param () begin { [bool] $isDomainMember = $false } process { try { $wmiObj = Get-WmiObject -Query 'SELECT * FROM Win32_ComputerSystem' if ($wmiObj.partofdomain -eq 'True') { $isDomainMember = $true } else { $isDomainMember = $false } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $isDomainMember } } function New-EmptyFileWithSize { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $path, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [int64] $sizeInBytes ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, $path)) { $newFile = [System.IO.File]::Create($path) if ($newFile) { $newFile.SetLength($sizeInBytes) $newFile.Dispose() } else { throw 'Error during creating file.' } } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Copy-Acl { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $sourcePath, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $targetPath ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose ('Get source path ACL of the source path: {0}' -f $sourcePath) $sourceACL = Get-Acl $sourcePath Write-Verbose ('Obtain new owner') $newOwner = New-Object System.Security.Principal.NTAccount('BUILTIN\Administrators') Write-Verbose ('Change owner of the ACL') $sourceACL.SetOwner($newOwner) Write-Verbose ('Disable inheritance in the ACL') $sourceACL.SetAccessRuleProtection($true, $true) Write-Verbose ('Apply the ACL to the target path: {0}' -f $targetPath) Set-Acl $targetPath -AclObject $sourceACL } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Backup-ScheduleTask { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $path, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $taskPath = '\' ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Get-ScheduledTask -TaskPath $taskPath | ForEach-Object { Write-Verbose ('Exporting task name: {0} -> {1}' -f $_.TaskName, ` (Join-Path $path "$($_.TaskName).xml")) Export-ScheduledTask -TaskName $_.TaskName -TaskPath $_.TaskPath -Verbose:$VerbosePreference | Out-File (Join-Path $path "$($_.TaskName).xml") } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Restore-ScheduleTask { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $inputPath, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [Management.Automation.PSCredential] $credentials, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $destinationSchedulerFolder = '\' ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $tasks = Get-ChildItem -Path $inputPath -Filter *.xml -Force Write-Verbose ('Found tasks to import: {0}' -f $tasks.Count) foreach ($task in $tasks) { $taskName = [System.IO.Path]::GetFileNameWithoutExtension($task) Write-Verbose ('Import task: {0} | {1}' -f $taskName, $task.FullName) Register-ScheduledTask -Xml (Get-Content $task.FullName | Out-String) -TaskName $taskName �User $credentials.UserName ` �Password ($credentials.GetNetworkCredential().Password) -TaskPath $destinationSchedulerFolder -Force -Verbose:$VerbosePreference | Out-Null Write-Verbose ('Disable task: {0}' -f $taskName) Disable-ScheduledTask -TaskName $TaskName -taskPath $destinationSchedulerFolder -Verbose:$VerbosePreference | Out-Null } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Set-WindowsEventLogForTaskScheduler { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $false)] [ValidateNotNull()] [bool] $enable ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try{ if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, $enable)) { $logName = 'Microsoft-Windows-TaskScheduler/Operational' $eventLog = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $logName $eventLog.IsEnabled = $enable $eventLog.SaveChanges() $eventLog.Dispose() [GC]::Collect() [GC]::WaitForPendingFinalizers() Write-Verbose ('Windows event log for Task scheduler enable: {0}' -f $enable) } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-MSSQLQueryResult { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([Data.DataTable])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string] $serverPlusInstance, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [string] $query, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [string] $database = 'Master', [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNull()] [bool] $encrypt ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $dataTable = $null } process { try{ Write-Verbose ('Going to connect to: SRV = {0} | DB = {1} | Encrypt = {2}' -f $serverPlusInstance, $database, $encrypt) $connString = 'Server={0};Database={1};Integrated Security=True;Encrypt={2};Pooling=false' -f $serverPlusInstance, $database, $encrypt Write-Verbose ('Connection string: {0}' -f $connString) $conn = New-Object Data.SqlClient.SqlConnection $connString $conn.Open() if ($conn) { Write-Verbose ('Server version: {0}' -f $conn.ServerVersion) Write-Verbose ('Workstation ID: {0}' -f $conn.WorkstationId) Write-Verbose ('Client connection ID: {0}' -f $conn.ClientConnectionId) Write-Verbose ('Connection timeout: {0} sec' -f $conn.ConnectionTimeout) $cmd = $conn.CreateCommand() $cmd.CommandText = $query $reader = $cmd.ExecuteReader() if ((-not $reader.IsClosed) -and $reader.HasRows) { Write-Verbose ('Load the data table into memory') $dataTable = New-Object Data.DataTable $dataTable.Load($reader) Write-Verbose ('Query returned: rows = {0}' -f $dataTable.Rows.Count) } $reader.Close() } $conn.Close() $conn.Dispose() return $dataTable } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Import-WindowsAPI { [CmdletBinding(SupportsShouldProcess = $false)] param () begin { $win32api = @' using System; using System.Runtime.InteropServices; using System.Text; namespace Win32Api { [StructLayout(LayoutKind.Sequential)] public struct LUID { public uint LowPart; public int HighPart; } [StructLayout(LayoutKind.Sequential)] public struct LUID_AND_ATTRIBUTES { public LUID Luid; public UInt32 Attributes; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_PRIVILEGES { public UInt32 PrivilegeCount; public LUID Luid; public UInt32 Attributes; } public class Kernel32 { public const uint DELETE = 0x00010000; public const uint READ_CONTROL = 0x00020000; public const uint WRITE_DAC = 0x00040000; public const uint WRITE_OWNER = 0x00080000; public const uint SYNCHRONIZE = 0x00100000; public const uint STANDARD_RIGHTS_ALL = ( READ_CONTROL | WRITE_OWNER | WRITE_DAC | DELETE | SYNCHRONIZE ); public const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000u; public const uint STANDARD_RIGHTS_READ = 0x00020000u; public const uint PROCESS_TERMINATE = 0x0001; public const uint PROCESS_CREATE_THREAD = 0x0002; public const uint PROCESS_VM_OPERATION = 0x0008; public const uint PROCESS_VM_READ = 0x0010; public const uint PROCESS_VM_WRITE = 0x0020; public const uint PROCESS_DUP_HANDLE = 0x0040; public const uint PROCESS_CREATE_PROCESS = 0x0080; public const uint PROCESS_SET_QUOTA = 0x0100; public const uint PROCESS_SET_INFORMATION = 0x0200; public const uint PROCESS_QUERY_INFORMATION = 0x0400; public const uint PROCESS_SUSPEND_RESUME = 0x0800; public const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000; public const uint PROCESS_ALL_ACCESS = ( STANDARD_RIGHTS_ALL | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_SET_QUOTA | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE ); [DllImport("kernel32.dll", SetLastError=true, ExactSpelling = true)] public static extern IntPtr OpenProcess(uint DesiredAccess, bool InheritHandle, int ProcessId); [DllImport("kernel32.dll", SetLastError=true, ExactSpelling = true)] public static extern IntPtr GetCurrentThread(); [DllImport("Kernel32.dll", SetLastError=true)] public static extern bool CloseHandle(IntPtr handle); [DllImport("Kernel32.dll")] public static extern uint GetLastError(); [DllImport("Kernel32.dll")] public static extern void SetLastError(int errCode); [DllImport("kernel32.dll", SetLastError=true, ExactSpelling = true)] public static extern IntPtr GetCurrentProcess(); } public class AdvAPI32 { public const uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001u; public const uint SE_PRIVILEGE_ENABLED = 0x00000002u; public const uint SE_PRIVILEGE_REMOVED = 0x00000004u; public const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000u; public const uint TOKEN_QUERY = 0x00000008; public const uint TOKEN_ADJUST_PRIVILEGES = 0x00000020; public const uint TOKEN_ASSIGN_PRIMARY = 0x00000001u; public const uint TOKEN_DUPLICATE = 0x00000002u; public const uint TOKEN_IMPERSONATE = 0x00000004u; public const uint TOKEN_QUERY_SOURCE = 0x00000010u; public const uint TOKEN_ADJUST_GROUPS = 0x00000040u; public const uint TOKEN_ADJUST_DEFAULT = 0x00000080u; public const uint TOKEN_ADJUST_SESSIONID = 0x00000100u; public const uint TOKEN_READ = ( Win32Api.Kernel32.STANDARD_RIGHTS_READ | TOKEN_QUERY ); public const uint TOKEN_ALL_ACCESS = ( Win32Api.Kernel32.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 enum SECURITY_IMPERSONATION_LEVEL:int { SecurityAnonymous = 0, SecurityIdentification = 1, SecurityImpersonation = 2, SecurityDelegation = 3 } [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool LookupPrivilegeValue( string lpSystemName, string lpName, out LUID lpLuid); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool OpenProcessToken( IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool OpenThreadToken( IntPtr ThreadHandle, UInt32 DesiredAccess, bool OpenAsSelf, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool AdjustTokenPrivileges( IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, UInt32 BufferLengthInBytes, IntPtr PreviousStateNull, IntPtr ReturnLengthInBytesNull); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool DuplicateToken( IntPtr ExistingTokenHandle, int ImpersonationLevel, out IntPtr DuplicateTokenHandle); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool SetThreadToken(IntPtr Thread, IntPtr Token); [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool RevertToSelf(); [DllImport("advapi32.dll", CharSet = CharSet.Auto)] public static extern int RegOpenKeyEx( int hKey, string subKey, int ulOptions, int samDesired, out int hkResult); [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")] extern public static int RegEnumKeyEx( int hkey, int index, StringBuilder lpName, ref int lpcbName, int reserved, StringBuilder lpClass, ref int lpcbClass, out long lpftLastWriteTime); [DllImport("advapi32.dll", EntryPoint="RegQueryInfoKey", CallingConvention=CallingConvention.Winapi, SetLastError=true)] extern public static int RegQueryInfoKey( int hkey, StringBuilder lpClass, ref int lpcbClass, int lpReserved, out int lpcSubKeys, out int lpcbMaxSubKeyLen, out int lpcbMaxClassLen, out int lpcValues, out int lpcbMaxValueNameLen, out int lpcbMaxValueLen, out int lpcbSecurityDescriptor, IntPtr lpftLastWriteTime); [DllImport("advapi32.dll", SetLastError=true)] public static extern int RegCloseKey(int hKey); } public class Shift { public static int Right(int x, int count) { return x >> count; } public static uint Right(uint x, int count) { return x >> count; } public static long Right(long x, int count) { return x >> count; } public static ulong Right(ulong x, int count) { return x >> count; } public static int Left(int x, int count) { return x << count; } public static uint Left(uint x, int count) { return x << count; } public static long Left(long x, int count) { return x << count; } public static ulong Left(ulong x, int count) { return x << count; } } } '@ } process { try { if (-not ('Win32Api.AdvAPI32' -as [type])) { Write-Verbose ('Define the new type.') [void] (Add-Type -TypeDefinition $win32api -Verbose:$VerbosePreference) } else { Write-Verbose ('The type already exists. Skipping.') } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Convert-PrivilegeNameToInt { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([int])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string] $privilegeName ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [int] $result = -1 } process { try { Import-WindowsAPI -Verbose:$VerbosePreference [Win32Api.LUID] $privilegeValue = New-Object Win32Api.LUID $resBool = [Win32Api.AdvAPI32]::LookupPrivilegeValue($null, $privilegeName, [ref] $privilegeValue) Write-Verbose ('WIN32API Result: {0}'-f $resBool) if ($resBool) { Write-Verbose ('Privilege value: {0} = {1}, {2}' -f $privilegeName, $privilegeValue.LowPart, ` $privilegeValue.HighPart) $result = [int] $privilegeValue.LowPart } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $result } } function Set-TokenPrivilege { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [int] $privilege, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [bool] $enable = $true ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Setting token privileges")) { Import-WindowsAPI -Verbose:$VerbosePreference [IntPtr] $accessToken = New-Object IntPtr Write-Verbose ('Should try OpenThreadToken() first to try if we are not impersonating') $result = [Win32Api.AdvAPI32]::OpenThreadToken(([Win32Api.Kernel32]::GetCurrentThread()), ` ([Win32Api.AdvAPI32]::TOKEN_ADJUST_PRIVILEGES + [Win32Api.AdvAPI32]::TOKEN_QUERY), $false, ` ([ref] $accessToken)) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('Win32 last error: {0}' -f $lastError) Write-Verbose ('Thread token opened: bool = {0} | token = {1:X8}' -f $result, ([int] $accessToken)) if (-not $result) { Write-Verbose ('Must go for OpenProcessToken()') $result = [Win32Api.AdvAPI32]::OpenProcessToken(([Win32Api.Kernel32]::GetCurrentProcess()), ` ([Win32Api.AdvAPI32]::TOKEN_ADJUST_PRIVILEGES + [Win32Api.AdvAPI32]::TOKEN_QUERY), ` ([ref] $accessToken)) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('Win32 last error: {0}' -f $lastError) Write-Verbose ('Process token opened: bool = {0} | token = {1:X8}' -f $result, ([int] $accessToken)) } else { Write-Verbose ('Thread token opened ok, will not try OpenProcessToken()') } if (($accessToken -ne [IntPtr]::Zero) -and ($accessToken -ne -1)) { [Win32Api.TOKEN_PRIVILEGES] $tokenPrivileges = New-Object Win32Api.TOKEN_PRIVILEGES $tokenPrivileges.PrivilegeCount = 1 $newLuid = $tokenPrivileges.Luid $newLuid.LowPart = $privilege $newLuid.HighPart = 0 $tokenPrivileges.Luid = $newLuid if ($enable) { $tokenPrivileges.Attributes = [Win32Api.AdvAPI32]::SE_PRIVILEGE_ENABLED } else { $tokenPrivileges.Attributes = 0 } Write-Verbose ('Call AdjustTokenPrivileges()') $result = [Win32Api.AdvAPI32]::AdjustTokenPrivileges($accessToken, $false, ([ref] $tokenPrivileges), ` ([System.Runtime.InterOpServices.Marshal]::SizeOf($tokenPrivileges)), [IntPtr]::Zero, [IntPtr]::Zero) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) } Write-Verbose ('Disposing handle: {0}' -f $accessToken) $result = [Win32Api.Kernel32]::CloseHandle($accessToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Copy-ProcessToken { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string] $process ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $theProcess = $null } process { try { Import-WindowsAPI -Verbose:$VerbosePreference Write-Verbose ('Get the process: {0}' -f $process) $theProcess = Get-Process -Name $process Write-Verbose ('Will duplicate process token for ID: {0}' -f $theProcess.Id) Set-TokenPrivilege -privilege (Convert-PrivilegeNameToInt -privilegeName SeDebugPrivilege -Verbose:$VerbosePreference) -Verbose:$VerbosePreference Write-Verbose ('Open process handle') [IntPtr] $procHandle = [IntPtr]::Zero $procHandle = [Win32Api.Kernel32]::OpenProcess(([Win32Api.Kernel32]::PROCESS_ALL_ACCESS), $false, $theProcess.Id) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('Process handle opened: {0}' -f $procHandle) Write-Verbose ('Win32 last error: {0}' -f $lastError) if (($procHandle -ne [IntPtr]::Zero) -and ($procHandle -ne -1)) { Write-Verbose ('Open process access token with READ_CONTROL') [IntPtr] $procToken = [IntPtr]::Zero $result = [Win32Api.AdvAPI32]::OpenProcessToken($procHandle, ([Win32Api.Kernel32]::READ_CONTROL), [ref] $procToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) if (($procToken -ne [IntPtr]::Zero) -and ($procToken -ne -1)) { Write-Verbose ('Open process access token to DUPLICATE') [IntPtr] $procToken = [IntPtr]::Zero $result = [Win32Api.AdvAPI32]::OpenProcessToken($procHandle, ([Win32Api.AdvAPI32]::TOKEN_IMPERSONATE -bor ` [Win32Api.AdvAPI32]::TOKEN_DUPLICATE -bor [Win32Api.AdvAPI32]::TOKEN_QUERY -bor ` [Win32Api.AdvAPI32]::TOKEN_QUERY_SOURCE -bor [Win32Api.AdvAPI32]::TOKEN_READ), [ref] $procToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) Write-Verbose ('Process token opened: {0}' -f $procToken) if (($procToken -ne [IntPtr]::Zero) -and ($procToken -ne -1)) { [IntPtr] $dulicatedProcToken = [IntPtr]::Zero Write-Verbose ('Duplicate process token') $result = [Win32Api.AdvAPI32]::DuplicateToken($procToken, ` [Win32Api.AdvAPI32+SECURITY_IMPERSONATION_LEVEL]::SecurityImpersonation, ` [ref] $dulicatedProcToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) Write-Verbose ('Duplicated process token: {0}' -f $dulicatedProcToken) if (($dulicatedProcToken -ne [IntPtr]::Zero) -and ($dulicatedProcToken -ne -1)) { Write-Verbose ('Set current thread token to the duplicated one') $result = [Win32Api.AdvAPI32]::SetThreadToken([IntPtr]::Zero, $dulicatedProcToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) Write-Verbose ('Disposing handle: {0}' -f $dulicatedProcToken) $result = [Win32Api.Kernel32]::CloseHandle($dulicatedProcToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) Get-CurrentIdentityInformation -Verbose:$VerbosePreference } } Write-Verbose ('Disposing handle: {0}' -f $procToken) $result = [Win32Api.Kernel32]::CloseHandle($procToken) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) } Write-Verbose ('Disposing handle: {0}' -f $procHandle) $result = [Win32Api.Kernel32]::CloseHandle($procHandle) $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Restore-Self { [CmdletBinding(SupportsShouldProcess = $true)] param () begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Reverting to self")) { Import-WindowsAPI -Verbose:$VerbosePreference Write-Verbose ('Revert to self') $result = [Win32Api.AdvAPI32]::RevertToSelf() $lastError = [Win32Api.Kernel32]::GetLastError() Write-Verbose ('WIN32API Result: {0}' -f $result) Write-Verbose ('Win32 last error: {0}' -f $lastError) Get-CurrentIdentityInformation -Verbose:$VerbosePreference } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Invoke-AsSystem { [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [scriptblock] $code ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $result = $null } process { try { Copy-ProcessToken -process lsass -Verbose:$VerbosePreference Write-Verbose ('Invoke the code') $result = $code.Invoke() Restore-Self -Verbose:$VerbosePreference } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $result } } function Get-RegKeyClass { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.String])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('HKCR','HKCU','HKLM','HKU','HKCC')] [string] $key, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [string] $subKey ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' switch ($key) { 'HKCR' { $nKey = 0x80000000} #HK Classes Root 'HKCU' { $nKey = 0x80000001} #HK Current User 'HKLM' { $nKey = 0x80000002} #HK Local Machine 'HKU' { $nKey = 0x80000003} #HK Users 'HKCC' { $nKey = 0x80000005} #HK Current Config } $keyRead = 0x19; $result = ''; [int] $hKey = 0 } process { try { Import-WindowsAPI -Verbose:$VerbosePreference if (-not ([Win32Api.AdvAPI32]::RegOpenKeyEx($nKey, $subKey, 0, $keyRead, [ref] $hKey))) { $classVal = New-Object Text.Stringbuilder 1024 [int] $len = 1024 if (-not ([Win32Api.AdvAPI32]::RegQueryInfoKey($hKey, $classVal, [ref]$len, 0, [ref]$null, ` [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, 0))) { $result = $classVal.ToString() } else { throw 'RegQueryInfoKey() failed' } [Win32Api.AdvAPI32]::RegCloseKey($hKey) | Out-Null } else { throw ('Cannot open key: {0}:\{1}' -f $key, $subKey) } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $result } } function Get-BootKey { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Object[]])] param () begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $s = [string]::Join('', $('JD','Skew1','GBG','Data' | ForEach-Object { Get-RegKeyClass -Key "HKLM" -SubKey "SYSTEM\CurrentControlSet\Control\Lsa\$_" })); $b = New-Object byte[] $($s.Length/2) 0..$($b.Length - 1) | ForEach-Object { $b[$_] = [Convert]::ToByte($s.Substring($($_*2), 2), 16) } $b2 = New-Object byte[] 16 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 | ` ForEach-Object -begin { $i = 0; }{ $b2[$i] = $b[$_]; $i++} return ,$b2; } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-RC4 { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([byte[]])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [byte[]] $key ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { return New-Object Object | Add-Member NoteProperty key $key -PassThru | Add-Member NoteProperty S $null -PassThru | Add-Member ScriptMethod init { if (-not ($this.S)) { [byte[]]$this.S = 0..255 0..255 | ForEach-Object -begin{ [long]$j = 0; } { $j = ($j + $this.key[$($_ % $this.key.Length)] + $this.S[$_]) % $this.S.Length; $temp = $this.S[$_]; $this.S[$_] = $this.S[$j]; $this.S[$j] = $temp } } } -PassThru | Add-Member ScriptMethod "encrypt" { $data = $args[0] $this.init() $outbuf = New-Object byte[] $($data.Length); $S2 = $this.S[0..$this.S.Length] 0..$($data.Length - 1) | ForEach-Object -begin{ $i=0; $j=0; } { $i = ($i+1) % $S2.Length $j = ($j + $S2[$i]) % $S2.Length $temp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $temp $a = $data[$_] $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ] $outbuf[$_] = ($a -bxor $b) } return ,$outbuf; } -PassThru } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-HBootKey { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [byte[]] $bootKey ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $qwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0") $num = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0") } process { try { Copy-ProcessToken -process lsass -Verbose:$VerbosePreference | Out-Null $key = Get-Item HKLM:\SAM\SAM\Domains\Account if (-not ($key)) { return $null } [byte[]]$F = $key.GetValue("F") if (-not ($F)) { return $null } $rc4 = Get-RC4 -key ([Security.Cryptography.MD5]::Create().` ComputeHash($F[0x70..0x7F] + $qwerty + $bootKey + $num)) return ,($rc4.encrypt($F[0x80..0x9F])) } catch { throw; } finally { Restore-Self -Verbose:$VerbosePreference | Out-Null $ErrorActionPreference = $eaPreferencesBackup } } } function Protect-DESCipher { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [byte[]] $data, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [byte[]] $key ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $result = $null } process { try { $desProv = New-Object Security.Cryptography.DESCryptoServiceProvider $desProv.Mode = [Security.Cryptography.CipherMode]::ECB $desProv.Padding = [Security.Cryptography.PaddingMode]::None $desProv.Key = $key; $desProv.IV = $key; $result = ($desProv.CreateEncryptor()).TransformFinalBlock($data, 0, $data.Length); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return ,$result } } function UnProtect-DESCipher { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [byte[]] $data, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [byte[]] $key ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $result = $null } process { try { $desProv = New-Object Security.Cryptography.DESCryptoServiceProvider $desProv.Mode = [Security.Cryptography.CipherMode]::ECB $desProv.Padding = [Security.Cryptography.PaddingMode]::None $desProv.Key = $key; $desProv.IV = $key; $result = ($desProv.CreateDecryptor()).TransformFinalBlock($data, 0, $data.Length); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return ,$result } } function Test-TlsConnection { [CmdletBinding(SupportsShouldProcess = $false)] [OutputType([PSObject])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string] $hostName, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [int] $port ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $out = New-Object PSObject } process { try { Write-Verbose ('Going to connect to: {0} | {1}' -f $hostName, $port) [System.Net.Sockets.TcpClient] $client = New-Object System.Net.Sockets.TcpClient $hostName, $port if ($client) { Write-Verbose ('Connected to: {0} | {1}' -f $hostName, $port) [System.IO.Stream] $netStream = $client.GetStream() [System.Net.Security.SslStream] $sslStream = New-Object System.Net.Security.SslStream $netStream, $false if ($sslStream) { Write-Verbose ('Start SSL session: {0}' -f $hostName) $sslStream.AuthenticateAsClient($hostName) if ($sslStream.IsAuthenticated) { $out = New-Object PSObject Add-Member -InputObject $out -MemberType NoteProperty -Name 'Protocol' ` -Value ($sslStream.SslProtocol) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Cipher algorithm' ` -Value ($sslStream.CipherAlgorithm) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Cipher strength' ` -Value ($sslStream.CipherStrength) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Hash algorithm' ` -Value ($sslStream.HashAlgorithm) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Hash strength' ` -Value ($sslStream.HashStrength) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Key exchange algorithm' ` -Value ($sslStream.KeyExchangeAlgorithm) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Key exchange strength' ` -Value ($sslStream.KeyExchangeStrength) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Server certificate thumbprint' ` -Value (($sslStream.RemoteCertificate).GetCertHashString()) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Server certificate subject' ` -Value (($sslStream.RemoteCertificate).Subject) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Server certificate issuer' ` -Value (($sslStream.RemoteCertificate).Issuer) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Server certificate not after' ` -Value ([DateTime]::Parse(($sslStream.RemoteCertificate).GetExpirationDateString())) Add-Member -InputObject $out -MemberType NoteProperty -Name 'Server certificate not before' ` -Value ([DateTime]::Parse(($sslStream.RemoteCertificate).GetEffectiveDateString())) } $sslStream.Close() $sslStream.Dispose() $netStream.Close() $netStream.Dispose() } Write-Verbose 'Close TLS session.' $client.Close() } else { throw 'Connection failed.' } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $out } } if ((-not ($psISE.CurrentPowerShellTab.AddOnsMenu.Submenus | Where-Object DisplayName -eq 'Sign open scripts')) ` -and ($host.name -eq 'Windows PowerShell ISE Host')) { $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('Sign open scripts', ` { Add-SignatureInISE }, 'Ctrl+Shift+S') | Out-Null } if ((-not ($psISE.CurrentPowerShellTab.AddOnsMenu.Submenus | Where-Object DisplayName -eq 'Clear ISE open file history')) ` -and ($host.name -eq 'Windows PowerShell ISE Host')) { $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('Clear ISE open file history', ` { Clear-ISEHistory }, 'Ctrl+Shift+C') | Out-Null } # SIG # Begin signature block # MIITBQYJKoZIhvcNAQcCoIIS9jCCEvICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUTby92V+kXEM+Clot2ZyVi6L5 # dz6ggg5rMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B # AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG # A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh # d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg # Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV # UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu # dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q # WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC # i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4 # ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3 # +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI # fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd # BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG # CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB # Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro # YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV # HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y # MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf # plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y # 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq # IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3 # DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh # dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD # QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE # BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT # eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow # mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0 # jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu # ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh # d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz # C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB # o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO # BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw # Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90 # cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx # oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy # bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV # HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa # 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH # bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73 # BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR # EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW # yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu # e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw # ggXOMIIEtqADAgECAgocYLQHAAAAAAMMMA0GCSqGSIb3DQEBCwUAMEYxFTATBgoJ # kiaJk/IsZAEZFgVsb2NhbDEUMBIGCgmSJomT8ixkARkWBHBvcnMxFzAVBgNVBAMT # DnBvcnMtREItU1JWLUNBMB4XDTE2MDQyNjExNTUwOVoXDTE4MDQyNjExNTUwOVow # gY8xFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEUMBIGCgmSJomT8ixkARkWBHBvcnMx # DjAMBgNVBAsTBUZpcm1hMRQwEgYDVQQLEwtaYW1lc3RuYW5jaTEYMBYGA1UEAxMP # TWlyb3NsYXYgTWVkdW5hMSAwHgYJKoZIhvcNAQkBFhFtZWR1bmFAcG9ycy1zdy5j # ejCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALetZGc/1Qa91Sj5NcbI # FjpqMfJMwEMnvmOzFWqA6+6K9X0732GcgKtyXqw0LitY1XZDEppxBTlivPHXVVsb # Y1cLqWsdICAklMdq9JWybVDSUiPhog5QIm107hx/xBOqdAGoksToFoUOOkrwB6yt # OZXbpiGSs4j7n64Z2zn5dZU5IafaZ4Z2OizLnjaNS+44h3v1FWKnEAVweynu0KSq # DtOi5cXEvbvFIK+/Ey0dzcZXY2vK0INxOlVvRtmJOv+0bRRFv6/Z1GHD8rHsL0oJ # yP5nquvHD3o0ikNpBcAXqEMl1emNxY0Qg4EvZLgOwKbxuE4P2dFulD56pgIISsC1 # XLMCAwEAAaOCAnIwggJuMD0GCSsGAQQBgjcVBwQwMC4GJisGAQQBgjcVCIOEoS6C # 59UEgbWVNoTN0CWG6fw/WYTdhUuHtfBuAgFkAgEEMBMGA1UdJQQMMAoGCCsGAQUF # BwMDMA4GA1UdDwEB/wQEAwIHgDAbBgkrBgEEAYI3FQoEDjAMMAoGCCsGAQUFBwMD # MB0GA1UdDgQWBBTvT3cMkc1mrLf8dyTScnKZkUbvAjAcBgNVHREEFTATgRFtZWR1 # bmFAcG9ycy1zdy5jejAfBgNVHSMEGDAWgBRbhvm5YOeWkaF1Awimwcg3cfuI/zCB # ygYDVR0fBIHCMIG/MIG8oIG5oIG2hoGzbGRhcDovLy9DTj1wb3JzLURCLVNSVi1D # QSxDTj1EQi1TUlYsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO # PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cG9ycyxEQz1sb2NhbD9jZXJ0 # aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJp # YnV0aW9uUG9pbnQwgb8GCCsGAQUFBwEBBIGyMIGvMIGsBggrBgEFBQcwAoaBn2xk # YXA6Ly8vQ049cG9ycy1EQi1TUlYtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUy # MFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cG9ycyxE # Qz1sb2NhbD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNh # dGlvbkF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAQEAl1Q1umCNlSbkV6pRaweZ # OBYZT2h6chfXaXtNeaELolOmXjzupXeGkykqmuytvKMC7TOZqdT/O1eccwoiBUlj # TTLK7ZKFXSI3ECwAYBpxCqW1pk88pK29jg7htvmPcOWETGWceTASlVnSD8s1bs/9 # 8GYaTqUlLMas47pARTekGdOZV3pSTLJzqC88/W+J3NOQiVTq88vpCcEoobsLYC4x # 2crHSxJCS3dYSsFV6l/Vs0ncOpLxAS3AJQ4yPKNu/EC2mXAnWJ/8DaJ8rtadBALL # UrCP/dfKEHbPwXWjxgU+t/LKzy9nf4ixXubmg0QR1z7eHgqQiR4AWkKVV6GFQIIf # fjGCBAQwggQAAgEBMFQwRjEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRQwEgYKCZIm # iZPyLGQBGRYEcG9yczEXMBUGA1UEAxMOcG9ycy1EQi1TUlYtQ0ECChxgtAcAAAAA # AwwwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZI # hvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcC # ARUwIwYJKoZIhvcNAQkEMRYEFN4HDZiRoowwRVGg7zo5Oi8KRNWuMA0GCSqGSIb3 # DQEBAQUABIIBAFwTs5knOPuc1B9k51BOcjwhDnBAvXrVhR2izV+o4MCyApKyZbSw # PCNtApaUe5RQvpHcmE5IRVxLpFRvQY+oIcvbECc48ErwaA4anEIBcZxcPqszmycI # LAUuFMipdVeDESD7Bf3farWu6vZdvXAmNAGBL4MpX+luRs6vwVCq1huSNMHzNulG # a9kQTQpcfCRHd8Jy1QcltJVePIWqV3VEqENAcEmtetVY5ymnoHDztgFmfv8aQDEE # SHsKTdKxM7hPchyxeupcBD7jxL97PyL6ads3ERi2zKoSjeXeDVeSqnoOx0OU4Z4S # WpsUUgTjZ+4Bb9tBUErs/rSEBWwRHk/bO/ihggILMIICBwYJKoZIhvcNAQkGMYIB # +DCCAfQCAQEwcjBeMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29y # cG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vydmlj # ZXMgQ0EgLSBHMgIQDs/0OMj+vzVuBNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZI # hvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTYwNTMxMTA0NzQ0 # WjAjBgkqhkiG9w0BCQQxFgQU9zI55593fGofnfChJOo3u3rtqEUwDQYJKoZIhvcN # AQEBBQAEggEAYxwbb7gYb7oOIkkCpYTadmklui7ivW9atqS28Eu2gbwq2eVruEBA # cYNe3KX2flmoQ2DdBJNp4Q6GvO0YQn7XAjcXtEt1Ty344Pzp8W7vYbZWKKVtGmQj # /nb6dETa5p62ojKJ97pWiJpeSpd2IcQPjGYH1RmIFLh65JwOmYgj/ty3Qf2pMCmR # Y450HkjfPObnzVCCKeTV6piNedgYyskHGkQ5NBfoCVs+yS/HSo6NrsfixI9b1mtw # Yb7XMKFklHeZcNzvBj8rET+xrqQmr2oL8Chways7eL1Ui0+Vr556Dx+ubhVXImly # QPrUh5LiSdg18Rc+Iv7lO997Q94F/TD6aQ== # SIG # End signature block |