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.

scrambled.png

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.pngpuzzle/tile-99.png

puzzle/tile-42.pngpuzzle/tile-42.png

puzzle/tile-409.pngpuzzle/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.pngred.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
flagTiles/tile-109.png flagTiles/tile-14.png flagTiles/tile-24.png flagTiles/tile-344.png flagTiles/tile-418.png flagTiles/tile-452.png flagTiles/tile-532.png flagTiles/tile-5.png
flagTiles/tile-111.png flagTiles/tile-1.png flagTiles/tile-265.png flagTiles/tile-345.png flagTiles/tile-42.png flagTiles/tile-473.png flagTiles/tile-541.png flagTiles/tile-61.png
flagTiles/tile-124.png flagTiles/tile-213.png flagTiles/tile-270.png flagTiles/tile-357.png flagTiles/tile-435.png flagTiles/tile-484.png flagTiles/tile-561.png flagTiles/tile-88.png
flagTiles/tile-128.png flagTiles/tile-236.png flagTiles/tile-277.png flagTiles/tile-361.png flagTiles/tile-447.png flagTiles/tile-516.png flagTiles/tile-580.png
flagTiles/tile-141.png flagTiles/tile-248.png flagTiles/tile-291.png flagTiles/tile-405.png flagTiles/tile-44.png flagTiles/tile-521.png flagTiles/tile-598.png

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:

flag.png

Flag

The flag is “jadeCTF{scr4mbl3d_w3_f4ll_un1t3d_w3_st4nd}”.