Encode / Decode .EXE into Base64

schizoid04 picture schizoid04 · Mar 4, 2017 · Viewed 45.4k times · Source

I have a .NET exe file that I'd like to encode into a Base-64 string, and then at a later point decode into a .exe file from the Base64 string, using Powershell.

What I have so far produces a .exe file, however, the file isn't recognizable to windows as an application that can run, and is always a different length than the file that I'm passing into the encoding script.

I think I may be using the wrong encoding here, but I'm not sure.

Encode script:

Function Get-FileName($initialDirectory)
{   
 [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "All files (*.*)| *.*"
$OpenFileDialog.ShowDialog() | Out-Null
$FileName = $OpenFileDialog.filename
$FileName

} #end function Get-FileName

$FileName = Get-FileName

$Data = get-content $FileName
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($Data)
$EncodedData = [Convert]::ToBase64String($Bytes)

Decode Script:

$Data = get-content $FileName
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($Data)
$EncodedData = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Bytes))

$EncodedData | Out-File ( $FileName )

Answer

wOxxOm picture wOxxOm · Mar 4, 2017

The problem was caused by:

  1. Get-Content without -raw splits the file into an array of lines thus destroying the code
  2. Text.Encoding interprets the binary code as text thus destroying the code
  3. Out-File is for text data, not binary code

The correct approach is to use IO.File ReadAllBytes:

$base64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes($FileName))

and WriteAllBytes to decode:

[IO.File]::WriteAllBytes($FileName, [Convert]::FromBase64String($base64string))