I am Jakoby
I am Jakoby

Reputation: 617

How do I convert a PowerShell script to Base64?

I have been working my brain on this one and can not figure out how I'm losing integrity here...

I have the following script I am trying to convert to Base64:

Function Get-Networks { 
    $Network = Get-WmiObject Win32_NetworkAdapterConfiguration | where { $_.MACAddress -notlike $null }  | select Index, Description, IPAddress, DefaultIPGateway, MACAddress | Format-Table Index, Description, IPAddress, DefaultIPGateway, MACAddress     
    $WLANProfileNames = @() 
    $Output = netsh.exe wlan show profiles | Select-String -pattern " : " 
    Foreach ($WLANProfileName in $Output) {     
        $WLANProfileNames += (($WLANProfileName -split ":")[1]).Trim() 
    } 
    $WLANProfileObjects = @() 
    Foreach ($WLANProfileName in $WLANProfileNames) {     
        try {         
            $WLANProfilePassword = (((netsh.exe wlan show profiles name="$WLANProfileName" key=clear | select-string -Pattern "Key Content") -split ":")[1]).Trim()     
        }
        Catch {         
            $WLANProfilePassword = "The password is not stored in this profile"     
        }     
        $WLANProfileObject = New-Object PSCustomobject      
        $WLANProfileObject | Add-Member -Type NoteProperty -Name "ProfileName" -Value $WLANProfileName     
        $WLANProfileObject | Add-Member -Type NoteProperty -Name "ProfilePassword" -Value $WLANProfilePassword     
        $WLANProfileObjects += $WLANProfileObject     
        Remove-Variable WLANProfileObject  
        return $WLANProfileObjects 
    } 
}  
$Networks = Get-Networks 
echo $Networks

initially, I was using the following snippet to do it. This would read the contents of my file to a variable and then convert it. I noticed when I converted it back this was outputting everything to one line and messing up the formatting

$Content = Get-Content -Path $FilePath    
$converted = [convert]::ToBase64String([System.Text.encoding]::Unicode.GetBytes($Content))

So I then switched to the following snippet to convert it using the file path instead of saving the content to a variable and I was pleased to see when I converted it back it maintained its integrity.

[convert]::ToBase64String((Get-Content -path $FilePath -Encoding byte))

but when I tried to execute it, this time it threw the following errors and I couldn't be more confused

畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮硥‬敄捳楲瑰潩Ɱ䤠䅐摤敲獳‬敄慦汵䥴䝐瑡睥祡‬䅍䅃摤敲獳簠䘠牯慭⵴慔汢⁥湉敤ⱸ䐠獥牣灩楴湯‬偉摁牤獥ⱳ䐠晥畡瑬 偉慇整慷ⱹ䴠䍁摁牤獥⁳ഉ␊䱗乁牐景汩乥浡獥㴠⡀ഩ␊畏灴瑵㴠渠瑥桳攮數眠慬桳睯瀠潲楦敬⁳⁼敓敬瑣匭牴湩⁧瀭瑡整湲∠㨠∠਍潆敲捡⡨圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ : The term
'畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮硥‬敄捳楲瑰潩Ɱ䤠䅐摤敲獳‬敄慦汵䥴䝐瑡睥祡‬䅍䅃摤敲獳簠䘠牯慭⵴慔汢⁥湉敤ⱸ䐠獥牣灩楴湯‬偉摁牤獥ⱳ䐠晥畡瑬偉慇整慷ⱹ䴠䍁摁牤獥⁳ഉ␊䱗乁牐景汩乥浡獥㴠⡀ഩ␊畏灴瑵㴠渠瑥桳攮數眠慬桳睯瀠潲楦敬⁳⁼敓敬瑣匭牴湩⁧瀭瑡整湲∠㨠∠਍潆敲捡⡨圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ' is not recognized
as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ 畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴...圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ:String) [], CommandNotFoundException

How do I simply write a script to convert this file to base64 so I can execute it properly?

Upvotes: 4

Views: 11144

Answers (2)

mklement0
mklement0

Reputation: 437080

To complement your own, effective solution with some background information:

  • Base64 encoding is an ASCII-string-based encoding of arbitrary byte data, so if a string is to be encoded, its specific encoding as an array of bytes needs to be decided on.

  • In your original attempt (as in your effective solution), you correctly obtained your Base64-encoded string based on the bytes that make up the UTF-16LE encoding of the input string to encode ([System.Text.Encoding]::Unicode.GetBytes(...)), because that is what the Windows PowerShell CLI (powershell.exe) / PowerShell (Core) 7+ CLI (pwsh) requires in an argument passed to its -EncodedCommand parameter.

    • Terminology note: In .NET and PowerShell, this specific Unicode encoding is poorly named for the abstract Unicode standard ([System.Text.Encoding]::Unicode in .NET, -Encoding Unicode in PowerShell's various file-processing cmdlets)
  • The problem with your original attempt was to use Get-Content without the -Raw switch, as Santiago Squarzon pointed out:

    • Without -Raw, Get-Content emits the target file's lines one by one, which, when (implicitly) collected, result in an array of lines - as opposed to the single, multi-line string that -Raw returns.

      • Either way, Get-Content reads the file content into .NET string(s), which are composed of UTF-16 code units ([char] instances), and to make sure that the file content is interpreted correctly, you may need to use the -Encoding parameter.

      • [System.Text.Encoding]::Unicode.GetBytes() invariably operates on in-memory .NET strings.

    • When an array is passed to a .NET method that expects a single [string] argument, PowerShell - perhaps unfortunately - automatically stringifies it by space-concatenating its elements.

      • Therefore, newlines (line breaks) in the input string are lost (replaced with spaces), which can result in broken code, given that newlines do have syntactic significance in PowerShell code.

Upvotes: 5

I am Jakoby
I am Jakoby

Reputation: 617

I ended up doing a little more research and found a method that did exactly what I needed it to and maintained all its integrity.

$encoded = [Convert]::ToBase64String(
  [System.Text.Encoding]::Unicode.GetBytes(
    (Get-Content -Path $Path -Raw -Encoding UTF8)
  )
)

Upvotes: 6

Related Questions