A more challenging steganography challenge using least-significant-bit encoding.

We are given a large PNG of some smarties (cropped): The PNG

Usual steganographic methods don't seem to return anything significant, but the large filesize of the image indicates that maybe there is something encoded in the least significant bit of each pixel in the image.

We can use Python and the PIL library to extract the least significant bit of each pixel and then convert each 7 bits in the binary string to ASCII We also need to note colours of the smarties in the image as it determines which channel (R, G or B) we need to read the LSB value from - The order in the picture is green, red, green, blue, blue, red, green, blue and using itertools we can create a cycle to cycle through this sequence and pick out the correct channel.

import sys
from PIL import Image
from itertools import cycle

image = Image.open("smarties.png")

message = []

order = cycle("GRGBBRGB")

for rgb in list(image.getdata()):
    channel = next(order)
    if channel == "R":
    	message.append(rgb[0] & 1)
    if channel == "G":
    	message.append(rgb[1] & 1)
    if channel == "B":
    	message.append(rgb[2] & 1)

for i in range(0, len(message), 7):
    sys.stdout.write(chr(int("".join([str(x) for x in message[i:i+7]]), 2)))
sys.stdout.flush()

Piping this to an output file with:

python lsb_steg.py > output.txt

Gives us a large output file of what appears to be hexadecimal - The first two bytes are 89 50 4E 47 0D 0A 1A 0A which indicate that it is a PNG file. Converting the output to a PNG file gives us the hidden image: The hidden image

The image gives us the flag:

pactf{JVQW4Y3IMVZXIZLS}