Description
Figure out how they are communicating, then find the flag. Download tftp.pcapng.
Setup
Download tftp.pcapng.
wget <url>/tftp.pcapngSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Export all TFTP objects from the capture
ObservationThe 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.bashwireshark tftp.pcapngWhat 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.
- 1 = RRQ (read request):
Step 2Decode the text files with ROT13
Observationinstructions.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:'.bashtr 'A-Za-z' 'N-ZA-Mn-za-m' < instructions.txtbashtr 'A-Za-z' 'N-ZA-Mn-za-m' < planWhat 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.
Step 3Extract the hidden data from picture3.bmp
ObservationThe 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.bashsteghide extract -sf picture3.bmp -p DUEDILIGENCEbashcat flag.txtExpected 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.
-sfselects the stego file and-ppasses 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.