Meow Transmission - Forensics
Points: 500 | Flag: BITSCTF{arn0ld5_c4t_m4ps_4r3_p3r10d1c} | Solved by: Smothy @ 0xN1umb

what we got
a single transmission.png - 128x128 grayscale PNG. description says "cat photo" with "strange ramblings about cats and dancing" in the metadata. lol ok
the solve
step 1 - metadata is everything
first thing, exiftool the image:
$ exiftool transmission.png
Comment: Meow! I'm a cat who loves to transform.
My journey involves 3 leaps through chaos.
At each leap, I choose my style: [1, 2, 1]
I spin [47, 37, 29] times at each stop.
Each dance has its own rhythm: [96, 64, 96] spins to complete.
The sequence of my adventure: [1, 2, 3]
My world is 128x128 pixels wide.
Perhaps a certain Russian mathematician knows my secret?
Author: Mr. Arnold Cat
ngl this was basically a full instruction manual. "Mr. Arnold Cat" + "Russian mathematician" = Arnold's Cat Map. Vladimir Arnold's classic chaotic image transformation. the metadata literally spells out every parameter lmao
step 2 - understanding the arnold cat map
the Arnold Cat Map is a pixel shuffling transform:
x' = (x + p*y) mod N
y' = (q*x + (p*q+1)*y) mod N
the key property? it's periodic - apply it enough times and the image returns to its original state. so if the period is T and you applied it n times, just apply it (T - n) more times to get the original back.
from the metadata we get:
| Step | Style (p) | q | Iterations | Period |
|---|---|---|---|---|
| 1 | p=1 | 1 | 47 | 96 |
| 2 | p=2 | 1 | 37 | 64 |
| 3 | p=1 | 1 | 29 | 96 |
applied in sequence [1, 2, 3]
step 3 - reverse it
to undo, reverse the order and use (period - iterations) forward applications:
- undo step 3: p=1, q=1, forward 67 times (96-29)
- undo step 2: p=2, q=1, forward 27 times (64-37)
- undo step 1: p=1, q=1, forward 49 times (96-47)
import numpy as np
from PIL import Image
img = np.array(Image.open("transmission.png"))
N = 128
def arnold_cat_map(image, p, q, iterations):
result = image.copy()
for _ in range(iterations):
temp = np.zeros_like(result)
for x in range(N):
for y in range(N):
new_x = (x + p * y) % N
new_y = (q * x + (p * q + 1) * y) % N
temp[new_x, new_y] = result[x, y]
result = temp
return result
# reverse order: undo step 3, then 2, then 1
result = arnold_cat_map(img, 1, 1, 96 - 29) # undo step 3
result = arnold_cat_map(result, 2, 1, 64 - 37) # undo step 2
result = arnold_cat_map(result, 1, 1, 96 - 47) # undo step 1
Image.fromarray(result).save("decoded.png")step 4 - LSB stego
the decoded image still looks like noise to the eye. but checking the bit planes:
Bit plane 0: 341 ones (2.1%)
Bit plane 1: 341 ones (2.1%)
Bit plane 2: 341 ones (2.1%)
lower 3 bits all have exactly 341 ones in the same positions. super structured. extracted the LSB as a binary image and scaled it up:
mask = (img & 1).astype(np.uint8)
binary_img = mask * 255
# scale up for readability
scaled = np.kron(binary_img[45:80, 3:86], np.ones((8, 8), dtype=np.uint8))
Image.fromarray(scaled).save("text_zoomed.png")and there it is - flag rendered in pixel font:
BITSCTF{arn0ld5_
c4t_m4ps_4r3_p3r
10d1c}
tldr
- exiftool reveals Arnold Cat Map parameters
- reverse the 3-stage cat map using periodicity
- extract LSB from decoded image
- pixel font flag in the lower bits
fr the challenge author was lowkey generous putting every single parameter in the metadata. the real trick was recognizing "Arnold Cat Map" from the hints and knowing about its periodic property.
flag
BITSCTF{arn0ld5_c4t_m4ps_4r3_p3r10d1c}
smothy out ✌️