Avengers Assemble! is a steganography challenge that was part of the 2022 Jade CTF. We had to solve this jigsaw puzzle to get the flag.

## Solution

Find tile size with `gimp`: 60x60 pixels.

Slice the image into tiles with this script:

``````import os
from PIL import Image

def crop(path, input, height, width, k, page, area):
im = Image.open(input)
imgwidth, imgheight = im.size
for i in range(0,imgheight,height):
for j in range(0,imgwidth,width):
box = (j, i, j+width, i+height)
a = im.crop(box)
try:
o = a.crop(area)
o.save(os.path.join(path, "tile-%s.png" % k))
except:
pass
k +=1

crop("puzzle/", "scrambled.png", 60, 60, 0, "tile", (0, 0, 60, 60))
``````
``````\$ mkdir puzzle
\$ python3 cutTo60x60.py
``````

Example tiles:

puzzle/tile-99.png

puzzle/tile-42.png

puzzle/tile-409.png

Use `gimp` to find the red color from the flag string and create a tile with this color and save it as `red.png`.

red.png

Get the color code from the red tile with this script:

``````from PIL import Image
from collections import defaultdict

img = Image.open('red.png')
by_color = defaultdict(int)
for pixel in img.getdata():
by_color[pixel] += 1

print("red.png:", by_color)
``````

Output:

``````\$ python3 redColor.py
red.png: defaultdict(<class 'int'>, {(197, 37, 37): 3600})
``````

Now we can find all tiles with the red color and put them in a new folder:

``````import os
from PIL import Image
from collections import defaultdict
import shutil

for file in os.listdir('puzzle'):
tile = os.path.join('puzzle', file)
img = Image.open(tile)
by_color = defaultdict(int)
for pixel in img.getdata():
by_color[pixel] += 1
if "197, 37, 37" in str(by_color):
shutil.copyfile(tile, ''.join(['flagTiles/',
file.split('/')[-1]]))
``````
``````\$ mkdir flagTiles
\$ python3 getFlagTiles.py
``````

The last step is to put the tiles together to get the flag.

We can do this with a simple word processor like `libreoffice writer`: