A more challenging steganography challenge using least-significant-bit encoding.
We are given a large PNG of some smarties (cropped):
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 image gives us the flag:
pactf{JVQW4Y3IMVZXIZLS}