Skip to content

Instantly share code, notes, and snippets.

@QNimbus
Last active March 26, 2025 08:42
Show Gist options
  • Save QNimbus/ded1f938a2b50ac5531201f3844d1219 to your computer and use it in GitHub Desktop.
Save QNimbus/ded1f938a2b50ac5531201f3844d1219 to your computer and use it in GitHub Desktop.
PowerShell profile #windows #powershell
# Deploy: pwsh -EncodedCommand "cAB3AHMAaAAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABVAG4AcgBlAHMAdAByAGkAYwB0AGUAZAAgAC0AQwBvAG0AbQBhAG4AZAAgAHsAIABTAHQAYQByAHQALQBQAHIAbwBjAGUAcwBzACAAcAB3AHMAaAAgAHsAIAAtAEMAbwBtAG0AYQBuAGQAIAAiACAATgBlAHcALQBJAHQAZQBtACAALQBUAHkAcABlACAARABpAHIAZQBjAHQAbwByAHkAIAAtAEYAbwByAGMAZQAgACIAIgAkAEUAbgB2ADoAVQBTAEUAUgBQAFIATwBGAEkATABFAFwARABvAGMAdQBtAGUAbgB0AHMAXABQAG8AdwBlAHIAUwBoAGUAbABsACIAIgAgAHwAIABPAHUAdAAtAE4AdQBsAGwAOwAgAEkAbgB2AG8AawBlAC0AVwBlAGIAUgBlAHEAdQBlAHMAdAAgAC0ASABlAGEAZABlAHIAcwAgAEAAewAiACIAQwBhAGMAaABlAC0AQwBvAG4AdAByAG8AbAAiACIAPQAiACIAbgBvAC0AYwBhAGMAaABlACIAIgB9ACAALQBPAHUAdABGAGkAbABlACAAIgAiACQARQBuAHYAOgBVAFMARQBSAFAAUgBPAEYASQBMAEUAXABEAG8AYwB1AG0AZQBuAHQAcwBcAFAAbwB3AGUAcgBTAGgAZQBsAGwAXABNAGkAYwByAG8AcwBvAGYAdAAuAFAAbwB3AGUAcgBTAGgAZQBsAGwAXwBwAHIAbwBmAGkAbABlAC4AcABzADEAIgAiACAALQBVAHIAaQAgACcAaAB0AHQAcABzADoALwAvAGcAaQBzAHQALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAFEATgBpAG0AYgB1AHMALwBkAGUAZAAxAGYAOQAzADgAYQAyAGIANQAwAGEAYwA1ADUAMwAxADIAMAAxAGYAMwA4ADQANABkADEAMgAxADkALwByAGEAdwAvAE0AaQBjAHIAbwBzAG8AZgB0AC4AUABvAHcAZQByAFMAaABlAGwAbABfAHAAcgBvAGYAaQBsAGUALgBwAHMAMQAnACAAIgAgAH0AfQA="
# This command deploys the PowerShell profile by running a base64 encoded command that sets up the environment.
#
# To force: Set-Item Env:\__ForceUpdateCheck $true; Start-Process pwsh
# References:
# - Installation of oh-my-posh:
# https://ohmyposh.dev/docs/installation/windows
# - Tutorial - Set up a custom prompt for PowerShell or WSL with Oh My Posh:
# https://learn.microsoft.com/en-us/windows/terminal/tutorials/custom-prompt-setup
# - How to make a pretty prompt in Windows Terminal with Powerline, Nerd Fonts, Cascadia Code, WSL, and oh-my-posh:
# https://www.hanselman.com/blog/how-to-make-a-pretty-prompt-in-windows-terminal-with-powerline-nerd-fonts-cascadia-code-wsl-and-ohmyposh
#
# TL;DR:
# - ```ps
# winget install JanDeDobbeleer.OhMyPosh -s winget
# Install-Module -Name Terminal-Icons -Repository PSGallery
# ```
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
# Variable to determine how many shells 'deep' we are
if (-not $Env:__ShellDepth) {
$Env:__ShellDepth = 0
}
$Env:__ShellDepth = [int] $Env:__ShellDepth + 1
# Timestamp of file to use to determine if code section has to be run
$dailyFile = $PROFILE
# Skip if we're in MS VSCode or if this is a subshell
$forceUpdate = $Env:__ForceUpdateCheck -eq $True
$isFirstShell = $Env:__ShellDepth -eq 1
$isNotVSCode = $Env:TERM_PROGRAM -ne 'vscode'
$isDailyCheckDue = ((Get-Date) - (Get-Item $dailyFile).LastWriteTime).TotalHours -ge 24
# Skip if we're in MS VSCode or if this is a subshell
if ($forceUpdate -Or ($isFirstShell -And $isNotVSCode -And $isDailyCheckDue)) {
# Update timestamp of $PROFILE file
(Get-Item $dailyFile).LastWriteTime = Get-Date
Write-Host "Daily check for packages that can be updated..."
# Packages not to update
$skipUpdate = @(
'Microsoft.DotNet.SDK.6',
'Microsoft.WindowsSDK'
)
class Software {
[string]$Name
[string]$Id
[string]$Version
[string]$AvailableVersion
[string]$Source
}
# Check if Scoop is installed and perform updates
if (Get-Command scoop -ErrorAction SilentlyContinue) {
Write-Host "Scoop is installed. Checking for updates..."
# Get outdated packages using Scoop
$scoopUpdates = scoop status | Select-String -Pattern '^\s*(\w+)\s+(\w+)\s+\->\s+(\w+)' | ForEach-Object {
$matches = $_ -match '^\s*(\w+)\s+(\w+)\s+\->\s+(\w+)'
[PSCustomObject]@{
Name = $matches[1]
InstalledVersion = $matches[2]
LatestVersion = $matches[3]
}
}
if ($scoopUpdates.Count -gt 0) {
Write-Host "The following Scoop packages have updates available:"
$scoopUpdates | Format-Table
$timeoutSeconds = 10
$defaultResponse = "N"
$response = $defaultResponse
Write-Host "You have $timeoutSeconds seconds to respond."
Write-Host "Would you like to update these packages? (Y/N) [Default: $defaultResponse] " -NoNewLine
While ((-not $Host.UI.RawUI.KeyAvailable) -and ($timeoutSeconds -gt 0)) {
Start-Sleep -Seconds 1
$timeoutSeconds--
}
if ($Host.UI.RawUI.KeyAvailable) {
$response = ($Host.UI.RawUI.ReadKey()).Character
}
Write-Host ""
if ($response -eq "Y") {
Write-Host "Updating Scoop packages..."
scoop update
}
else {
Write-Host "To update Scoop packages manually, run: scoop update"
}
}
else {
Write-Host "No Scoop packages need updates."
}
}
else {
Write-Host "Scoop is not installed. Skipping Scoop update check."
}
# Get available upgrades
$upgradeResult = winget upgrade --include-unknown --source winget
# Loop through the list and get package data
$upgrades = @()
$idStart = -1
$isStartList = 0
$upgradeResult | ForEach-Object -Process {
if ($isStartList -lt 1 -and -not $_.StartsWith("Name") -or $_.StartsWith("---") -or $_.StartsWith("The following packages")) {
return
}
if ($_.StartsWith("Name")) {
$idStart = $_.toLower().IndexOf("id")
$isStartList = 1
return
}
if ($_.Length -lt $idStart) {
return
}
$Software = [Software]::new()
$Software.Name = $_.Substring(0, $idStart - 1)
$info = $_.Substring($idStart) -split '\s+'
$Software.Id = $info[0]
$Software.Version = $info[1]
$Software.AvailableVersion = $info[2]
$Software.Source = $info[3]
$upgrades += $Software
}
if ($upgrades.Length -ge 1) {
# View list
$upgrades | Format-Table
$timeoutSeconds = 10
$defaultResponse = "N"
$response = $defaultResponse
Write-Host "You have $timeoutSeconds seconds to respond."
Write-Host "Are you sure you want to upgrade these packages? (Y/N) [Default: $defaultResponse] " -NoNewLine
While ((-not $Host.UI.RawUI.KeyAvailable) -and ($timeoutSeconds -gt 0)) {
Start-Sleep -Seconds 1
$timeoutSeconds--;
}
if ($Host.UI.RawUI.KeyAvailable) {
$response = ($Host.UI.RawUI.ReadKey()).Character # Read-Host
}
Write-Host ""
if ($response -eq "Y") {
# Loop through the list, compare with the skip list and execute the upgrade (could be done in the upper foreach as well)
$upgrades | ForEach-Object -Process {
if ($skipUpdate -contains $_.Id) {
Write-Host "Skipped upgrade to package $($_.id)"
return
}
winget upgrade --include-unknown --source $($_.Source) $($_.Id)
}
}
else {
# Loop through the list, compare with the skip list and execute the upgrade (could be done in the upper foreach as well)
$upgrades | ForEach-Object -Process {
if ($skipUpdate -contains $_.Id) {
Write-Host "Skipped upgrade to package $($_.id)"
return
}
Write-Host "To upgrade $($_.Id), type : " -NoNewLine
'winget upgrade --include-unknown --source {0} {1}' -f $($_.Source), $_.Id
}
Write-Host "To force a re-run of this profile script, type : " -NoNewLine
'"Set-Item Env:\__ForceUpdateCheck $true; Start-Process pwsh"'
}
}
}
# Useful functions
function which($command) {
Get-Command -Name $command -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Path -ErrorAction SilentlyContinue
}
function Set-Location-Directory-Opus([string] $path = $(Get-Location)) {
& "${Env:ProgramFiles}\GPSoftware\Directory Opus\dopus.exe" $path
}
function ForceUpdateCheck() {
try {
$Env:__ForceUpdateCheck = $True ; pwsh -Command "exit" ; Remove-Item Env:__ForceUpdateCheck
}
catch {
Write-Host "An error occurred:"
Write-Host $_
}
}
# Useful aliases
Set-Alias grep findstr
Set-Alias touch New-Item
Set-Alias cat Get-Content
Set-Alias make mingw32-make
Set-Alias dopus Set-Location-Directory-Opus
Set-Alias pbpaste Get-Clipboard
if ($host.Name -eq 'ConsoleHost') {
Import-Module PSReadLine
# Set options for PSReadLine to show the history of our typed commands
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -EditMode Windows
# Enable CTRL-D to close session
Set-PSReadlineKeyHandler -Key Ctrl+d -Function DeleteCharOrExit
# With these bindings, up arrow/down arrow will work like PowerShell/cmd if the current command line is blank.
# If you've entered some text though, it will search the history for commands that start with the currently entered text.
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
#region Smart Insert/Delete
# Edit: Disabled because copy/pasting content with quotes, braces, etc does not quite work
# # The next four key handlers are designed to make entering matched quotes
# # parens, and braces a nicer experience. I'd like to include functions
# # in the module that do this, but this implementation still isn't as smart
# # as ReSharper, so I'm just providing it as a sample.
# Set-PSReadLineKeyHandler -Key '"',"'" `
# -BriefDescription SmartInsertQuote `
# -LongDescription "Insert paired quotes if not already on a quote" `
# -ScriptBlock {
# param($key, $arg)
# $quote = $key.KeyChar
# $selectionStart = $null
# $selectionLength = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState([ref]$selectionStart, [ref]$selectionLength)
# $line = $null
# $cursor = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
# # If text is selected, just quote it without any smarts
# if ($selectionStart -ne -1)
# {
# [Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $quote + $line.SubString($selectionStart, $selectionLength) + $quote)
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
# return
# }
# $ast = $null
# $tokens = $null
# $parseErrors = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$parseErrors, [ref]$null)
# function FindToken
# {
# param($tokens, $cursor)
# foreach ($token in $tokens)
# {
# if ($cursor -lt $token.Extent.StartOffset) { continue }
# if ($cursor -lt $token.Extent.EndOffset) {
# $result = $token
# $token = $token -as [StringExpandableToken]
# if ($token) {
# $nested = FindToken $token.NestedTokens $cursor
# if ($nested) { $result = $nested }
# }
# return $result
# }
# }
# return $null
# }
# $token = FindToken $tokens $cursor
# # If we're on or inside a **quoted** string token (so not generic), we need to be smarter
# if ($token -is [StringToken] -and $token.Kind -ne [TokenKind]::Generic) {
# # If we're at the start of the string, assume we're inserting a new string
# if ($token.Extent.StartOffset -eq $cursor) {
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote ")
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
# return
# }
# # If we're at the end of the string, move over the closing quote if present.
# if ($token.Extent.EndOffset -eq ($cursor + 1) -and $line[$cursor] -eq $quote) {
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
# return
# }
# }
# if ($null -eq $token -or
# $token.Kind -eq [TokenKind]::RParen -or $token.Kind -eq [TokenKind]::RCurly -or $token.Kind -eq [TokenKind]::RBracket) {
# if ($line[0..$cursor].Where{$_ -eq $quote}.Count % 2 -eq 1) {
# # Odd number of quotes before the cursor, insert a single quote
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
# }
# else {
# # Insert matching quotes, move cursor to be in between the quotes
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote")
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
# }
# return
# }
# # If cursor is at the start of a token, enclose it in quotes.
# if ($token.Extent.StartOffset -eq $cursor) {
# if ($token.Kind -eq [TokenKind]::Generic -or $token.Kind -eq [TokenKind]::Identifier -or
# $token.Kind -eq [TokenKind]::Variable -or $token.TokenFlags.hasFlag([TokenFlags]::Keyword)) {
# $end = $token.Extent.EndOffset
# $len = $end - $cursor
# [Microsoft.PowerShell.PSConsoleReadLine]::Replace($cursor, $len, $quote + $line.SubString($cursor, $len) + $quote)
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($end + 2)
# return
# }
# }
# # We failed to be smart, so just insert a single quote
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
# }
# Set-PSReadLineKeyHandler -Key '(','{','[' `
# -BriefDescription InsertPairedBraces `
# -LongDescription "Insert matching braces" `
# -ScriptBlock {
# param($key, $arg)
# $closeChar = switch ($key.KeyChar)
# {
# <#case#> '(' { [char]')'; break }
# <#case#> '{' { [char]'}'; break }
# <#case#> '[' { [char]']'; break }
# }
# $selectionStart = $null
# $selectionLength = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState([ref]$selectionStart, [ref]$selectionLength)
# $line = $null
# $cursor = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
# if ($selectionStart -ne -1)
# {
# # Text is selected, wrap it in brackets
# [Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $key.KeyChar + $line.SubString($selectionStart, $selectionLength) + $closeChar)
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
# } else {
# # No text is selected, insert a pair
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)$closeChar")
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
# }
# }
# Set-PSReadLineKeyHandler -Key ')',']','}' `
# -BriefDescription SmartCloseBraces `
# -LongDescription "Insert closing brace or skip" `
# -ScriptBlock {
# param($key, $arg)
# $line = $null
# $cursor = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
# if ($line[$cursor] -eq $key.KeyChar)
# {
# [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
# }
# else
# {
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)")
# }
# }
# Set-PSReadLineKeyHandler -Key Backspace `
# -BriefDescription SmartBackspace `
# -LongDescription "Delete previous character or matching quotes/parens/braces" `
# -ScriptBlock {
# param($key, $arg)
# $line = $null
# $cursor = $null
# [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
# if ($cursor -gt 0)
# {
# $toMatch = $null
# if ($cursor -lt $line.Length)
# {
# switch ($line[$cursor])
# {
# <#case#> '"' { $toMatch = '"'; break }
# <#case#> "'" { $toMatch = "'"; break }
# <#case#> ')' { $toMatch = '('; break }
# <#case#> ']' { $toMatch = '['; break }
# <#case#> '}' { $toMatch = '{'; break }
# }
# }
# if ($toMatch -ne $null -and $line[$cursor-1] -eq $toMatch)
# {
# [Microsoft.PowerShell.PSConsoleReadLine]::Delete($cursor - 1, 2)
# }
# else
# {
# [Microsoft.PowerShell.PSConsoleReadLine]::BackwardDeleteChar($key, $arg)
# }
# }
# }
#endregion Smart Insert/Delete
# This key handler shows the entire or filtered history using Out-GridView. The
# typed text is used as the substring pattern for filtering. A selected command
# is inserted to the command line without invoking. Multiple command selection
# is supported, e.g. selected by Ctrl + Click.
Set-PSReadLineKeyHandler -Key F7 `
-BriefDescription History `
-LongDescription 'Show command history' `
-ScriptBlock {
$pattern = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$pattern, [ref]$null)
if ($pattern) {
$pattern = [regex]::Escape($pattern)
}
$history = [System.Collections.ArrayList]@(
$last = ''
$lines = ''
foreach ($line in [System.IO.File]::ReadLines((Get-PSReadLineOption).HistorySavePath)) {
if ($line.EndsWith('`')) {
$line = $line.Substring(0, $line.Length - 1)
$lines = if ($lines) {
"$lines`n$line"
}
else {
$line
}
continue
}
if ($lines) {
$line = "$lines`n$line"
$lines = ''
}
if (($line -cne $last) -and (!$pattern -or ($line -match $pattern))) {
$last = $line
$line
}
}
)
$history.Reverse()
$command = $history | Out-GridView -Title History -PassThru
if ($command) {
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert(($command -join "`n"))
}
}
}
# Path to the patterns directory
$patternsPath = Join-Path $HOME ".config/fabric/patterns"
if (Test-Path -Path $patternsPath) {
foreach ($patternDir in Get-ChildItem -Path $patternsPath -Directory) {
$patternName = $patternDir.Name
# Dynamically define a function for each pattern
$functionDefinition = @"
function $patternName {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = `$true)]
[string] `$InputObject,
[Parameter(ValueFromRemainingArguments = `$true)]
[String[]] `$patternArgs
)
begin {
# Initialize an array to collect pipeline input
`$collector = @()
}
process {
# Collect pipeline input objects
if (`$InputObject) {
`$collector += `$InputObject
}
}
end {
# Join all pipeline input into a single string, separated by newlines
`$pipelineContent = `$collector -join "`n"
# If there's pipeline input, include it in the call to fabric
if (`$pipelineContent) {
`$pipelineContent | fabric --pattern $patternName `$patternArgs
} else {
# No pipeline input; just call fabric with the additional args
fabric --pattern $patternName `$patternArgs
}
}
}
"@
# Add the function to the current session
Invoke-Expression $functionDefinition
}
}
# Define the 'yt' function as well
function yt {
[CmdletBinding()]
param(
[Parameter()]
[Alias("timestamps")]
[switch]$t,
[Parameter(Position = 0, ValueFromPipeline = $true)]
[string]$videoLink
)
begin {
$transcriptFlag = "--transcript"
if ($t) {
$transcriptFlag = "--transcript-with-timestamps"
}
}
process {
if (-not $videoLink) {
Write-Error "Usage: yt [-t | --timestamps] youtube-link"
return
}
}
end {
if ($videoLink) {
# Execute and allow output to flow through the pipeline
fabric -y $videoLink $transcriptFlag
}
}
}
# Oh My Posh
if ($env:USE_OH_MY_POSH -eq 'true' -and $Env:TERM_PROGRAM -ne 'vscode') {
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/nordtron.omp.json" | Invoke-Expression
}
else {
# Vanilla PowerShell
Write-Host "Using vanilla PowerShell without oh-my-posh."
}
@QNimbus
Copy link
Author

QNimbus commented Mar 23, 2023

To download to %USERPROFILE%\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 :

pwsh -EncodedCommand "cAB3AHMAaAAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABVAG4AcgBlAHMAdAByAGkAYwB0AGUAZAAgAC0AQwBvAG0AbQBhAG4AZAAgAHsAIABTAHQAYQByAHQALQBQAHIAbwBjAGUAcwBzACAAcAB3AHMAaAAgAHsAIAAtAEMAbwBtAG0AYQBuAGQAIAAiACAATgBlAHcALQBJAHQAZQBtACAALQBUAHkAcABlACAARABpAHIAZQBjAHQAbwByAHkAIAAtAEYAbwByAGMAZQAgACIAIgAkAEUAbgB2ADoAVQBTAEUAUgBQAFIATwBGAEkATABFAFwARABvAGMAdQBtAGUAbgB0AHMAXABQAG8AdwBlAHIAUwBoAGUAbABsACIAIgAgAHwAIABPAHUAdAAtAE4AdQBsAGwAOwAgAEkAbgB2AG8AawBlAC0AVwBlAGIAUgBlAHEAdQBlAHMAdAAgAC0ASABlAGEAZABlAHIAcwAgAEAAewAiACIAQwBhAGMAaABlAC0AQwBvAG4AdAByAG8AbAAiACIAPQAiACIAbgBvAC0AYwBhAGMAaABlACIAIgB9ACAALQBPAHUAdABGAGkAbABlACAAIgAiACQARQBuAHYAOgBVAFMARQBSAFAAUgBPAEYASQBMAEUAXABEAG8AYwB1AG0AZQBuAHQAcwBcAFAAbwB3AGUAcgBTAGgAZQBsAGwAXABNAGkAYwByAG8AcwBvAGYAdAAuAFAAbwB3AGUAcgBTAGgAZQBsAGwAXwBwAHIAbwBmAGkAbABlAC4AcABzADEAIgAiACAALQBVAHIAaQAgACcAaAB0AHQAcABzADoALwAvAGcAaQBzAHQALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAFEATgBpAG0AYgB1AHMALwBkAGUAZAAxAGYAOQAzADgAYQAyAGIANQAwAGEAYwA1ADUAMwAxADIAMAAxAGYAMwA4ADQANABkADEAMgAxADkALwByAGEAdwAvAE0AaQBjAHIAbwBzAG8AZgB0AC4AUABvAHcAZQByAFMAaABlAGwAbABfAHAAcgBvAGYAaQBsAGUALgBwAHMAMQAnACAAIgAgAH0AfQA="

Note: This is a Base64 encoded command - the decoded command is below. Use base64decode.org to verify (UTF-16LE encoding)

Input

To get the encoded command I used the following code:

$cmd = @"
pwsh -ExecutionPolicy Unrestricted -Command {
    Start-Process pwsh {
        -Command "
            New-Item -Type Directory -Force ""`$Env:USERPROFILE\Documents\PowerShell"" | Out-Null;
            Invoke-WebRequest
                -Headers @{""Cache-Control""=""no-cache""}
                -OutFile ""`$Env:USERPROFILE\Documents\PowerShell\Microsoft.PowerShell_profile.ps1""
                -Uri 'https://gist.githubusercontent.com/QNimbus/ded1f938a2b50ac5531201f3844d1219/raw/Microsoft.PowerShell_profile.ps1'
        "
    }
}
"@ -replace "`n",""  -replace '\s+',' '
$encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($cmd))

Clear-Host
'# Command'
'# {0}' -f $([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encodedCmd)))

'# Base64 encoded command (UTF-16)'
'# {0}' -f $encodedCmd

Output

# pwsh -ExecutionPolicy Unrestricted -Command { Start-Process pwsh { -Command " New-Item -Type Directory -Force ""$Env:USERPROFILE\Documents\PowerShell"" | Out-Null; Invoke-WebRequest -Headers @{""Cache-Control""=""no-cache""} -OutFile ""$Env:USERPROFILE\Documents\PowerShell\Microsoft.PowerShell_profile.ps1"" -Uri 'https://gist.githubusercontent.com/QNimbus/ded1f938a2b50ac5531201f3844d1219/raw/Microsoft.PowerShell_profile.ps1' " }}

# cAB3AHMAaAAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABVAG4AcgBlAHMAdAByAGkAYwB0AGUAZAAgAC0AQwBvAG0AbQBhAG4AZAAgAHsAIABTAHQAYQByAHQALQBQAHIAbwBjAGUAcwBzACAAcAB3AHMAaAAgAHsAIAAtAEMAbwBtAG0AYQBuAGQAIAAiACAATgBlAHcALQBJAHQAZQBtACAALQBUAHkAcABlACAARABpAHIAZQBjAHQAbwByAHkAIAAtAEYAbwByAGMAZQAgACIAIgAkAEUAbgB2ADoAVQBTAEUAUgBQAFIATwBGAEkATABFAFwARABvAGMAdQBtAGUAbgB0AHMAXABQAG8AdwBlAHIAUwBoAGUAbABsACIAIgAgAHwAIABPAHUAdAAtAE4AdQBsAGwAOwAgAEkAbgB2AG8AawBlAC0AVwBlAGIAUgBlAHEAdQBlAHMAdAAgAC0ASABlAGEAZABlAHIAcwAgAEAAewAiACIAQwBhAGMAaABlAC0AQwBvAG4AdAByAG8AbAAiACIAPQAiACIAbgBvAC0AYwBhAGMAaABlACIAIgB9ACAALQBPAHUAdABGAGkAbABlACAAIgAiACQARQBuAHYAOgBVAFMARQBSAFAAUgBPAEYASQBMAEUAXABEAG8AYwB1AG0AZQBuAHQAcwBcAFAAbwB3AGUAcgBTAGgAZQBsAGwAXABNAGkAYwByAG8AcwBvAGYAdAAuAFAAbwB3AGUAcgBTAGgAZQBsAGwAXwBwAHIAbwBmAGkAbABlAC4AcABzADEAIgAiACAALQBVAHIAaQAgACcAaAB0AHQAcABzADoALwAvAGcAaQBzAHQALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAFEATgBpAG0AYgB1AHMALwBkAGUAZAAxAGYAOQAzADgAYQAyAGIANQAwAGEAYwA1ADUAMwAxADIAMAAxAGYAMwA4ADQANABkADEAMgAxADkALwByAGEAdwAvAE0AaQBjAHIAbwBzAG8AZgB0AC4AUABvAHcAZQByAFMAaABlAGwAbABfAHAAcgBvAGYAaQBsAGUALgBwAHMAMQAnACAAIgAgAH0AfQA=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment