← Back to home

UMass CTF 2024 — Stop the voices

Patrick’s been trying to remember the flag, but his vision seems a little blurry and the voices just don't stop...

We're given 400 samples and a generator script that looks like this:

Code (py):

1from PIL import Image
2import numpy as np
3
4img = Image.open('FLAG.png').convert('L')
5arr = np.asanyarray(img)
6
7
8def normalize(mat):
9    return (mat - mat.min()) / (mat.max() - mat.min()) * 255
10
11
12for i in range(400):
13    noise = np.random.normal(arr, 200)
14    noise = normalize(noise)
15    noise = noise.astype(np.uint8)
16    im = Image.fromarray(noise)
17    im.save(f"./samples/{i}.png")

The script generates 400 files of random noise based on the original flag image, storing them in the samples directory like so:

<p align="center"> <img src="https://gist.github.com/assets/60120929/c6159703-13b4-4cf1-b5fd-2f6c0cd83e5f"> </p>

We can write a script to combine all the samples into a single grayscale image using OpenCV.

Code (py):

1import cv2
2
3cv2.namedWindow('reconstruction', cv2.WINDOW_NORMAL)
4reconstructed = None
5
6for i in range(400):
7    img = cv2.imread(f'./samples/{i}.png', cv2.IMREAD_GRAYSCALE)
8    if reconstructed is None:
9        reconstructed = img / (400 * 255)
10    else:
11        reconstructed += img / (400 * 255)
12
13cv2.imshow('reconstruction', reconstructed)
14cv2.waitKey()
15
16out = cv2.equalizeHist((reconstructed * 255).astype('uint8'))
17cv2.imshow('reconstruction', out)
18cv2.waitKey()
<p align="center"> <img src="https://gist.github.com/assets/60120929/41879338-8a5c-41cb-8e16-77a89263e65d"> </p>

Then, equalizing the histogram using OpenCV, we get the flag.

<p align="center"> <img src="https://gist.github.com/assets/60120929/38a486f2-e626-4f74-8059-e9efcdac027a"> </p>

Code:

1UMASS{#id31n9_L1k3_@_c#Am3_le0n}