Challenge Description

Danish (original)

Thor har modtaget en besked fra jætterne, som hævder at have krypteret et vigtigt juleflag i en digital gave. Kun de, der kan afkode beskeden og bryde jætternes obfuskerede logik, kan hjælpe Asgård med at genoprette flaget. Kan du finde flaget og redde julen?

English (from chatgpt)

Thor has received a message from the giants, claiming to have encrypted an important Christmas flag in a digital gift. Only those who can decode the message and break the giants’ obfuscated logic can help Asgard restore the flag. Can you find the flag and save Christmas?

File

We are also given the following file:

Solution

Unzipping the file we get an exe file:

$ unzip IndpakketGave.zip
Archive:  IndpakketGave.zip
  inflating: IndpakketGave.exe

Running strings I found .NET library names (e.g. System.Security.Cryptography), so I tried opening it with AvaloniaILSpy, but that actually did not work. So thinking about the challenge name “Den Indpakkede Gave” (The Wrapped Gift) I used foremost to see if it might be a program in a program, and it sure is:

$ foremost IndpakketGave.exe
Processing: IndpakketGave.exe
|*|

$ cat output/audit.txt
Foremost version 1.5.7 by Jesse Kornblum, Kris Kendall, and Nick Mikus
Audit File

Foremost started at Mon Dec 23 09:54:20 2024
Invocation: foremost IndpakketGave.exe
Output directory: /home/osiriz/dl/output
Configuration file: /etc/foremost.conf
------------------------------------------------------------------
File: IndpakketGave.exe
Start: Mon Dec 23 09:54:20 2024
Length: 118 KB (121346 bytes)

Num      Name (bs=512)         Size      File Offset     Comment

0:      00000000.exe         108 KB               0      10/17/2024 12:16:00
1:      00000216.exe           9 KB          110592      12/08/2088 01:22:32
Finish: Mon Dec 23 09:54:20 2024

2 FILES EXTRACTED

exe:= 2
------------------------------------------------------------------

Foremost finished at Mon Dec 23 09:54:20 2024

So opening the extracted 00000216.exe instead we can get the following source code:

internal class P
{
	private static void Main(string[] args)
	{
		Console.WriteLine("\n                                 |\n                               \\ ' /\n                             -- (*) --\n                                >*<\n                               >0<@<\n                              >>>@<<*\n                             >@>*<0<<<\n                            >*>>@<<<@<<\n                           >@>>0<<<*<<@<\n                          >*>>0<<@<<<@<<<\n                         >@>>*<<@<>*<<0<*<\n           \\*/          >0>>*<<@<>0><<*<@<<\n       ___\\\\U//___     >*>>@><0<<*>>@><*<0<<\n       |\\\\ | | \\\\|    >@>>0<*<0>>@<<0<<<*<@<<  \n       | \\\\| | _(UU)_ >((*))_>0><*<0><@<<<0<*<\n       |\\ \\| || / //||.*.*.*.|>>@<<*<<@>><0<<<\n       |\\\\_|_|&&_// ||*.*.*.*|_\\\\db//_               \n       \"\"|'.'.'.|~~|.*.*.*|     ____|_\n           |'.'.'.|   ^^^^^^|____|>>>>>>|\n           ~~~~~~~~         '\"\"`------'\n                                   ");
		string kG = Resources.kG;
		Console.WriteLine("Velkommen!");
		Console.WriteLine("Venligst indsat flaget:");
		string? q = Console.ReadLine();
		byte[] bytes = Encoding.ASCII.GetBytes("valhallahpakkergodegaver");
		byte[] s = new byte[16];
		if (S(E(q, bytes, s)) == kG)
		{
			Console.WriteLine("Tillykke dit flag er korrekt!");
		}
		else
		{
			Console.WriteLine("Forkert.");
		}
	}

	private static string E(string q, byte[] r, byte[] s)
	{
		using AesManaged aesManaged = new AesManaged();
		aesManaged.Key = r;
		aesManaged.IV = s;
		aesManaged.Mode = CipherMode.CBC;
		using MemoryStream memoryStream = new MemoryStream();
		using (CryptoStream stream = new CryptoStream(memoryStream, aesManaged.CreateEncryptor(), CryptoStreamMode.Write))
		{
			using StreamWriter streamWriter = new StreamWriter(stream);
			streamWriter.Write(q);
		}
		return Convert.ToBase64String(memoryStream.ToArray());
	}

	private static string S(string q)
	{
		char[] array = q.ToCharArray();
		for (int i = 0; i < array.Length - 1; i += 2)
		{
			char c = array[i];
			array[i] = array[i + 1];
			array[i + 1] = c;
		}
		return new string(array);
	}
}

And also important is Resources.kG:

aS6BpWo8WyKFzwRzntKjW+nuD4+IeeZbMM2OmQcsTf2fgWoE81bOah1hmiPTLOzP

So reversing the operations we can get the flag, here is my solve script:

from Crypto.Cipher import AES
import base64

kg = list("aS6BpWo8WyKFzwRzntKjW+nuD4+IeeZbMM2OmQcsTf2fgWoE81bOah1hmiPTLOzP")
key = b'valhallahpakkergodegaver'
iv = b'\x00' * 16

for i in range(0, len(kg) - 1, 2):
    kg[i], kg[i+1] = kg[i+1], kg[i]

ciphertext = base64.b64decode(''.join(kg))

cipher = AES.new(key, AES.MODE_CBC, iv=iv)

print(cipher.decrypt(ciphertext))
$ python solve.py
b'FDCA{1ndp4kk3t_g4ver_er_d3_8edste}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e'