NEXSEC 2025 - Intervarsity Cyber Forensics Challenge
An intervarsity digital forensics competition with categories such as Reverse Engineering, Malware Analysis, Digital Forensics and Threat Response
This is our writeup for Team Bla Bla Bla which consists of me and 2 Forensic 🐐.
Preliminary Round
Rev/Advisory
Q1 : The binary presents itself as a legitimate document viewer, but preliminary analysis suggests otherwise. Reverse-engineer the binary and identify the DLL name used by the malware to blend in with legitimate system files.
Analyzing the distributed files, we are given a binary, a Word document and a dll file

When analyzing the binary in IDA, we can see it calls
LoadLibraryA is a Windows API function used to dynamically load a DLL at runtime rather than linking it statically at compile time
nexsec25{vcruntime140.dll}
Q2 : What directory does the malware copy itself to?
By examining the malware’s control flow in main(), we see that the executable does not perform any direct copying itself. Instead, it loads a malicious, trojanized vcruntime140.dll and the main program behaviour is inside the DLL.

That DLL function explicitly copies itself to
nexsec25{C:\ProgramData\MicrosoftSyncService}
Q3 : Uncover the exported function used to achieve persistence.

Based on our findings earlier, we have identified that __vcrt_InitializeCriticalSectionEx is the function that is being called.
nexsec25{__vcrt_InitializeCriticalSectionEx}
Q4 : What is the command and control (C2) domain that the implant communicates with?
When looking for a command and control (C2) domain, we suspected that the string could be encrypted and began looking for decryption routines

Looking at the imported functions, we can see that theres Crypto APIs being called. We then proceeded to trace where it was being called.

Looking at its cross references, we can see the function to decrypt is being called here at CreateFrameInfo(). The data being decrypted is located at unk_25D7F5020 and it has a size of 0x270 bytes. Our next step would be to identify the encryption algorithm.


Looking at the API docs for CryptImportKey, it expects a pbData struct


The PUBLICKEYSTRUC expects a aiKeyAlg parameter which determines the encryption algorithm.


By examining this structure in IDA and cross-referencing the ALG_ID value with official documentation, the algorithm was identified as Triple DES (3DES).
Key Material (from hardcoded QWORDs)
pbData = 0x12`, so the IV becomes
Then, we can recreate a decryption script like this
Looking at the strings from the decrypted shellcode, we can find our domain name after removing the "H" at the end of the string

The decrypted shellcode ultimately reconstructs the following command
nexsec25{fj3m58a9.capturextheflag.io}
Rev/QuackBot
Q1 : We identified a phishing campaign that uses several evasion techniques to deliver malware. Our visibility is limited to the malicious email attachment; any activity beyond that point requires further malware analysis. Analyse the malware to find what evil action being done by it.

Noticed the QuackBot.quack file is a PYC compiled binary

Reversed it using pylingual and noticed that it is a Kramer compiled binary, so we used https://github.com/jcarndt/kramer_decryptor/blob/main/kramer_decryptor.py to decrypt but ran into issues

It seems to be unable to extract the necessary ceb6 patterns even though the QuackBot.quack file clearly had the ceb6 pattern. So I modified the script such that the regex is more relaxed and is capable of finding the ceb6 pattern


After successfully decrypting it, it seems like it is running shellcode.
We were unable to emulate the shellcode using scdbg. Hence we converted the shellcode to an exe using https://github.com/accidentalrebel/shcode2exe and analyzed it in IDA.

Main entry point calls sub_4063c5
PEB Walk

sub_40C13C dynamically resolves a function address without using GetProcAddress by walking the Process Environment Block (PEB) and inspecting the export tables of all loaded modules. It is a core component of a hash-based API resolution mechanism commonly used in malware loaders and shellcode.
The hash_lo and hash_hi are both 32 bit values that are combined to form a 64 bit value which would be the expected hash after calculating the hash of the module name and the function name. The hashing is calculated from:

Knowing that it will dynamically resolve WindowsAPI, the common targets would be VirtualAlloc(). So, we had an idea that the shellcode will eventually copy the next stage payload somewhere

After debugging the shellcode, we find out that it will call sub_40ab95()

sub_40C5B1() copies a really large blob of bytes from somewhere to a memory region located at v6. After that sub_40C2A9() decrypts that payload.

We set a breakpoint at the call to sub_40C2A9(). It appears that argument 1 is our key, argument 2 is the IV and argument 3 is the destination buffer for the decrypted payload. Hence, our goal is to dump the values at 0x001B023C with the length of 0x5184 bytes.
Use this ida script to dump the binary after sub_40C2A9() completes execution


Now there are readable strings inside and it looks like theres an exe embedded inside.

We extracted the exe using dd. The resulting binary seems to be making a bind shell by opening a TCP listener, and it executes a cmd.exe command.

The variable off_140003000 also contains a bunch of invalid IP addresses. We can decode these IP addresses from octal back to decimal to get the flag
nexsec25{513afc1272b40668995da3f69faeee5b37dd58beccc9fbf41cc3b44a58669de6}
Final Round
We were given 40gb worth of artefacts which consists :
ova file of Workstation (patient 0)
ova file of FS server
packet capture (pcap) of FS server
Splunk instance
After trying to start the VM and lagging for 10 minutes whenever the VM was booting up, I realised this couldnt continue if I were to be able to continue analyzing it. So I extracted the .ova file using 7z and obtained a vmdk file. Then, converted it to a format that FTK Imager can read.

Another interesting thing was, there were no challenge questions given to us and we would have to investigate it ourself and come up with all the IOCs, technical details and timeline of events. The questions would only be released about 1 hour before the competition ended for us to submit all of our findings.
Without knowing what questions may come up, it was important to gather all the details and IOCs first. This writeup will focus on answering the final questions and would not necessarily reflect our thought processes when initially looking for the artefacts
MD5 Madness
What is the SHA256 hash of the malware?

When navigating to the Public folder, we found explorer.exe here which should'nt be in this folder in the first place. So we uploaded it to VirusTotal. Later on when we reversed this binary, we will find out that it is actually the C2 agent thats running.
NEXSEC25{59CEBD35102C4164A6CA164B6BDA97AFE56984CB35C3F572A66343F774474542}
File Name I
Identify the initial file responsible for the compromise
When analyzing powershell commands in Splunk, we noticed there was a suspicious powershell command with a parent process coming from WINWORD.EXE which suggests the user may have opened a macro enabled document.
Virustotal however identified the document as exploiting CVE-2017-0199, a vulnerability that allows arbitrary code execution when a document references a malicious external template
NEXSEC25{YEAR-END-FINANCIAL-REPORT-2025.docx}
Credential Catcher
What file did the attackers use to dump the credentials?
Once again, when analyzing powershell commands in Splunk, we found a mimikatz binary renamed into a different name.
NEXSEC25{Neurotransmitter.exe}
Acteur de la menace
What is the name of the Threat Actor?
There were clues scattered around the filesystem about the name of the Threat Actor. We can also navigate to the IP address of the C2 and find the login page.

NEXSEC25{SilentRimba}
Adversary Tool Hosting Activity
Identify the username associated with the account used by the threat actor to host additional tools.
NEXSEC25{TomatoTerbang}
Internal Propagation Account
Which user account was abused by the threat actor to facilitate lateral movement across internal systems?
After the attacker managed to dump OS credentials, they used Cerebrum.ps1 to perform Pass-the-Hash into FS-CORP.
NEXSEC25{itdadmin}
Victime d'un logiciel de rançon
Who is the patient zero of this ransomware attack?
We have identified that fakhri.zambri received the phishing email and opened the document.
NEXSEC25{fakhri.zambri}
Command and Control
What is the IP address associated with the Command-and-Control (C2) server utilized by the adversary?
explorer.exe is a dotnet binary that is intentionally protected by Eziriz .NET Reactor to make it hard to reverse engineer. The main functionalities are located in NetworkDiagnostics.dll

NEXSEC25{209.97.175.18}
Lateral Movement
Based on Mitre Att&ck ID, what is lateral movement used by the threat actor?
Based on
The script closely resembles Invoke-WMIExec. The Mitre Att&ck ID for this is T1047
nexsec25{T1047}
Key Decryption
Identify the hash of the decryption key associated with the compromised file share server
Before looking for the decryption key, we analyzed the ransomware. The ransomware generates a random 32 byte AES key for each file that is being encrypted. Then, the AES key is encrypted using a hardcoded RSA public key.
Without knowing the attacker's private key, it is impossible to be able to decrypt the files. After finding nothing in the file system, we turned our attention to the attacker's C2 infrastructure.
Going through the endpoints of 209.97.175.18, only /victim is valid. The /victim endpoint seems to be vulnerable to SQL injection in the uniqueID parameter

Then, using SQLMap we dumped the database.

When dumping the c2 database victims table, we can find a unique_agentId column for itdadmin which has the value c18dabd3-bd18-453e-ba11-ba51ef1d5120

When dumping the agents table, we can find the agent_uniqueId as well as base64 encoded blobs. One of them is the public key and another is the private key. After identifying the private key, we can decrypt our files and recover what was lost. By calculating the sha256 of the private key we get
NEXSEC25{b706d87ab56ecb51bbbfc98d62d6642a86b898f49f028b665761917dabb4a2b0}
File Recovery
As part of the recovery effort, restore the contents of C:\Users\itdadmin\Documents\2025. Once recovered, determine the SHA-256 hash of the file "report-of-june-2025_compressed.pdf"
With the private key, we can just write a decryption script

nexsec25{b1134f54cff738629f94bc979b6c2ad6f15d8d191cad8fe1007508ce47086424}
Reconstructed Timeline of Attack
Final Thoughts
Overall this was a very fun CTF. The challenges were really good, especially Reverse Engineering imo. It might feel guessy at first because we are used to the jeopardy format, however it was really fun finding a clue and working off that clue to find the next until you can eventually piece together the entire chain of events.
Last updated