--:--
ping
download
upload
← back to blog

· ctf · forensics · writeups · author · 20 min read

FL1TZ CTF Winter 2025 — Forensics & Malware Analysis Writeups

For FL1TZ CTF Winter 2025 I authored the entire Forensics category, the Malware Analysis task, and the OSINT tasks. This post walks through the nine challenges I built — from event-log archaeology to memory-dump triage — with the full solve paths, the answers, and why each answer matters. The repo with every artifact is at github.com/0xZyyz/FL1TZ-CTF-Winter-2025.

I wanted these tasks to be realistic, intense, and fun, the kind that push your investigative skills to the limit.

The tools you needed


1. Seek & Hunt — Malware Analysis

In this task you dive into malware analysis. It’s a combined challenge: you need both static and dynamic analysis to uncover the true nature of a suspicious executable, and answer three questions about it.

1. What is the original name of the file?

Answer: pdhelper.exe

Use VirusTotal to check whether the file has been analyzed before, and to see its reputation and detections.

2. What scripting language was used to create the malware?

Answer: AHK (AutoHotkey)

Run it in ANY.RUN or a similar sandbox and watch its behavior to identify the scripting language (Python, PowerShell, AutoHotkey…).

3. Does the malware make use of any DLL files?

Answer: dx9_overlay.dll

Use VirusTotal to check the DLLs the malware relies on, and investigate their purpose and reputation.

FL1TZ{pdhelper.exe_AHK_dx9_overlay.dll}


2. RAMDive — Memory Forensics with Volatility 3

Special thanks to my partners in cyber-crime, Bitraven and Ghr4b, for inspiring this chaotic, malware-filled challenge. Without you, I wouldn’t have had the pure joy of digging through memory dumps and malware. You two are the real MVPs! 😎

Background

Read this part, it makes the rest a lot more fun.

This challenge is based on a real incident: my friend Bitraven (the crypto wizard behind FL1TZ CTF) managed to turn his PC into a digital disaster when malware — from Cloudflare, of all places — came in and completely wrecked it.

I love malware, trojans in particular, so this one got me thinking: what if I turn this chaos into a memory forensics challenge? So we did the most logical thing ever. Bitraven extracted the malicious executable, and I dove deep into a memory forensics investigation. What did we find? A network trojan with backdoor functionality: a little digital gremlin that pokes around your system, steals everything, and calls home to its attacker in Amsterdam. Classic, right? 😈

Malware analysis summary

To analyze the memory dump, we used Volatility 3. Below are the findings from the different plugins, with an explanation for each one.

A quick word about Volatility

Volatility is your digital detective, but instead of a magnifying glass it uses RAM dumps. It lets you look into a computer’s memory and see everything that was happening while the system was running: which processes were alive, which network connections were open, and what the machine was doing behind your back (like running malware!). You can find out whether a malicious process was lurking in the shadows, which user accounts were involved, and what happened right before things went south. It’s CSI for your computer’s brain — except instead of solving murders, you’re catching cybercriminals.

Key findings

1. Path of the malicious process

Answer: C:\Windows\Microsoft.NET\Framework\v4.0.30319\jsc.exe

python3 vol.py -f memdump.mem windows.cmdline

The command line of the running process (jsc.exe) shows that it lives inside the .NET Framework directory, which is suspicious. The malware is abusing .NET components to execute its payload.

2. SID and username the malware was running under

Answer: S-1-5-21-1261973874-1698488304-1739942524-1001_Zyyz

python3 vol.py -f memdump.mem windows.getsids

The SID (Security Identifier) identifies the account the process ran under. Here it’s the user Zyyz, so the attacker executed it with user-level privileges.

3. NTLM hash of the user

Answer: 7eb59e280c8fbc878955e0269cbe2ae9

python3 vol.py -f memdump.mem windows.hashdump

The NTLM hash is the user’s password hash stored in memory. Attackers can use it in Pass-the-Hash attacks to authenticate without ever knowing the plaintext password.

4. City of the attacker

Answer: Amsterdam

python3 vol.py -f memdump.mem windows.netscan

The malware opened a connection to an attacker-controlled server. A reverse lookup of the IP address tied to jsc.exe shows the server is in Amsterdam.

5. Ending address of the executable

Answer: 0xf8dfff

python3 vol.py -f memdump.mem windows.vadinfo

The ending address of jsc.exe in memory tells you the memory range allocated to the executable, which is useful for spotting code injection or memory-resident malware.

6. Memory protection flag of the process

Answer: PAGE_EXECUTE_WRITECOPY

python3 vol.py -f memdump.mem windows.vadinfo

This flag means the memory pages can be both executed and modified, something malware often relies on to inject shellcode into processes.

7. The DLL the process used for cryptographic functions

Answer: \Windows\SysWOW64\cryptbase.dll

python3 vol.py -f memdump.mem windows.vadinfo

cryptbase.dll is a Windows DLL for encryption and decryption. The malware most likely used it to steal sensitive data like passwords, encryption keys, or Bitcoin wallets.

8. Name of the computer

Answer: DESKTOP-AJM6HKU

python3 vol.py -f memdump.mem windows.envars

The malware reads the computer name to fingerprint the infected system, which helps the attacker tell victims apart.

9. Path of the temporary variable the process used

Answer: C:\Users\Zyyz\AppData\Local\Temp

python3 vol.py -f memdump.mem windows.envars

Lots of malware drops temporary files in AppData\Local\Temp, then deletes them after execution to cover its tracks.

10. Creation time of the process

Answer: 2025-02-04 03:21:09 UTC

python3 vol.py -f memdump.mem windows.pstree

The creation time anchors the timeline: it tells us exactly when the malware was executed on the system.

11. The Windows user registry the process interacted with

Answer: HKEY_USERS\S-1-5-21-1261973874-1698488304-1739942524-1001\SOFTWARE\MICROSOFT\WINDOWS NT\CURRENTVERSION

python3 vol.py -f memdump.mem windows.handles

This registry path stores system settings. Malware often touches registry keys like this for persistence or evasion.

12. The 9th privilege of the process

Answer: SeTakeOwnershipPrivilege

python3 vol.py -f memdump.mem windows.privileges.Privs

SeTakeOwnershipPrivilege lets a process take ownership of files and objects, which can be used to bypass access restrictions and exfiltrate files.

13. The secret message hidden in memory

Answer: FL1TZ{U_G0T_M3!}

python3 vol.py -f memdump.mem windows.strings | grep -i FL1TZ

Searching the ASCII and Unicode strings in memory turns up this message inside the malware’s memory space.

14. Number of threads of the process

Answer: 5

python3 vol.py -f memdump.mem windows.thrdscan

Threads are the active execution paths inside a process. Several threads usually mean parallel work, which is typical for backdoors and network-based malware.

15. The DLL the process used for system calls

Answer: ntdll.dll

python3 vol.py -f memdump.mem windows.dlllist | grep -i jsc.exe

ntdll.dll is the core Windows DLL behind system calls and low-level OS interactions. Malware often hooks it to hide its activity.

FL1TZ{R4M_TR4C3_UNl0CK}


3. Operation LogTrace — Event Log Forensics

In this challenge you investigate a cyber attack by analyzing Windows event logs: security logs, system logs, and PowerShell script logs, to trace what the attacker did — from how they got in, to what they did, to how they tried to cover their tracks. Special thanks to Stoura, my first-year professor, who inspired this whole challenge.

Task background

For this investigation I executed the whole attack chain myself: running PowerShell commands, opening HTTP and TCP connections, downloading malicious files, escalating privileges, viewing hashes, and even trying Pass-the-Hash. The challenge is a deep dive into the event logs that recorded all of it.

Questions, answers and explanations

1. When was the new user created?

Answer: 2025-01-30 00:24:29

Log: Security, Event ID 4720

Event ID 4720 means “a user account was created”. Knowing when the attacker created a new user matters because it shows when they gained access to the system.

2. What is the credential key identifier of the new user?

Answer: 0x422304C2319BA5917BD4EC2B6A7E9FE61D95D1E773EE0886CE36BB51AFFDC22E

Log: Crypto-DPAPI operational log

This is the unique identifier of the credential key tied to the new user. DPAPI (Data Protection API) is what Windows uses to encrypt sensitive data like credentials, and this identifier is needed to decrypt the credentials associated with that user.

3. Name the script the new user used for privilege escalation.

Answer: UAC_BYPASS.ps1

Log: PowerShell Operational, Event ID 4104 (Script Block Logging)

This PowerShell script bypasses User Account Control (UAC), a common privilege escalation technique. By running it, the attacker elevated their privileges and got more control over the system.

4. Which private IP address hit an error while trying to connect to the network?

Answer: 10.0.2.15

Log: DHCP, Event ID 1002

This IP address failed to get a valid lease, and the DHCP logs recorded the error. It can point to a compromised device, or to the attacker’s own machine, struggling to connect.

5. What’s the socket used to download the malware?

Answer: 192.168.100.57:8000

Log: PowerShell Operational, Event ID 4104

The attacker pulled the malware onto the compromised system from this IP and port, a server under their control.

6. Which registry key was modified to persist a backdoor for a specific user profile?

Answer: HKU\S-1-5-21-1261973874-1698488304-1739942524-1002\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\Backdoor

Log: Sysmon, Event ID 13 (filter on “Malware”)

Values under the Run key execute every time the user logs in, so this entry makes sure the backdoor keeps coming back. Modifying Run is one of the most common persistence tricks.

7. What technique did the attacker use to access a remote system without a plaintext password?

Answer: Pass-the-Hash

Log: PowerShell Operational, Event ID 4104

In a Pass-the-Hash attack, the attacker authenticates with the hash of the user’s password instead of the password itself, typically after stealing hashes from one system to reach others.

8. Name the device Stoura tried to connect to remotely but failed.

Answer: LAPTOP-3CU59SBJ

Log: Event ID 32784 (Windows Remote Management error)

Stoura tried to reach this device over WinRM and failed, and the error was logged. A failure like this can be a sign of an attacker trying to pivot, or move laterally, and hitting an obstacle.

9. What is the primary domain the attacker exfiltrated sensitive files to?

Answer: attackerserver.com

Log: PowerShell Operational, Event ID 4104

The attacker uploaded sensitive files to this domain. Knowing it is essential to understand the scope of the data exfiltration.

10. Stoura used a tool to dump the user’s passwords. What’s its process GUID?

Answer: {2f06b238-dd55-679a-7d08-000000000900}

Log: PowerShell Operational, Event ID 4104

The process GUID identifies the exact process of the password-dumping tool in the logs, which is key to tracking which tools were used to compromise the system.

11. What is the content of the secret file?

Answer: FL1TZ{w4n3z8u9fgh32m2i}

Log: Sysmon, Event ID 15

Sysmon event 15 (FileCreateStreamHash) recorded the secret file, and its content is this flag-formatted string.

12. What is the name of the ADS file created?

Answer: hidden_stream.txt

Log: Sysmon, Event ID 15

The attacker created an Alternate Data Stream named hidden_stream.txt to hide data. ADS is an NTFS feature that lets a file carry multiple streams of data, which makes it a handy place to hide malicious content.

13. What’s the password inside the hidden file?

Answer: trustno1

Log: Sysmon, Event ID 15

The hidden stream hidden_stream.txt holds a password hash. Crack it with an online tool like CrackStation and you get the password.

What you’ll learn

By working through these logs you uncover the full scope of the attack, from privilege escalation to exfiltration. It’s like piecing together a cyber-thriller, one event log at a time.

FL1TZ{Ev3nt_L0gs_R3v3@l_Th3_Truth}


4. MFT Chronicles — Unveiling the Attacker’s Footprints

What is the MFT?

The Master File Table (MFT) is a critical part of the NTFS file system. It keeps a record of every file and directory on an NTFS disk: names, timestamps, attributes, and where the data lives. Every file has an entry in the MFT, which makes it a goldmine for investigating file activity, deletions, and modifications.

Extracting the MFT data

Parse the $MFT into a CSV with Eric Zimmerman’s MFTECmd:

MFTEcmd.exe -f "$mft" --csv "file.csv"

1. Identify the malicious .lnk file.

Answer: malware.exe.lnk

.lnk files are Windows shortcuts. Attackers often use them to launch malicious payloads while disguising them as legitimate shortcuts. Here, malware.exe.lnk points to an executable used in the attack.

2. What was the last modification time of the malware?

Answer: 2025/01/28 20:33:27

The MFT records creation, modification, and last-access timestamps. The modification time tells us when the attacker last changed the malware file, which helps build the attack timeline.

3. What was the malicious IP the attacker downloaded a malicious archive from?

Answer: 192.168.100.57

The attacker downloaded a malicious archive from an external server. This IP is the source of the file, which helps track the attacker’s infrastructure.

4. The attacker downloaded a tool used for detailed system activity. What was its name?

Answer: Sysmon

Sysmon (System Monitor) logs detailed system activity. Defenders usually deploy it for monitoring, but an attacker can install it too, to watch the system while working on persistence, privilege escalation, or defense evasion.

5. What was the path of the server-side application run in Python?

Answer: /Users/Zyyz/Downloads/server.py

The attacker ran a Python script named server.py from the user’s Downloads folder. It likely acted as a malicious server or command-and-control (C2) component.

6. The attacker created a memory dump. What was its creation time?

Answer: 2025/01/23 09:51:16

Memory dumps capture the contents of RAM. Attackers create them to extract sensitive data like passwords, encryption keys, or session tokens, and the timestamp tells us exactly when this happened.

7. The attacker downloaded a script for privilege escalation. Name it.

Answer: UAC_BYPASS.ps1

A UAC bypass escalates privileges to admin on Windows. This PowerShell script abuses User Account Control to run high-privilege commands without the user’s consent.

8. Which executable did the attacker use to retrieve security keys?

Answer: mimikatz.exe

Mimikatz is the well-known post-exploitation tool for pulling credentials, security keys, and NTLM hashes out of memory. It powers pass-the-hash, pass-the-ticket, and many other credential theft techniques.

FL1TZ{MFT_F1l3_Xtr4ct3d_9d4c}


5. Scripted Chaos — File Carving & Layered Decoding

We’re given a capture file and need to analyze its HTTP traffic to uncover the hidden flag. It’s an onion of encodings: every layer reveals the next.

1. The capture reveals two files

Extracting the objects from the HTTP traffic gives two files:

2. Investigating no_need

no_need contains JFIF (JPEG) data, but it looks incomplete. Instead of making assumptions, we move on to important.js.

3. Analyzing important.js

important.js is mostly garbage, but hidden in it there’s hex-encoded text. Decoding the hex gives obfuscated text, and after a closer look we identify it as a VBE (VBScript Encoded) file.

4. Deobfuscating the VBE script

Save the extracted data as a .vbe file and run it through an online VBE decoder, like master.ayra.ch/vbs/vbs.aspx. That turns the VBE back into a readable VBS script.

5. Decoding the VBS script

The VBS is readable now, but still not clear. It contains Base64 data; concatenating and decoding it gives a PowerShell script:

function Invoke-ObscureRoutine1 {
    $strMsg1 = "System diagnostics in progress..."
    Write-Host $strMsg1
    Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 2)
}

function Invoke-ObscureRoutine2 {
    $strMsg2 = "Executing deep scan for threats..."
    Write-Host $strMsg2
    Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 2)
}

And inside the PowerShell script, there’s another Base64 layer.

6. Extracting the JSON data

Decoding the Base64 inside the PowerShell script gives a JSON file, holding yet another Base64 string:

{
    "image_part": "fMKpw6sFFFFABRRRQAUUUUAFFFF...AFFFFAHw7/DmQ=="
}

7. Reconstructing the JPEG

Decoding that last Base64 string gives what looks like random data. Remember no_need from earlier? This is its missing part. Append the data to no_need in a hex editor and the image comes back:

The reconstructed no_need image

The reconstructed image contains a Pastebin link, pastebin.com/KJbQFy3z, and the paste gives us a flag.

9. Extracting flag.rar

We submit it… and it’s wrong??? Oh! We almost forgot the password-protected flag.rar from the handout. The “flag” from Pastebin is its password. Extract the archive with it, and flag.txt inside holds the real flag:

FL1TZ{D1G_D33P3R_7H3_H1DD3N_53CR37_L13S}


6. Time’s Whisper — ICMP TTL Steganography

We’re given a capture file and need to analyze its ICMP packets to uncover a hidden flag.

1. Inspecting the ICMP packets

In Wireshark, the TTL (Time-To-Live) values of the ICMP echo requests keep changing, which is not normal.

2. Identifying the pattern

The TTL values only range between 64 and 67. In binary, only the two least significant bits change. So the flag is encoded as the concatenation of the last two bits of every ICMP request.

3. Filtering the relevant packets

To isolate the packets that carry data, apply this display filter:

icmp && !(frame.len == 60) && icmp.type == 8

That leaves 108 packets, so 216 bits, so 27 characters.

4. Extracting the flag

A small Python script does the rest: read the TTLs of the filtered packets, keep the last two bits of each, concatenate them into a binary string, and convert it to ASCII.

from scapy.all import rdpcap, IP, ICMP

bits = ""
for pkt in rdpcap("Capture.pcapng"):
    # ICMP echo requests only, skipping the 60-byte noise frames
    if ICMP in pkt and pkt[ICMP].type == 8 and len(pkt) != 60:
        bits += format(pkt[IP].ttl & 0b11, "02b")   # keep the 2 LSBs of the TTL

print(bytes(int(bits[i:i + 8], 2) for i in range(0, len(bits), 8)).decode())

FL1TZ{P1NG_P0NG_W1TH_1CMP!}


7. Echoed Mysteries — ICMP Destination Unreachable

In this challenge we analyze network traffic with Wireshark.

1. Filter the Destination Unreachable packets

Use this display filter to find the ICMP Destination Unreachable (type 3) messages with a length of 61:

icmp.type == 3 && frame.len == 61

2. Inspect the data section

Click one of the packets, expand the Packet Details pane, and look at the Data section. Destination Unreachable messages carry part of the original packet, and here that’s where the payload hides: each of the 32 packets carries one character of the flag.

3. Extract the hidden flag

Read the characters in order, or let tshark do it in one line:

tshark -r Chall.pcapng -Y 'icmp.type == 3 && frame.len == 61' -T fields -e data.data | tr -d '\n' | xxd -r -p

FL1TZ{H1DD3N_1N_1CMP_P4CK37S!!!}


8. The Disguised Artifact — HTA That’s Actually an ISO

We’re given a file named FLAG.hta, and it looks corrupted. The task: analyze and repair it to uncover the hidden flag.

1. Identify the true file type

First, check the file type:

$ file FLAG.hta
FLAG.hta: data

data means the type isn’t recognized, so the file is corrupted or disguised. The .hta extension suggests an HTML Application, but we need to dig further.

2. Analyze the file with a hex editor

Open it in a hex editor like HxD. Looking through it, you spot the string PowerISO, a strong sign that this is actually an ISO image whose extension was changed to .hta to disguise it.

3. Fix the corruption

An ISO 9660 image carries the signature CD001 at offset 0x8001. Here, it was tampered with:

$ xxd -s 0x8000 -l 16 FLAG.hta
00008000: 0144 4431 3233 0100 5769 6e33 3220 2020  .DD123..Win32

Replace DD123 with CD001 in the hex editor, save it as FLAG.iso, and it’s recognized again:

$ file FLAG.iso
FLAG.iso: ISO 9660 CD-ROM filesystem data '31_01_2025'

4. Mount the ISO

On Linux:

sudo mount -o loop FLAG.iso /mnt/iso

On Windows, use PowerISO or WinCDEmu.

5. Fix the corrupted image

Inside the ISO there’s a PNG file, and it’s corrupted too. To fix it:

6. Recover the flag

Once the PNG is fixed, open it to reveal the flag.

FL1TZ{D3crypt_th3_Secr3t_Mount}


9. Unveiled — Hidden Clues in an Image

1. Read the license.txt file

The handout comes with an image and a license.txt. At the bottom of the license you’ll find:

For any queries, please contact artivive@gmail.com

2. Recognize the keyword: Artivive

Artivive is an augmented reality (AR) platform: it overlays digital content on images when you scan them with the Artivive mobile app. So the image probably hides AR content.

3. Scan the image

Scan the given image with the Artivive app, and the overlay reveals the flag.

FL1TZ{H1DD3N_TR34SUR3_Unl0ck3d}


Final Thoughts

Building this category was a blast — a full attack narrative spanning event logs, the MFT, memory, network captures, and layered malware. I put a lot of effort into making these tasks realistic, challenging, and fun, and I hope you had a great time playing them. Big thanks to everyone who played, and to Bitraven, Ghr4b, and Stoura for the inspiration. Full artifacts: github.com/0xZyyz/FL1TZ-CTF-Winter-2025.