Beaver.psm1
#Requires -Version 5.0 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)] param() begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $currentPrincipal = [Security.Principal.WindowsIdentity]::GetCurrent($false) Write-Output ('Running under: {0} = {1}' -f $currentPrincipal.Name, ` $currentPrincipal.User.Value) [Security.Principal.WindowsIdentity] $threadIdentityOnlyIfImpersonating = $null $threadIdentityOnlyIfImpersonating = [Security.Principal.WindowsIdentity]::GetCurrent($true) Write-Output ('This thread is impersonating: {0}' -f ([bool] $threadIdentityOnlyIfImpersonating)) $runningIdentity = [Security.Principal.WindowsIdentity]::GetCurrent($false) Write-Output ('Running identity: name = {0} | system = {1} | SID = {2}{3}' -f ` $runningIdentity.Name, $runningIdentity.IsSystem, $runningIdentity.User, [Environment]::NewLine) foreach ($oneSID in ($runningIdentity.Groups | Select-Object -Expand Value )) { Write-Output (' SID: {0} | {1}' -f $oneSID, (Convert-SidToUserName $oneSid)) } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } 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 } if ($enableHistory) { Write-Verbose ('Enabling the windows event log for the task scheduler') } } 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; 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(); } } '@ } 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-TokenPrivileges { [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-TokenPrivileges -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 } } 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 # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUNYBka7Hzyi17cjVqi3z3+Mly # ekWggg5rMIID7jCCA1egAwIBAgIQfpPr+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 # ARUwIwYJKoZIhvcNAQkEMRYEFOTPTfEUFddQKoGUjIHFLxCiGI++MA0GCSqGSIb3 # DQEBAQUABIIBAGLPj6d2m8BZWBSdExVTCN7eHASCq4TmaPU16VkKjuAQKzSM6pWG # VwgGT+xzYbE6SMmJCJ/U5aESX/Txm85rZm18NKi562KvPwIF+pHbufi5WHyYPDxZ # i22PhoZE7Sg3G/bZKq+T7E01vPIuloRHw2P6IWoPmY8ZE3wrLnQNWouRrG2taqzF # fvTL601AY6e4m4MitDrAxNkINy8NQxv3E0RC928+IbylELlpxUH/gLGdsL5fxMWx # TmKOwhfh/qRWZtUOutjz01RUvjL5srGYhDgMRvbWfK0Gq1cl5o2mvnlcU6CYdPDp # 4WbhHZflQpCfHVpxTZPWHeJs7U+j6WWRH7OhggILMIICBwYJKoZIhvcNAQkGMYIB # +DCCAfQCAQEwcjBeMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29y # cG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vydmlj # ZXMgQ0EgLSBHMgIQDs/0OMj+vzVuBNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZI # hvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTYwNTExMTEyMjA5 # WjAjBgkqhkiG9w0BCQQxFgQUSQQDJmM+gWGDRtyet2VkJxeZBtkwDQYJKoZIhvcN # AQEBBQAEggEADT7+3Y8gt4QJISbU1dKjrGvVQz8IYG48AYLjB96FDEHWFMY4/NGn # nD3Kz2jRz3+ChL8QlZ6iti8FTd0VnH1sZznI36fXUO4PcPryHhF0wWIL3ML9/DJU # J+IoApV+Ja+nB8APDY2HsyqkBASvKPfjj2fxFOMafGJdyQS3M6KxiLWNmfiCEKfb # H+zqEqoVnM/i1x6+aMWXd53U2d+JE/5SslqOJi7uSdSSoIH2YwCG/WPVAb314Zvu # GA++r8NBVeJD7OjduzB4AowIAISTgz729YKSoSiOO8eIJYgEIb/JwuesscIGimoy # Qi/wQ0Z/2wQtNxmIR4DMcY/BkbbMmsvIDg== # SIG # End signature block |