Hackvent 2024: Day 18

Hackvent 202430

[HV24.18] Santa's Stego

Santa has written his own super secret stego algorithm back in the old days, after learning about base 2. It could even do RGB stuff to make the images not look off. Sadly he forgot how it worked, can you help him out?

Analyze the image and get the flag.
Flag format: HV24{}
sha256sum of the image: 3f297b44688a97af4c1f656f9de87c30c55e9f42ec4f31033a4cd5d39ced04c6

This challenge was written by coderion. He had lots of "fun" solving Hackvent stego challenges, so why not write his own?

Image file:

Hackvent 2024 - Day 18 - image.png

Solution

Based on the challenge description of Santa learning about base 2 and performing 'RGB stuff' to make images appear correct, we suspect there is hidden data in the LSB of each RGB channel. The size of the image (45x45 pixels) also suggests that it is a 45x45 QR code. This means we need to extract just 1 bit from each RGB channel. This is typically done by considering just one channel or performing an operation, such as XOR, on multiple channels.

We use an online tool, in this case Aperisolve, to help us visualise the bits in the image. Tools like this can display only one of the eight bits in each RGB channel to help us find hidden data.

Hackvent 2024 - Day 18 - Aperisolve Channels

We notice that, for each RGB channel, one visualization stands out from the rest. They contains predominantly dark pixels. By manually inspecting the first few bits of the first row of the channels, we see that XORing the bits results in a series of 1's followed by a 0, which matches the position marker of a 45x45 QR code.

Therefore, we write a script that processes each pixel and takes the LSB of the red channel, the 2nd LSB of the green channel and the 3rd LSB of the blue channel and outputs a 45x45 QR code:

# Hackvent 2024 - Day 18
# Mo Beigi
#
# Extract signifiant LSB's from RGB channels to create QR code.

from PIL import Image

img = Image.open("image.png")
img = img.convert("RGB")
width, height = img.size

result_bits = []

# Loop over each pixel to extract LSBs and perform XOR
for y in range(height):
    for x in range(width):
        r, g, b = img.getpixel((x, y))
        
        # Extract LSB and XOR the Red, Green, and Blue channels in one step
        xor_result = (r & 1) ^ ((g >> 1) & 1) ^ ((b >> 2) & 1)
        result_bits.append(str(xor_result))

# Create QR code image
image_size = 45
result_binary_string = ''.join(result_bits)[:image_size * image_size]
qr_code_image = Image.new("1", (image_size, image_size))
pixels = [1 if bit == '1' else 0 for bit in result_binary_string]
qr_code_image.putdata(pixels)
qr_code_image.save("qr_code.png")

This results in the following qr_code.png file:

Hackvent 2024- Day 18 - QR code

This QR code scans to give us our daily flag!

Flag:

HV24{v3ry_fun_l0l_s0rry_f0r_th3_p41n_n3v3r_g0nna_g1v3_y0u_up}

Leave a comment

(required)(will not be published)(required)

Comments

There are no comments yet. Be the first to add one!