MSB picoCTF 2023 Solution

Published: April 26, 2023

Description

Most-significant-bit steganography hides data in the high bit of each pixel channel. Use a Python MSB steganography script or Stegsolve to extract the hidden text, then grep for the flag.

Install Stegsolve (or an equivalent tool) and open the provided PNG.

Use Analyse → Data Extract, set bit order to MSB First, and enable Red 7, Green 7, Blue 7. Scroll to the top of the extracted text.

bash
wget https://artifacts.picoctf.net/c/294/Ninja-and-Prince-Genji-Ukiyoe-Utagawa-Kunisada.flag.png
bash
# Option 1: Python MSB extraction script
bash
pip3 install Pillow
bash
# Option 2: Stegsolve
bash
wget http://www.caesum.com/handbook/Stegsolve.jar -O stegsolve.jar
bash
java -jar stegsolve.jar
Stegsolve's bit-plane extraction is explained step-by-step in the Introduction to Steganography Tools post - including the exact settings to use for MSB vs LSB extraction.
  1. Step 1Extract MSB data
    Use a Python MSB steganography script to extract bit 7 from each pixel channel. The extracted bytes concatenated form the hidden text. Alternatively, use Stegsolve: toggle Red 7, Green 7, Blue 7 in the data extractor and save the output.
    python
    python3 - <<'PY'
    from PIL import Image
    
    img = Image.open("Ninja-and-Prince-Genji-Ukiyoe-Utagawa-Kunisada.flag.png")
    pixels = list(img.getdata())
    
    bits = []
    for pixel in pixels:
        for channel in pixel[:3]:  # R, G, B
            bits.append((channel >> 7) & 1)  # MSB
    
    # Group bits into bytes
    out = bytearray()
    for i in range(0, len(bits) - 7, 8):
        byte = 0
        for b in bits[i:i+8]:
            byte = (byte << 1) | b
        out.append(byte)
    
    with open("msb_output.bin", "wb") as f:
        f.write(out)
    print("Written msb_output.bin")
    PY
    bash
    strings msb_output.bin | grep pico
    Learn more

    In digital images each pixel's color is encoded as a set of channel values (Red, Green, Blue) typically stored as 8-bit integers (0 to 255). Each byte has 8 bit planes: bit 0 is the least significant bit (LSB) and bit 7 is the most significant bit (MSB). Changing bit 7 shifts a channel value by 128, a very visible change. Changing bit 0 shifts it by 1, imperceptible to the human eye.

    Classic LSB steganography hides data in bit 0, where changes are invisible. This challenge uses MSB steganography(bit 7) instead. Because the image was specifically chosen to have "natural" high-bit patterns (or was specifically crafted), the flag hidden in the MSB is not visually obvious. Stegsolve's data extractor reads the selected bit from every pixel in row-major order and concatenates them into a byte stream, which surfaces the hidden ASCII text.

    Stegsolve is a Java tool that provides bit-plane viewers, color filters, and frame analyzers. It is invaluable for CTF image steganography because it visualizes every bit plane at a glance: a pattern of text in an otherwise noisy bit plane is a dead giveaway that data is hidden there. The full bit-plane workflow is covered in the CTF steganography and steganography tools guides.

  2. Step 2Search the dump
    Stegsolve's data extractor saves the raw bytes (the default save dialog dumps to a file you choose; many people just save it as text in the same directory). Run strings on the saved file and grep for pico. Remove stray spaces from the recovered flag if MSB alignment introduced any.
    bash
    strings text | grep pico
    Learn more

    After extraction, the raw byte stream may contain the flag interleaved with garbage bytes, or the flag may be contiguous. strings filters for sequences of printable ASCII characters of a minimum length (default 4), which naturally isolates human-readable content like picoCTF{...} from surrounding binary data.

    The grep pico pipe then narrows the output to only lines containing the flag prefix. This two-step pipeline - strings | grep pattern - is a general-purpose technique applicable to any binary file: ELF binaries, firmware dumps, memory captures, or steg output. It is often the fastest first step in any binary analysis task.

    About those spaces: MSB extraction reads one bit per channel per pixel, then groups the resulting bit stream into 8-bit bytes. If the hidden message is shorter than the image (or padded with zero-bytes), runs of zero bits decode to NULs (0x00) which print as nothing, and runs of 0x20 bytes decode as ASCII space. Strip extra whitespace before submitting.

Flag

picoCTF{15_y0ur_que57...d55bee}

Only the MSB bits carry useful data, so LSB analysis will pass but yield nothing.

Want more picoCTF 2023 writeups?

Useful tools for Forensics

Related reading

What to try next