PoSH Challenge part 7
This one was very challenging and got me puzzling for way to deep into the night morning last Friday, taking much more time as expected.
The problem at hand at Level 8 did involve bzip2 , I started to find if there was a .NET library for this and found this one: .NET Zip Library #ziplib (SharpZipLib)
And Loaded the library into my PowerShell session and used the Update-TabExpansionTypes function to update the PowerTab database, to enable me to use tabcompletion to explore the library :
[Tab] [System.Reflection.Assembly]::LoadFile('C:\PoSH\ICSharpCode.SharpZipLib.dll')
GAC Version Location
--- ------- --------
False v2.0.50727 C:\PoSH\ICSharpCode.SharpZipLib.dll
PoSH> Update-TabExpansionTypes
PoSH> [
PoSH> ╔═ [ ══════════════╗
PoSH> ║ [Accessibility ║
PoSH> ║ [ICSharpCode ║
PoSH> ║ [Microsoft ║
PoSH> ║ [NTFS ║
PoSH> ║ [System ║
PoSH> ║ [Trinet ║
PoSH> ╚═[1] 1-6 (6/6)]═══╝
PoSH>
PoSH> [ICSharpCode.SharpZipLib.
PoSH> ╔═ [ICSharpCode.SharpZipLib. ═════════════════════╗
PoSH> ║ [ICSharpCode.SharpZipLib.BZip2 ║
PoSH> ║ [ICSharpCode.SharpZipLib.Checksums ║
PoSH> ║ [ICSharpCode.SharpZipLib.Core ║
PoSH> ║ [ICSharpCode.SharpZipLib.Encryption ║
PoSH> ║ [ICSharpCode.SharpZipLib.GZip ║
PoSH> ║ [ICSharpCode.SharpZipLib.Tar ║
PoSH> ║ [ICSharpCode.SharpZipLib.Zip ║
PoSH> ║ [ICSharpCode.SharpZipLib.SharpZipBaseException] ║
PoSH> ╚═[1] 1-8 (8/8)]══════════════════════════════════╝
PoSH>
PoSH> [ICSharpCode.SharpZipLib.BZip2.BZip2]::
PoSH> ╔═ [ICSharpCode.SharpZipLib.BZip2.BZip2]:: ═══════════════╗
PoSH> ║ [ICSharpCode.SharpZipLib.BZip2.BZip2]::Compress( ║
PoSH> ║ [ICSharpCode.SharpZipLib.BZip2.BZip2]::Decompress( ║
PoSH> ║ [ICSharpCode.SharpZipLib.BZip2.BZip2]::Equals( ║
PoSH> ║ [ICSharpCode.SharpZipLib.BZip2.BZip2]::ReferenceEquals( ║
PoSH> ╚═[1] 1-4 (4/4)]══════════════════════════════════════════╝
PoSH>
PoSH>
Exactly what I needed, It did look like an easy enough fix till then and I figured I was almost there , ... but then the trouble started.
I got the strings like this :
$s1 = 'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
$s2 = 'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
The library needed a Stream object as input not a string , this I had at hand before so I created a memory stream but could not get it accepted by the decompress method.
I did see the escape characters for hex so a first step was un-escaping the line :
PoSH> [regex]::Unescape('BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\
xbe\x084')
BZh91AY&SYA_? ☺☺?☻A☻ !?h3M<]ɶáBA4_
PoSH>
Still no valid output ( end of stream errors ), Searching the Internet for this error, gave me the reason (it had been stored as a string ) but only warned me never to cast the compressed bytes to a string.
A good enough advice, as I was well aware off myself by that time ;-) , but not helpful in my case as I ONLY HAD the string in the first place.
By the time I also made a script to compress text myself and then decompress it again, this did work OK, and I started playing with different encoding's, and saving to textfiles first in different formats, again to no avail.
After a lot more trail and error I was becoming desperate, but finally I got lucky by first making it Unicode and only after that cast it to a ASCII byte array, giving a different resulting byte array :
My solution to Level 8 :
<?xml version="1.0"?>
[System.Reflection.Assembly]::LoadFile('C:\PoSH\ICSharpCode.SharpZipLib.dll')
Function ConvertFrom-BZip2EncodedUnixTextString ($String){
$un = [regex]::Unescape($String)
$b = (new-Object System.Text.UnicodeEncoding).getbytes($un)
$b = 0..($b.Length -1) |? {$_%2 -eq 0} |% { $b[$_] }
$in = new-Object System.IO.MemoryStream($b,$false)
$out = new-Object System.IO.MemoryStream
[ICSharpCode.SharpZipLib.BZip2.BZip2]::DeCompress($in,$out)
(new-Object System.Text.asciiEncoding).GetString($out.toarray())
}
$s1 = 'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
$s2 = 'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
$s1,$s2 |% {ConvertFrom-BZip2EncodedUnixTextString $_}
WOW, It took a good refresh of my encoding skills, to much time and some luck for me to solve this one (also because the name and password where English words,e.g. had a meaning so I knew when I did it right) but mostly this shows that storing it as text is not something you should do with compressed data in real life (use binary streams).
Hope you still see then when used right this is a great library, till the PowerShell Community Extensions fill this gap (Yes X0n I know you're busy ;-) ) , and also notice how easy PowerTab makes it to work with "external" .NET libraries in PowerShell .
In the next post about level 9, we're going to have some Bitmap fun again with PowerShell
Enjoy,
Greetings /\/\o\/\/