Skip to main content

Trivial Flag Transfer Protocol picoCTF 2021 Solution

A packet capture involving a file-transfer protocol and steganography. Piece together the clues to extract the flag.

Published: April 2, 2026Updated: August 13, 2026

Description

Figure out how they are communicating, then find the flag. Download tftp.pcapng.

Download tftp.pcapng.

bash
wget <url>/tftp.pcapng

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Export all TFTP objects from the capture
    Observation
    The capture is named tftp.pcapng, and TFTP moves files in plaintext over UDP. So every transferred file is recoverable straight out of the capture with Wireshark's Export Objects.
    Open tftp.pcapng in Wireshark, then File > Export Objects > TFTP. You'll recover instructions.txt, plan, picture1.bmp, picture2.bmp, picture3.bmp, and program.deb.
    bash
    wireshark tftp.pcapng
    What didn't work first

    Tried: Trying to extract files with tcpdump or tshark -r tftp.pcapng -x instead of Wireshark's Export Objects menu

    tshark -x prints raw per-packet hex, not reassembled payloads, and TFTP splits its DATA blocks across many UDP frames, so you get fragments rather than files. Wireshark's Export Objects for TFTP follows the DATA block sequence numbers and reassembles each transfer for you.

    Tried: Filtering for HTTP or TCP streams in Wireshark expecting to find transferred files there

    TFTP runs over UDP port 69, so TCP stream reassembly finds nothing at all. Export Objects works only with TFTP selected from the protocol list; the HTTP entry comes back empty. Check the Protocol column: frames labeled TFTP under UDP confirm you are in the right place.

    Learn more

    TFTP packet primer. TFTP runs over UDP/69 with a tiny opcode-driven format:

    • 1 = RRQ (read request): opcode | filename\0 | mode\0
    • 2 = WRQ (write request): same shape as RRQ
    • 3 = DATA: opcode | block# | up to 512 bytes
    • 4 = ACK: opcode | block#
    • 5 = ERROR: opcode | errcode | message\0

    Filename and mode in RRQ/WRQ are NUL-terminated ASCII strings. Because everything is plaintext, Wireshark's Export Objects walks the DATA blocks and reassembles complete files. See Wireshark for CTF for the broader protocol-analysis playbook.

  2. Step 2Decode the text files with ROT13
    Observation
    instructions.txt and plan hold text with recognizable English word shapes but uniformly shifted letters, which is the mark of a letter substitution. ROT13 is the obvious first try, being the common self-inverse shift on a 26-letter alphabet.
    instructions.txt and plan are ROT13. Decode them to learn the steg tool (steghide) and the passphrase. Look for the passphrase on a clearly-marked line: often the last line of the file or a label like 'password:' or 'passphrase:'.
    bash
    tr 'A-Za-z' 'N-ZA-Mn-za-m' < instructions.txt
    bash
    tr 'A-Za-z' 'N-ZA-Mn-za-m' < plan
    What didn't work first

    Tried: Trying caesar cipher with a different shift (ROT7, ROT18) because the first few words still look garbled

    ROT13 is a shift of 13 and its own inverse, so one application decodes the message completely. If the output still looks garbled, the usual cause is running tr against the wrong file, or misreading a filename from the Wireshark export. Check the exact names Export Objects produced; they are case-sensitive.

    Tried: Using base64 -d or xxd to decode the text files instead of ROT13

    Base64 output uses only alphanumerics plus plus, slash, and equals, and shows no English word shapes however you shift it. These files carry recognizable but shifted words, HFRQ decoding to USED, which is the signature of a letter substitution rather than base64.

  3. Step 3Extract the hidden data from picture3.bmp
    Observation
    The decoded plan names steghide as the tool, picture3.bmp as the carrier, and DUEDILIGENCE as the passphrase. That is everything needed to run steghide extract against that one image.
    Use steghide on picture3.bmp with the recovered passphrase (DUEDILIGENCE in the canonical solve). The output file contains the flag.
    bash
    steghide extract -sf picture3.bmp -p DUEDILIGENCE
    bash
    cat flag.txt

    Expected output

    picoCTF{h1dd3n_1n_pLa1n_51GHT_...}
    What didn't work first

    Tried: Running steghide extract on picture1.bmp or picture2.bmp with the recovered passphrase instead of picture3.bmp

    steghide reports no extractable data, or a capacity or checksum error, on any carrier with no payload in it. Only picture3.bmp holds hidden data, and the decoded plan names the third image explicitly. Re-read the decoded output to confirm which file it points at.

    Tried: Trying zsteg or binwalk on the .bmp files instead of steghide, because those are common stego tools

    zsteg reads PNG and BMP LSB planes and knows nothing about steghide's format, which alters pixel colour values in the spatial domain and encrypts the payload with AES keyed by the passphrase. zsteg shows random-looking LSB data rather than the flag. The decoded instructions name steghide, so passphrase-based extraction with steghide -sf is the path.

    Learn more

    Steghide hides data inside image and audio carriers by tweaking pixel/sample values; the payload is encrypted with a passphrase. -sf selects the stego file and -p passes the passphrase. See steganography tools for the broader toolkit (zsteg for PNG LSB, binwalk for embedded archives, stegsolve for visual bit planes).

    This challenge chains TFTP recovery, ROT13 decoding, and steghide extraction. Each clue is hidden in the previous step's output, a common multi-stage pattern in forensics CTFs.

Interactive tools
  • Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
  • Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
  • StegallDrop any file and Stegall runs every applicable steg technique in parallel: LSB sweeps, bit planes, spectrograms, polyglot carving, metadata, whitespace decode, and a 6-layer base/ROT/XOR/zlib cascade. Recursively unpacks results and surfaces flag matches.

Flag

Reveal flag

picoCTF{h1dd3n_1n_pLa1n_51GHT_...}

TFTP transfers files without encryption: export all objects from the capture, decode the ROT13 instructions to recover the steghide passphrase, and pull the flag out of picture3.bmp.

Key takeaway

Multi-stage forensics chains mirror how real exfiltration works: a cleartext protocol, a simple cipher, a steganographic carrier, each adding friction without adding security. TFTP exposes every transferred file to any observer, ROT13 is an illusion of privacy rather than encryption, and steghide only hides data once the passphrase is recoverable. Anyone with the full packet capture peels every layer offline, which is why defense in depth means real encryption at every hop, not obscurity at one.

Related reading

Useful tools for Forensics

Where to go next