Created
February 29, 2024 23:07
-
-
Save figueroadavid/5d1ef614f72a9ca2d7f8a0f6bf0ce3c9 to your computer and use it in GitHub Desktop.
Backup a user's registry keys for WinSCP from HKEY_USERS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Backup-ArbitraryWinSCPKey { | |
| <# | |
| .SYNOPSIS | |
| This script backups a user's registry keys for WinSCP | |
| .DESCRIPTION | |
| Unlike the Backup-WinSCPKey, this script allows the user to backup an arbitrary user's | |
| WinSCP key out of HKEY_USERS\<usersid>\Software\Martin Prikryl | |
| .NOTES | |
| This does require administrator rights, since the user will be delving into HKEY_USERS. | |
| .PARAMETER SamAccountName | |
| This is the login name of the user that will have their registry key backed up. | |
| .PARAMETER UserAccountDomain | |
| This is the domain for the user account, it defaults to the domain of the user running the script | |
| .PARAMETER ExportDirectory | |
| This is the directory where the exported file will be created. | |
| The name of the file is WinSCP_<samaccountname>_<timestamp>.reg | |
| .PARAMETER Overwrite | |
| If the export file exists, this adds the /y switch to the reg export so that it will overwrite the file. | |
| .PARAMETER Silent | |
| This tells the script to not return the file object of the created export file | |
| .PARAMETER OutputIsHKCU | |
| This tells the script to convert the export files references to [HKEY_USERS\<usersid>] to [HKEY_CURRENT_USER] | |
| making it suitable for the user to import their own keys. | |
| .EXAMPLE | |
| PS C:\> Backup-ArbitraryWinSCPKey -samAccountName User1 -ExportDirectory C:\temp -OutputIsHKCU | |
| Directory: C:\temp | |
| Mode LastWriteTime Length Name | |
| ---- ------------- ------ ---- | |
| -a---- 2/29/2024 4:48 PM 35422 WinSCP_User1_2024-02-29_164810.reg | |
| #> | |
| [cmdletbinding()] | |
| param( | |
| [parameter(Mandatory, ValueFromPipelineByPropertyName)] | |
| [string]$SamAccountName, | |
| [parameter(ValueFromPipelineByPropertyName)] | |
| [string]$UserAccountDomain = $env:USERDOMAIN, | |
| [parameter(Mandatory, ValueFromPipelineByPropertyName)] | |
| [string]$ExportDirectory, | |
| [parameter(ValueFromPipelineByPropertyName)] | |
| [switch]$Overwrite, | |
| [parameter(ValueFromPipelineByPropertyName)] | |
| [switch]$Silent, | |
| [parameter(ValueFromPipelineByPropertyName)] | |
| [switch]$OutputIsHKCU | |
| ) | |
| begin { | |
| function Get-UserSID { | |
| <# | |
| .SYNOPSIS | |
| Retrieves a user's security identifier without the need for the ActiveDirectory Module | |
| .DESCRIPTION | |
| Retrieves a user's security identifier without the need for the ActiveDirectory Module | |
| .PARAMETER samAccountName | |
| The actual samAccountName for the user whose account the SID should be retrieved. | |
| .PARAMETER Domain | |
| This is the domain of the account to be checked. It defaults to the domain of the user | |
| running the script. | |
| .NOTES | |
| Thanks to @JBorean93 for this greatly simplified version | |
| https://github.com/jborean93 | |
| .EXAMPLE | |
| PS C:\> Get-UserSid -samAccountName User1 | |
| S-1-5-21-176475294-9861874819-1984720271-198576 | |
| #(The SID is completely made up) | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [parameter(Mandatory, ValueFromPipelineByPropertyName)] | |
| [string]$samAccountName, | |
| [parameter(ValueFromPipelineByPropertyName)] | |
| [string]$Domain = $env:USERDOMAIN | |
| ) | |
| try { | |
| [System.Security.Principal.NTAccount]::new($Domain, $samAccountName).Translate( | |
| [System.Security.Principal.SecurityIdentifier]).Value | |
| } | |
| catch { | |
| throw 'Unable to locate the user in ActiveDirectory' | |
| } | |
| } | |
| } | |
| process { | |
| $thisUserSID = Get-UserSID -samAccountName $SamAccountName -Domain $UserAccountDomain | |
| $WinSCPPath = 'HKEY_USERS\{0}\SOFTWARE\Martin Prikryl' -f $thisUserSID | |
| if (-not (test-Path -Path registry::$WinSCPPath)) { | |
| throw ('Unable to find WinSCP key in HKU\<SID>, exiting') | |
| } | |
| $ExportPath = [System.IO.Path]::GetFullPath($ExportDirectory) | |
| if (Test-Path -Path $ExportPath) { | |
| $thisPath = Get-Item -Path $ExportPath | |
| if ($thisPath -is [System.IO.DirectoryInfo]) { | |
| Write-Verbose -Message ('$ExportDirectory ({0}) is a directory, continuing' -f $ExportPath) | |
| } | |
| else { | |
| Throw ('The provided $ExportDirectory ({0}) is not a valid path, unable to continue' -f $ExportPath) | |
| } | |
| } | |
| else { | |
| throw ('$ExportDirectory ({0}) does not exist, unable to continue' -f $ExportDirectory) | |
| } | |
| $ExportFileName = 'WinSCP_{0}_{1}.reg' -f $env:USERNAME, [datetime]::Now.ToString('yyyy-MM-dd_HHmmss') | |
| $FilePath = [system.io.path]::Combine($ExportDirectory, $ExportFileName) | |
| $StartProcInfo = [System.Diagnostics.ProcessStartInfo]::new('reg.exe') | |
| $StartProcInfo.CreateNoWindow = $true | |
| $StartProcInfo.LoadUserProfile = $true | |
| $StartProcInfo.UseShellExecute = $false | |
| $StartProcInfo.RedirectStandardError = $true | |
| $StartProcInfo.RedirectStandardOutput = $true | |
| $StartProcInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden | |
| $ArgList = 'export "{0}" "{1}"' -f $WinSCPPath, $FilePath | |
| if ($Overwrite) { | |
| $StartProcInfo.Arguments = ('{0} /y' -f $ArgList) | |
| } | |
| else { | |
| $StartProcInfo.Arguments = $ArgList | |
| } | |
| $Proc = [System.Diagnostics.Process]::new() | |
| $Proc.StartInfo = $StartProcInfo | |
| [void]$Proc.Start() | |
| $Proc.WaitForExit() | |
| $MyExitCode = $Proc.ExitCode | |
| switch ($MyExitCode) { | |
| 0 { Write-Verbose -Message 'Successful'; break } | |
| 1 { Write-Warning -Message ($Proc.StandardError.ReadToEnd()); break } | |
| 2 { Write-Warning -Message 'Successful, but something is different{0}StdOut:{0}{1}{0}StdErr:{0}{2}' -f "`r`n", $Proc.StandardOutput.ReadToEnd(), $Proc.StandardError.ReadToEnd() } | |
| } | |
| if ($OutputIsHKCU) { | |
| $OutputContent = Get-Content -Path $FilePath | |
| $OutputContent = $OutputContent -replace ('HKEY_USERS\\{0}' -f $thisUserSID), 'HKEY_CURRENT_USER' | |
| Set-Content -Path $FilePath -Value $OutputContent | |
| } | |
| if (-not $Silent) { | |
| Get-Item -Path $FilePath | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment