---
# System prepended metadata

title: IRON CTF 2024 - Random Pixels

---

# IRON CTF 2024 - Random Pixels
**Title:** Random Pixels

**Description:** My Image accidently fell into a pixel mixer can you help me recover it?

**Files:** 
- `enc.py`:
```python
import random, time, numpy
from PIL import Image
from secret import FLAG

def randomize(img, seed):
	random.seed(seed)
	new_y = list(range(img.shape[0]))
	new_x = list(range(img.shape[1]))
	random.shuffle(new_y)
	random.shuffle(new_x)

	new = numpy.empty_like(img)
	for i, y in enumerate(new_y):
		for j, x in enumerate(new_x):
			new[i][j] = img[y][x]
	return numpy.array(new)


if __name__ == "__main__":
	with Image.open(FLAG) as f:
		img = numpy.array(f)
		out = randomize(img, int(time.time()))
		image = Image.fromarray(out)
		image.save("encrypted.png")
```
- `encrypted.png`:
![encrypted](https://hackmd.io/_uploads/rklo7Vekkg.png)

## Solution:
The challenge begins with an encrypted PNG image. Suspecting that the image was randomized based on pixel positions, we analyzed the encryption process.

I inspected the encryption script(`enc.py`) and found this:
```python
def randomize(img, seed):
    random.seed(seed)
    new_y = list(range(img.shape[0]))
    new_x = list(range(img.shape[1]))
    random.shuffle(new_y)
    random.shuffle(new_x)

    new = numpy.empty_like(img)
    for i, y in enumerate(new_y):
        for j, x in enumerate(new_x):
            new[i][j] = img[y][x]
    return numpy.array(new)
```

The encryption process involves using a random number generator to shuffle the `x` and `y` coordinates of the image. 
I discovered that the Unix timestamp at the time of encryption was the key factor in shuffling. Luckily, I was able to find out the file's modification date through the image's metadata:
```bash
$ exiftool encrypted.png
ExifTool Version Number         : 12.40
File Name                       : encrypted.png
Directory                       : .
File Size                       : 22 KiB
File Modification Date/Time     : 2024:10:03 00:02:40+03:00
File Access Date/Time           : 2024:10:06 18:25:20+03:00
File Inode Change Date/Time     : 2024:10:05 21:40:40+03:00
File Permissions                : -rwxrwxrwx
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 300
Image Height                    : 300
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Image Size                      : 300x300
Megapixels                      : 0.090
```

```bash
File Modification Date/Time     : 2024:10:03 00:02:40+03:00
```

I used this timestamp as the seed to reverse the shuffle. By using the seed, I can reverse the shuffling process and reconstruct the image by:
- Generating the same shuffled indices for `x` and `y` axes.
- Creating inverse mappings of these indices.
- Rearranging the pixels back to their original positions using the inverse mappings.
Here's the script I used for this:
```python
import random
import numpy as np
from PIL import Image
import os

def get_seed_from_mtime(file_path):

    mtime = os.path.getmtime(file_path)
    unix_timestamp = int(mtime)
    return unix_timestamp

def reverse_randomize(encrypted_img, seed):
    random.seed(seed)
    height, width = encrypted_img.shape[:2]

    new_y = list(range(height))
    new_x = list(range(width))
    random.shuffle(new_y)
    random.shuffle(new_x)

    inverse_y = [0] * height
    inverse_x = [0] * width
    for i, y in enumerate(new_y):
        inverse_y[y] = i
    for j, x in enumerate(new_x):
        inverse_x[x] = j

    decrypted_img = np.empty_like(encrypted_img)

    for i in range(height):
        for j in range(width):
            decrypted_img[i][j] = encrypted_img[inverse_y[i]][inverse_x[j]]

    return decrypted_img

encrypted_image_path = 'encrypted.png'
decrypted_image_path = 'decrypted.png'

seed = get_seed_from_mtime(encrypted_image_path)

with Image.open(encrypted_image_path) as img:
    img = img.convert('RGB')
    encrypted_array = np.array(img)

decrypted_array = reverse_randomize(encrypted_array, seed)

decrypted_image = Image.fromarray(decrypted_array)
decrypted_image.save(decrypted_image_path)

print(f"Decrypted image saved as {decrypted_image_path}")
```

```bash
$ python3 decrypt.py
Decrypted image saved as decrypted.png
```
![decrypted](https://hackmd.io/_uploads/rJNh7Vg11g.png)


Once the image was decrypted, we noticed that it contained a QR code, likely hiding the flag.
To extract the flag from the QR code, I used a tool called `zbarimg` which is used for scanning barcodes and QR codes from images.
```bash
$ zbarimg decrypted.png
QR-Code:ironCTF{p53ud0_r4nd0m_f0r_4_r3450n}
scanned 1 barcode symbols from 1 images in 0.15 seconds
```

And there's our flag: `ironCTF{p53ud0_r4nd0m_f0r_4_r3450n}`