FRA CTF · Network forensics · 3 of 7 flags documented
FRA CTF: Exfiltratören — Network Traffic Forensics
5 min read
- CyberChef
- Wireshark
- Python 3
- dCode
Objective
In FRA’s fictional scenario, a space-industry company suspects an employee of leaking information to someone planning a break-in. I investigated the supplied network capture to identify what had left the network and recover the concealed messages.
My notes document three recovered flags across FTP, email, and a custom UDP transfer. The work combines protocol inspection in Wireshark, Base45 decoding in Python, CyberChef transformations, and image-metadata inspection with ExifTool. This is a partial solution to the seven-flag challenge.
| Evidence trail | Recovered information |
|---|---|
| FTP → msg.txt → Base64 | flagga{functional_treshold_power} |
| SMTP → PDF → QR → Base45 → PNG | Door code 1632 and flagga{qrazy_basy} |
| UDP → reconstructed PNG → metadata → Base64 | A message about three gates and flagga{play_the_5_tones} |
Flag 1 — FTP
The FTP control conversation exposes a STOR msg.txt command: a file upload worth following. The key detail is the PORT command, because FTP carries commands and file contents on separate connections. Reading the control stream alone would miss the message.
PORT 10,0,0,10,160,249
160 × 256 + 249 = 41209
Wireshark display filter:
tcp.port == 41209Filtering on port 41209 and following the TCP stream exposes a short Swedish message about switching to disguised communication, followed by an encoded line.
I entered the encoded line into dCode’s Cipher Identifier to identify a likely encoding. Base64 Coding was its top suggestion, giving me a concrete transformation to try next.
I then pasted the same string into CyberChef and applied From Base64. The output reads flagga{functional_treshold_power}, confirming the suggested encoding and revealing the first flag. Base64 is an encoding rather than encryption, so this step decodes the text without a decryption key.
Flag 2 — Email & QR payload
The protocol hierarchy also shows SMTP traffic. Following that conversation reveals an email with a MIME attachment named presentkort.pdf and Content-Transfer-Encoding: base64. These headers identify a recoverable document inside the message.
I used Wireshark’s Export Objects → IMF to save the email, then opened its PDF attachment. The document looks like a coffee gift card, but its QR code supplies the next layer of data to investigate.
I saved the QR payload in qr.txt and decoded it with Python’s base45 package. Before treating the output as an image, the script printed its first eight bytes. The resulting PNG signature gave a concrete check that the decoded bytes had the expected file format.
from pathlib import Path
import base45
encoded = Path("qr.txt").read_text(
encoding="utf-8"
).strip("\r\n")
decoded = base45.b45decode(encoded)
print("File header:", decoded[:8].hex(" "))
Path("decoded.png").write_bytes(decoded)Opening decoded.png reveals a door code, 1632, alongside flagga{qrazy_basy}. The sequence connects the result back to the capture: an email attachment contains a QR code whose Base45 payload is itself an image.
Flag 3 — UDP & image metadata
The UDP conversations expose a custom JSON-based transfer. Its opening message announces top_secret.png, an expected size of 2,662,470 bytes, and an MD5 value. That is useful validation information: a readable image alone would not establish that every byte had been reconstructed correctly.
The response supplies a transfer ID, a key, and port 31337. Subsequent messages contain indexed chunks and acknowledgements with a chk field; the data stream carries hex-encoded content. These fields matter because packet order alone is not enough to reconstruct a UDP transfer, and the capture includes a negative acknowledgement.
First, order the data-bearing chunks by ix. Exclude the rejected chunk identified by chk: false, then combine the remaining data values in index order. This reconstructs a hex representation of the transferred bytes.
Next, use From Hex in CyberChef, then RC4 with the transfer key interpreted as hexadecimal. Hex decoding alone does not yield the expected PNG; RC4 produces output beginning with its file signature.
Ordered chunk data → From Hex → RC4
Key: 425c7548030e56735ef1c01c9182ec1f
Key format: HEX
Save the decrypted bytes as top_secret.pngFinally, compare the decrypted file with the announced size and checksum. The MD5 output shown below matches the advertised value.
ExifTool identifies the reconstructed file as a 1024 × 1024 PNG and exposes a User Comment containing encoded text. Inspecting metadata extends the investigation beyond the visible pixels: a recovered image can carry a separate message in its descriptive fields.
Decoding that comment from Base64 in CyberChef reveals a Swedish message about three gates, followed by flagga{play_the_5_tones}. This is the third flag documented in my analysis.
Takeaways
The central lesson is to follow the structure of the traffic: FTP control commands point to a separate data connection, MIME headers identify an attachment, and a custom transfer exposes its own indexing and validation fields. Each recovered artifact becomes evidence for the next step.
The UDP transfer highlights the value of checking each transformation: chunk indices establish order, the PNG signature identifies the decrypted format, and the checksum checks the reconstructed bytes. Metadata inspection then reveals information beyond the visible image.
Sources & tools used
FRA — official challenge ↗Challenge scenario and download. FRA lists seven flags in Exfiltratören; this write-up documents three.
Tools used
- CyberChef
- Wireshark
- Python 3
- dCode