Packets Primer picoCTF 2022 Solution

Published: July 20, 2023

Description

The PCAP file contains the picoCTF flag as plain ASCII, but the flag was transmitted one character per TCP segment, so it appears space-separated in the output. Running strings, grepping for the spaced pattern, and stripping spaces with tr extracts the clean flag.

Run strings on the PCAP to view printable data.

The flag appears space-separated in the output (each character is its own byte in the stream), so grep for p i c o to match it.

Pipe through tr -d ' ' to collapse the spaces and produce the clean flag.

bash
strings network-dump.flag.pcap | head
bash
strings network-dump.flag.pcap | grep 'p i c o'
bash
strings network-dump.flag.pcap | grep 'p i c o' | tr -d ' '

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1
    Use strings
    Observation
    I noticed the challenge provided a raw PCAP file and mentioned the flag was sent as plain ASCII over the network, which suggested that the payload would be sitting verbatim in the file bytes and that running strings would surface it without needing to parse any packet structure.
    This capture isn't even obfuscated. Running strings prints the readable ASCII inside the file, including the flag.
    What didn't work first

    Tried: Open the PCAP in Wireshark and search for the flag string using Edit > Find Packet with the string 'picoCTF'.

    Wireshark's string search looks for contiguous byte sequences, but each character was sent in a separate TCP segment, so the bytes 'p', 'i', 'c', 'o' are never adjacent in any single packet payload. The search returns zero results. The strings command reads the raw file bytes across segment boundaries, which is why it finds the spaced-out flag when Wireshark's per-packet search cannot.

    Tried: Run 'file network-dump.flag.pcap' or 'xxd network-dump.flag.pcap | head' to inspect the file format before extracting anything.

    These commands confirm the file is a valid PCAP and show the libpcap magic bytes, but they don't surface the flag payload. xxd prints hex alongside ASCII, so short printable runs get fragmented by packet metadata in between. The strings command is purpose-built to extract ASCII runs from binary files and gives a cleaner, flag-revealing output in one step.

    Learn more

    PCAP (Packet CAPture) files store raw network traffic recorded by tools like Wireshark, tcpdump, or tshark. The format stores each packet with a timestamp and the full byte content of the captured frame, including headers at every network layer (Ethernet, IP, TCP/UDP, application protocol). Any unencrypted payload transmitted over the network is present verbatim in the file.

    strings scans a binary file and outputs any sequence of printable ASCII characters that meets a minimum length threshold (4 by default). It doesn't understand packet structure - it just finds readable text wherever it appears in the raw bytes. This makes it a fast first pass for PCAP files: if anything interesting was sent in plaintext, strings will show it without needing to understand the protocol.

    The broader lesson is that any data transmitted over an unencrypted network channel is visible to any party who can capture traffic on that path - whether that's the ISP, a coffee shop router, or another host on the same network segment. This is why TLS (Transport Layer Security) is essential for any sensitive communication, and why protocols like HTTP, FTP, and Telnet have been superseded by HTTPS, SFTP, and SSH respectively.

  2. Step 2
    Clean the output
    Observation
    I noticed that the strings output showed the flag with a space between every character (for example, p i c o C T F), which indicated each character had arrived in its own TCP segment and that grep for p i c o combined with tr -d ' ' was needed to recover the contiguous flag string.
    The flag was transmitted one byte at a time over the TCP stream, so each character lands in a separate TCP segment. When strings reconstructs the readable runs from the raw PCAP bytes, it outputs the flag with a space between every character. Grepping for p i c o (with spaces) matches that line, and tr -d ' ' collapses it back into the standard flag format.

    A typical head of the output looks like this, with the flag spread across a single spaced line:

    Linux 5.4.0
    GET /index.html HTTP/1.1
    Host: 10.0.0.5
    User-Agent: curl/7.81.0
    Accept: */*
    HTTP/1.1 200 OK
    Content-Type: text/plain
    p i c o C T F { p 4 c k 3 7 _ 5 h 4 r k _ 0 1 b 0 . . . }
    Content-Length: 31
    Connection: close

    Piping through grep and tr produces the clean flag:

    $ strings network-dump.flag.pcap | grep 'p i c o' | tr -d ' '
    picoCTF{p4ck37_5h4rk_...}
    What didn't work first

    Tried: Run 'strings network-dump.flag.pcap | grep picoCTF' to find the flag in one shot.

    The literal string 'picoCTF' never appears as a contiguous run in the file because each character arrives in its own TCP segment, separated by packet metadata. grep picoCTF returns nothing. The flag is only findable by grepping for the spaced pattern 'p i c o', which matches the way strings outputs the separated bytes.

    Tried: Skip the tr step and submit the grepped line directly, treating the spaces as part of the flag format.

    The picoCTF flag format never includes spaces - the correct token is a compact alphanumeric string like picoCTF{p4ck37_5h4rk_...}. Submitting the spaced version will be rejected by the scoring system. The tr -d ' ' step is mandatory, not cosmetic, because the spaces are an artifact of the one-character-per-segment transmission and are not part of the original flag.

    Learn more

    The flag is sent one character per TCP segment, which is unusual but valid. Because each byte arrives as its own segment, strings sees them separated by the inter-segment metadata and prints a space between each character. This is why a naive grep picoCTF finds nothing - the literal string "picoCTF" never appears as a contiguous run. Searching for 'p i c o' matches the spaced-out line, and tr -d ' ' is the required step to collapse it into a usable flag, not an optional cleanup.

    For more structured PCAP analysis, Wireshark is the industry standard. Its "Follow TCP Stream" feature (right-click any TCP packet → Follow → TCP Stream) reconstructs the full conversation in human-readable form. tshark is the command-line equivalent: tshark -r file.pcap -q -z follow,tcp,ascii,0 prints the first TCP stream as ASCII text. These tools understand protocol structure and can filter, reassemble, and decode specific sessions far more precisely than raw strings.

    This challenge is the first of several in picoCTF that involve PCAP analysis. As the challenges progress, traffic becomes encrypted, protocols become more complex, and simple strings stops being sufficient - building toward skills in protocol dissection and traffic analysis that are directly applicable to network forensics and incident response work.

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.

Flag

Reveal flag

picoCTF{p4ck37_5h4rk_01b0...}

Site policy redacts the trailing characters. The flag appears space-separated in the PCAP (one char per TCP segment), so `tr -d ' '` is required to produce a submittable token.

Key takeaway

Unencrypted network payloads survive verbatim in PCAP files and are recoverable with strings even without parsing protocol structure; any protocol that sends data in plaintext leaves that data permanently visible to anyone who captured traffic on the path. This is why TLS is the baseline requirement for any channel carrying sensitive data, and why protocols like HTTP, FTP, and Telnet have been superseded by HTTPS, SFTP, and SSH.

Related reading

Want more picoCTF 2022 writeups?

Useful tools for Forensics

Do these first

What to try next