Skip to main content

Very very very Hidden picoCTF 2021 Solution

A forensics challenge involving a packet capture and an image file with a hidden payload embedded using steganography.

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

Description

Find the hidden flag. A packet capture file is provided containing network traffic - dig through it to uncover something suspicious.

Download try_me.pcap. Get the files from the challenge page on CyLab Security Academy (formerly play.picoctf.org).

Install Wireshark to inspect and export objects from the capture.

bash
sudo apt install wireshark

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Export HTTP objects from the capture
    Observation
    The capture mixes TLS-encrypted traffic with plain HTTP. Export the HTTP objects first, since those transfers are readable immediately and may well carry something suspicious.
    Open try_me.pcap in Wireshark. Most traffic is TLS-encrypted, but five plain HTTP transfers are visible. Use File > Export Objects > HTTP and click Save All. Among the exports you will find duck.png and evil_duck.png. Both images share the same pixel dimensions, yet evil_duck.png is more than twice the file size of duck.png despite appearing lower quality - a clear sign that extra data is packed inside it.
    bash
    # In Wireshark: File -> Export Objects -> HTTP -> Save All
    bash
    ls -lh duck.png evil_duck.png
    bash
    file duck.png evil_duck.png
    What didn't work first

    Tried: Running steghide extract -sf evil_duck.png to find the hidden data

    steghide uses its own passphrase-protected format, modifying DCT coefficients in JPEG or manipulating a palette, and reports that it could not extract anything, because this PNG uses Invoke-PSImage's 4-bit pixel encoding instead. No passphrase guess helps. Read the raw pixel values with PIL.

    Tried: Running zsteg evil_duck.png to detect the hidden payload automatically

    zsteg scans common LSB bit-planes but defaults to one bit per channel. Invoke-PSImage writes into the low four bits, so zsteg returns garbled output or nothing. Target bits 0 through 3 of the blue and green channels directly rather than relying on a generic scanner.

    Learn more

    Why evil_duck.png is suspicious. When two images are the same dimensions but one is dramatically larger, the extra bytes are almost always hidden payload rather than image data. Standard tools like steghide and zsteg find nothing here because the data is not hidden with those schemes.

    The HTTP traffic also reveals a tell: Wireshark's Server Name column shows the user browsed GitHub, Microsoft documentation, and powershell.org before the image downloads. That browsing trail is a hint that PowerShell steganography is involved.

  2. Step 2Identify the steganography scheme: Invoke-PSImage
    Observation
    evil_duck.png is more than twice the size of duck.png at identical dimensions and visibly lower quality, and the capture's browsing history includes PowerShell and GitHub. That points at a PowerShell pixel steganography tool such as Invoke-PSImage.
    Searching for 'powershell steganography' surfaces the peewpw/Invoke-PSImage GitHub repository. This tool hides a PowerShell script inside a PNG file by writing the payload into the least significant 4 bits of the blue and green channel of each pixel. The image looks nearly normal to the eye, but every pixel carries 1 byte of hidden script data, which explains why evil_duck.png is so much larger than a clean image of the same dimensions.
    Learn more

    How LSB-4 pixel encoding works. Each pixel stores 1 byte of payload across two channels: the low 4 bits of blue hold the upper nibble, and the low 4 bits of green hold the lower nibble. Reconstructing the byte:

    r, g, b = pixel
    byte = ((b & 0x0F) << 4) | (g & 0x0F)

    Walking every pixel in order yields a complete PowerShell script embedded invisibly inside the image.

  3. Step 3Decode evil_duck.png and run the extracted script
    Observation
    Invoke-PSImage packs exactly one payload byte per pixel, into bits 0 through 3 of the blue and green channels. A Python PIL loop reconstructs those nibbles and recovers the hidden PowerShell script, which XORs two strings to produce the flag.
    Use the PCsXcetra/Decode_PS_Stego tool (PowershellStegoDecode.exe on Windows) to extract the hidden PowerShell from evil_duck.png. Alternatively, the Python snippet below decodes it manually. The extracted script XORs two hardcoded strings together and writes the result to flag.txt. Running that script produces the flag.
    bash
    # Python manual decode (Linux-friendly):
    python
    python3 -c "
    python
    from PIL import Image
    bash
    im = Image.open('evil_duck.png')
    bash
    w, h = im.size
    bash
    out = []
    bash
    for x in range(h):
    bash
        for y in range(w):
    bash
            r, g, b = im.getpixel((y, x))
    bash
            out.append(chr(((b & 15) << 4) | (g & 15)))
    python
    print(''.join(out))" > extracted.ps1
    bash
    bash
    # Then run the extracted PowerShell (Windows / pwsh):
    bash
    pwsh extracted.ps1
    bash
    cat flag.txt

    Expected output

    picoCTF{n1c3_job_f1nd1ng_th3_s3cr3t_in_the_im@g3}

    The extracted script XORs $string1 against $string2 byte-by-byte and writes the binary result to flag.txt. You can also paste the two strings into CyberChef's XOR operation to decode without PowerShell.

    What didn't work first

    Tried: Running the Python pixel extraction on duck.png instead of evil_duck.png

    duck.png is the clean original with no payload in it, so reading its pixel LSBs gives random-looking garbage rather than a PowerShell script. The target is evil_duck.png, the file whose unexpectedly large size marked it as suspicious.

    Tried: Trying to extract the flag by XORing the strings manually in CyberChef before running the pixel decoder

    The two XOR strings live inside the PowerShell script hidden in evil_duck.png; they are not available separately. Finish the pixel extraction, read both values out of the recovered script, and only then can CyberChef's XOR do anything.

    Learn more

    The embedded PowerShell payload (for reference).

    $out = "flag.txt"
    $enc = [system.Text.Encoding]::UTF8
    $string1 = "HEYWherE(IS_tNE)50uP?^DId_YOu(]E@t*mY_3RD()B2g3l?"
    $string2 = "8,:8+14>Fx0l+$*KjVD>[o*.;+1|*[n&2G^201l&,Mv+_'T_B"
    $data1 = $enc.GetBytes($string1)
    $bytes = $enc.GetBytes($string2)
    for($i=0; $i -lt $bytes.count ; $i++) {
        $bytes[$i] = $bytes[$i] -bxor $data1[$i]
    }
    [System.IO.File]::WriteAllBytes("$out", $bytes)

    XOR-ing those two strings byte-by-byte produces the ASCII bytes of the flag. The XOR key and ciphertext are baked into the image - no external password or key file is needed.

Interactive tools
  • 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.
  • 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{n1c3_job_f1nd1ng_th3_s3cr3t_in_the_im@g3}

The flag is recovered by exporting HTTP objects from the PCAP, then decoding evil_duck.png with the Invoke-PSImage reversal tool (or a Python pixel-reader) to extract a PowerShell XOR script that writes flag.txt.

Key takeaway

Steganography hides arbitrary payloads in images by using the low-significance bits of pixel colour channels, which contribute almost nothing to appearance. This challenge stacks two layers: LSB encoding hides a script inside a PNG, and that script XORs to obscure the final payload. A network capture preserves the whole transfer context, and browsing artifacts in the same file, a visit to a stego tool repository for instance, often name the decoding method before any image analysis begins.

Related reading

Useful tools for Forensics

Where to go next