Skip to main content

Hackday 2025 - The Cogs of Blackmail

·733 words·4 mins

Author : Glz_SQL
My Opinion : Really interesting challenge, easy to understand the logic even though coding the parser is a bit harder 😅.
Here is the challenge : 📥 Download Binary

Binary Analysis
#

For this challenge we first analyze the binary, which is a DLL in Dotnet, so we upload it in DNSpy, after further simplification of the code we get something like this :

using System;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading;

// Token: 0x02000002 RID: 2
public class btJuHzNucnTGdQAZwMmMnhZQZkH
{
	public static void RcyBinrittxjWupPNlCeddcAqv()
	{
		byte[] array = Convert.FromBase64String("TVo/AAMAAAAEAAAAPz8A...garbagebase64");
		string value = "HtTpS://WinDOws.UpDaTe.ShUnbCKhiT.NeT/d5nZ72";
		string value2 = "HtTpS://WinDOws.UpDaTe.ShUnbCKhiT.NeT/2hGbZ3";
		byte[] array2 = Convert.FromBase64String("TVo/AAMAAAAEAAAAPz8A...garbagebase64");

		string value3 = "HtTpS://WinDOws.UpDaTe.ShUnbCKhiT.NeT/gTbvs4";
		Aes aes = Aes.Create();
		byte[] iv = new byte[]
		{
			34,
			24,
			249,
			50,
			19,
			169,
			176,
			81,
			77,
			113,
			42,
			8,
			30,
			58,
			25,
			86
		};
		try
		{
			int num3 = Convert.ToInt32(value2);
			int num2 = num3;
			num3 = num2 + 1;
			bool flag4 = num3 % 3 == 1;
			if (flag4)
			{
				return;
			}
		}
		catch
		{
		}
		aes.Mode = CipherMode.CBC;
		array2 = Convert.FromBase64String("TVo/AAMAAAAEAAAAPz8AAD8A...garbage_base64");
		...
		byte[] key = new byte[]
		{
			75,
			51,
			238,
			229,
			103,
			150,
			200,
			137,
			20,
			150,
			126,
			246,
			211,
			224,
			45,
			68,
			167,
			240,
			234,
			250,
			75,
			59,
			126,
			168,
			4,
			37,
			252,
			4,
			146,
			4,
			102,
			102
		};
		aes.Key = key;
		aes.IV = iv;
		ICryptoTransform cryptoTransform = aes.CreateDecryptor();
		array2 = new byte[]
		{
			93,
			212,
			70,
			17,
			222,
			77,
			122,
			106,
			... // A Lot of data decrypted
		};

		Assembly assembly = Assembly.Load(cryptoTransform.TransformFinalBlock(array2, 0, array2.Length));
		Type type = assembly.GetType("TOpeUzKRdlVkUernmEtHHRK");
		...
	}
}

All we need to understand from this code is that the binary is actually decrypting content of array2 using an IV and an AES Key using CBC mode. So I’ve wrote the following code to decipher the data in array2 :

from Crypto.Cipher import AES
iv = bytes.fromhex("2218f93213a9b0514d712a081e3a1956")
key = bytes.fromhex("4b33eee56796c88914967ef6d3e02d44a7f0eafa4b3b7ea80425fc0492046666")
begin_data = bytearray([93,212,70,17,222,77,122,106,134,126,32])
cipher = AES.new(key, AES.MODE_CBC, iv)
with open("DLLception.dll", "rb") as file:
	big_data = file.read()

array_data_idx = big_data.index(begin_data)
ciphertext = bytearray()
for i in range(3185680): # size given by dnspy counting the rest elements in array2
	ciphertext.append(big_data[array_data_idx+i])

plaintext = cipher.decrypt(ciphertext)
with open("other.dll", "wb") as other:
	other.write(plaintext)

It gave me another DLL doing the same process, than the previous DLL, so I’ve understood the DLL was unpacking itself multiple time.

Understanding the algorithm
#

Everytime the DLL changes the IV and the Key change, as you can see in the below screen :

algorithm cog
That’s why I had to develop a parser of C# code, of course to dump the code from the CMD I’ve used ilspycmd ;).

Developping the solver
#

Finally I’ve developped with Python the following solver to unpack the binary :

import subprocess
import re
import os
from Crypto.Cipher import AES
for x in range(0, 151):
	command = ["ilspycmd", f".\\DLLception{x}.dll", "-o", "."]
	subprocess.run(command, check=True)
	print(f"[+] Decompilation done for {x}")
	with open(f"DLLception{x}.decompiled.cs", "r") as decompiled:
		decompiled_lines = decompiled.readlines()
	pattern = r"key\s*=\s*new\s*byte\[[^\]]*\]\s*\{([^}]*)\}"

	garb1 = decompiled_lines.index("\t\t};\n")
	decompiled_lines[garb1] = ""
	garb2 = decompiled_lines.index("\t\t};\n")
	decompiled_lines[garb2] = ""

	for i in range(len(decompiled_lines)):
		if "iV " in decompiled_lines[i]:
			iv_line1 = decompiled_lines[i+2].replace("\t", "").replace("\n", "")
			iv_line2 = decompiled_lines[i+3].replace("\t", "").replace("\n", "")
			iv_str = iv_line1 + iv_line2
			iv = bytearray([int(i) for i in iv_str.split(',')])
			break

	for i in range(len(decompiled_lines)):
		if "key " in decompiled_lines[i]:
			key_line1 = decompiled_lines[i+2].replace("\t", "").replace("\n", "")
			key_line2 = decompiled_lines[i+3].replace("\t", "").replace("\n", "")
			key_line3 = decompiled_lines[i+4].replace("\t", "").replace("\n", "")
			key_line4 = decompiled_lines[i+5].replace("\t", "").replace("\n", "")
			key_str = key_line1 + key_line2 + key_line3 + key_line4
			key = bytearray([int(i) for i in key_str.split(',')])
			break
	print(f"{iv=},{key=}")

	start_idx = 461
	end_idx = decompiled_lines.index("\t\t};\n")
	values_str = ",".join(line.strip().replace("\t", "").rstrip(",") for line in decompiled_lines[start_idx:end_idx])
	ciphertext = bytearray([int(v) for v in values_str.split(',')])
	cipher = AES.new(key, AES.MODE_CBC, iv)
	plaintext = cipher.decrypt(ciphertext)
	with open(f"DLLception{x+1}.dll", "wb") as other:
		other.write(plaintext)
	print("[+] Decipher done !")
	os.remove(f"DLLception{x}.decompiled.cs")

And at the iteration 150 I got this code which gives the flag :

using System;
using System.Threading;

public class Program
{
	public static void Main()
	{
		char[] array = new char[]
		{
			'H',
			'A',
			'C',
			'K',
			'D',
			'A',
			'Y',
			'{',
			'd',
			'l',
			'l',
			'C',
			'e',
			'p',
			't',
			'i',
			'o',
			'n',
			'-',
			'b',
			'e',
			'9',
			'7',
			'4',
			'6',
			'f',
			'a',
			'-',
			'd',
			'0',
			'f',
			'7',
			'-',
			'4',
			'7',
			'6',
			'1',
			'-',
			'a',
			'5',
			'b',
			'a',
			'-',
			'0',
			'e',
			'4',
			'6',
			'1',
			'a',
			'1',
			'6',
			'2',
			'8',
			'7',
			'7',
			'}'
		};
		Thread.Sleep(1);
		for (int i = 0; i < array.Length; i++)
		{
			char[] array2 = array;
			int num = i;
			array2[num] ^= array[i];
		}
		Console.WriteLine("Hello, World!");
	}
}

Flag : HACKDAY{dllCeption-be9746fa-d0f7-4761-a5ba-0e461a162877}