Silent Stream picoCTF 2026 Solution

Published: March 20, 2026

Description

We recovered a suspicious packet capture file that seems to contain a transferred file. The sender was kind enough to also share the script they used to encode and send it. Can you reconstruct the original file? Download the PCAP: packets.pcap and encoding encrypt.py .

Download packets.pcap and encrypt.py.

Open the PCAP in Wireshark and read encrypt.py to understand the encoding scheme.

bash
wireshark packets.pcap &
bash
cat encrypt.py
  1. Step 1Read the encoding script
    Open encrypt.py to understand the encoding scheme. The encoder adds a fixed key of 42 to each byte, modulo 256: encoded = (original + 42) % 256. The encoded bytes were then sent over the network and captured in the PCAP.
    bash
    cat encrypt.py
    Learn more

    This encoding scheme is a Caesar cipher applied to raw bytes rather than letters - also called a modular addition cipher or ROT cipher for bytes. By adding a fixed constant (42) to each byte modulo 256, the original byte values are shifted in the byte value space. Unlike XOR, this operation is not its own inverse: to decode, you subtract (or equivalently, add 256 - 42 = 214) rather than applying the same operation again.

    The key value of 42 is not cryptographically meaningful (it is famously "the answer to life, the universe, and everything" from The Hitchhiker's Guide to the Galaxy), emphasizing that this is purely an encoding scheme, not encryption. Real encryption requires keys that are large, random, and secret. A fixed, known key provides no security - it is purely obfuscation.

    In network forensics, understanding the encoding scheme is the first step before extracting and decoding data. Challenge authors often provide the encoding script to simulate a real-world scenario where an analyst has recovered both the captured traffic and, perhaps through source code review or endpoint forensics, the tool used to generate it.

  2. Step 2Find the right TCP stream and extract its payload
    List all TCP conversations sorted by byte count and pick the longest - that's the file transfer. Then dump that stream's raw bytes using tshark and xxd -r -p.
    bash
    # 1. Find the longest TCP conversation
    bash
    tshark -r packets.pcap -q -z conv,tcp
    bash
    # 2. Note the stream index of the largest one (column: Bytes)
    bash
    # 3. Extract that stream as raw binary
    bash
    tshark -r packets.pcap -q -z follow,tcp,raw,<STREAM_INDEX> | tail -n +7 | tr -d '\n' | xxd -r -p > encoded.bin
    Learn more

    tshark -z conv,tcp dumps a table of every TCP conversation with packet counts and byte totals on each side. Sort by the bytes column; the largest is your transfer. follow,tcp,raw,N selects stream N (zero-indexed) and outputs hex; the rest of the pipe strips header lines and decodes hex back to raw bytes.

    xxd -r -p decoded. -r means "reverse" (hex back to binary). -p means "plain": read continuous hex without expecting xxd's default format (offset column on the left, ASCII column on the right). Together, they consume a stream of hex digits and emit raw bytes, ignoring whitespace.

    See Wireshark for PCAP CTF for the broader pcap workflow and hex dumps for CTF for everything you can do with xxd.

  3. Step 3Reverse the encoding (subtract key 42)
    The decoding is the mathematical inverse: original = (encoded - 42) % 256. Apply this to every byte of the extracted stream to recover the original file.
    python
    python3 << 'EOF'
    with open("encoded.bin", "rb") as f:
        encoded = f.read()
    
    key = 42
    decoded = bytes((b - key) % 256 for b in encoded)
    
    with open("decoded.bin", "wb") as f:
        f.write(decoded)
    
    print(decoded.decode(errors="replace"))
    EOF
    Learn more

    The modular math. Decoding is (encoded - 42) % 256. Equivalent: (encoded + 214) % 256, since -42 mod 256 = 214. Python's % always returns a non-negative result for positive moduli, so (0 - 42) % 256 = 214 works without manual wrap. C-style % would return -42 for the same input; use (b - 42 + 256) & 0xFF in those languages.

    The errors="replace" argument to decode() substitutes a replacement character (U+FFFD) for any bytes that are not valid UTF-8. This makes the print safe even when the decoded output is binary. The next step runs file decoded.bin to identify the real format.

  4. Step 4Identify the decoded format and read the flag
    Always run file decoded.bin first - the decoded blob may not be text. PNG, ZIP, ELF, and PDF are all common, and each needs its own opener.
    bash
    file decoded.bin
    bash
    # If text:    cat decoded.bin
    bash
    # If PNG/JPG: xdg-open decoded.bin
    bash
    # If ZIP:     unzip decoded.bin
    bash
    # If ELF:     ./decoded.bin   (chmod +x first if needed)
    Learn more

    file reads the magic bytes and tells you the real format regardless of extension. If it says data or something unfamiliar, xxd decoded.bin | head shows the first bytes; the magic number usually identifies it (89 50 4e 47 = PNG, 50 4b 03 04 = ZIP, 7f 45 4c 46 = ELF, 25 50 44 46 = PDF).

    This pattern - encode before transmission, capture the traffic, reverse the encoding - appears in real incident response when attackers use light obfuscation to evade signature-based detection. More sophisticated obfuscation (real encryption, tunneling) needs deeper analysis, but the workflow of identifying the scheme and inverting it is the same.

Alternate Solution

The byte-level shift of +42 is conceptually the same as a Caesar cipher applied to raw bytes. Use the ROT Cipher tool on this site with a shift of -42 (or equivalently +214) to quickly decode the extracted byte stream without writing any Python code.

Flag

picoCTF{s1l3nt_str34m_...}

The encoding scheme is encoded = (original + 42) % 256 - extract the TCP stream from the PCAP, then reverse it with (encoded - 42) % 256 per byte.

Want more picoCTF 2026 writeups?

Useful tools for Reverse Engineering

Related reading

What to try next