Write-up: Meow Meow Meow Meow

Now this one’s a bit tricky and might require some prior knowledge and intuition (or lots of googling).

By keeping only the capital letter’s in the challenge’s description, we get “LSB”, an obvious hint as for the steganographic technique used.

Time for some background!

What in the tarnation is LSB?

You’re probably familiar with the fact that images are composed of pixels.
You probably also know that each of the pixels is a tuple of three values: (Red, Green, Blue)

Furthermore, each of the values of each tuple of each pixel is a value in-between 0 and 255.
Why 255? Because it’s the values that can fit in 8 bits!
So, if we look at it in binary, each pixel is a tuple of three 8 bit values.

Now’s the fun part:
We can hide binary data by picking one bit and writing linearly the data in that bit of each pixels (each column for each row in order).

Obviously, changing the “Most Significant Bit” (aka the MSB, the bit equal to 2^7) will result in great changes in the image that will be easily noticeable by the human eye. Some drastic changes can even render part or the entirety of the image seemingly “corrupted”.

So, we instead use the “Least Significant Bit” (aka LSB, the one equal to 2^0). Such a change will be so minimal that it will be invisible to the naked human eye.

In conclusion: A basic execution of an LSB algorithm

# Encoding:
- Let data be a string in binary encoding our data
 - For each row
	 - For each column
		 - Take the red, green, blue values of current pixel
		 - Convert those values to binary
		 - Change the LSB of red to the ith bit of our data
		 - Change the LSB of green to the i+1th bit of our data
		 - Change the LSB of blue to the i+2th bit of our data
	
	
# Decoding:
- For each row
	- For each column
		- Take the red, green, blue values of current pixel
		- Convert those values to binary
		- Append the last bit of binary_red
		- Append the last bit of binary_green
		- Append the last bit of binary_red

So now what? More analysing :D

Obviously, if you tried implementing that algorithm, you would get junk data. Fun is not allowed around me!!

So we go back to analysing the file a bit more :D

We try to print every triplet of LSB:

from PIL import Image

img = Image.open("cat.png")
data = img.load()
q = "".join([" ".join(["("+str(bin(data[i,j][0]))[-1]+" "+str(bin(data[i,j][1]))[-1]+" "+str(bin(data[i,j][2]))[-1]+")" for j in range(img.height)]) for i in range(img.width)])[:500]
$ python3 lsb.py 
(0 0 1) (0 0 0) (1 0 1) (0 0 0) (0 0 0) (0 0 0) (0 1 1) (0 0 0) 
(1 0 0) (0 0 0) (0 0 0) (0 0 0) (1 1 1) (0 0 0) (0 1 0) (0 0 0) 
(0 1 0) (0 0 0) (1 0 0) (0 0 0) (1 1 0) (0 0 0) (1 0 1) (0 0 0) 
(0 1 1) (0 0 0) (1 0 0) (0 0 0) (1 1 0) (0 0 0) (1 0 1) (0 0 0) 
(0 0 1) (0 0 0) (1 0 0) (0 0 0) (0 0 0) (0 0 0) (1 0 1) (0 0 0) 
(1 0 0) (0 0 0) (1 0 1) (0 0 0) (0 1 0) (0 0 0) (1 1 1) (0 0 0) 
(0 1 1) (0 0 0) (1 0 1) (0 0 0) (0 0 0) (0 0 0) (1 1 0) (0 0 0) 
(1 1 0) (0 0 0) (0 0 1) (0 0 0) (0 0 1) (0 0 0) (1 0

That’s weird… every other triplet is (0,0,0) ??
We can simply realise from there:

So we edit our script accordingly:

from PIL import Image

img = Image.open("cat.png")
data = img.load()
print("".join(["".join([str(bin(data[i,j][0]))[-1]+str(bin(data[i,j][1]))[-1]+str(bin(data[i,j][2]))[-1] for j in range(0,img.height,2)]) for i in range(img.width)])[:500])
$ python3 lsb.py 
0011010000111000001110100101001101010111001101010011000001011001010101110111010
0011011000100110101101010010100100011011101010100010000110101001001101001010110
0000110000010001010111100001100010011011000101001001100110010101100100011101100
1110111101001100100010001100011100101001001010011010110111001001010010001010100
1001010101100011100001111000011000100110101100110101011100000101011001000011010
0111000111001111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111

We can then use a cool online tool for decryption (keep this one noted somewhere, it’s really useful): kt.gy

After decryption of the binary bit (cut after 500 characters for simplicity of use):

48:SW50YWtlMjR7TCRiX0ExblRfVGgzdF9IMnJEIV8xbk5pVCN9ÿÿÿÿÿÿÿÿÿÿÿ

The 48:... bit looks suspicious, as if someone was trying to give us a hint!
So, we copy the first 48 characters after the 48:, and decode in b64:

SW50YWtlMjR7TCRiX0ExblRfVGgzdF9IMnJEIV8xbk5pVCN9 -> Intake24{L$b_A1nT_Th3t_H2rD!_1nNiT#}

Flagged :D