Reputation: 914
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 )
Upvotes: 50
Views: 97402
Reputation: 1702
This is a purely PowerShell version of Swonkie's answer which, despite working quite well if you have access to the utility, isn't a PowerShell answer - which is what I needed.
$SourceFile = "C:\Src\OriginalBinaryFile.dll"
$B64File = "C:\Src\DllAsB64.txt"
$Reconstituted = "C:\Src\ReConstituted.dll"
[IO.File]::WriteAllBytes($B64File,[char[]][Convert]::ToBase64String([IO.File]::ReadAllBytes($SourceFile)))
[IO.File]::WriteAllBytes($Reconstituted, [Convert]::FromBase64String([char[]][IO.File]::ReadAllBytes($B64File)))
As a side note. If the DllAsB64.txt is created by certutil, it will be wrapped by these lines.
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
After removing these lines the PowerShell command above will decode it. Certutil ignores them so it will decode its own output or the PowerShell output.
Upvotes: 12
Reputation:
Just to add an alternative for people looking to do a similar task: Windows comes with certutil.exe
(a tool to manipulate certificates) which can base64 encode and decode files.
certutil -encode test.exe test.txt
certutil -decode test.txt test.exe
Upvotes: 60
Reputation: 73586
The problem was caused by:
Get-Content
without -raw
splits the file into an array of lines thus destroying the codeText.Encoding
interprets the binary code as text thus destroying the codeOut-File
is for text data, not binary codeThe 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))
Upvotes: 85