Sudda, sudda, sudda

Kategori

Forensik

Beskrivning

Ta lite pengar och köp ett bättre maskeringsverktyg.

Flaggan (exklusive cratectf{}) är 19 tecken lång och den dolda delen består endast av siffror samt mellanslag. (Och det går inte att handla något med kortet)

Lösning

Bifogat är en bild innehållande flaggan, men den är gjord suddig så man inte kan läsa den.

Suddig flagga

Grundbilden på kortet, fonten som används samt scriptet som använts för att generera flaggan finns också bifogat.

Genom att använda sig av den medföljande koden för genereringen så kan man brute-force:a vilka tecken det är som är gömda genom att testa två tecken och jämföra hur de ser ut med den biten av flagg-kortet.

Följande är ett script för att återskapa flaggan genom att testa olika kombinationer och sedan jämföra med flagg-kortet.

#!/usr/bin/env python3

from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageChops

FONT_FILE = "LiberationMono-Regular.ttf"
FLAG_POSITION = (90, 280)

blurred_img = Image.open("card.png")

font = ImageFont.truetype(FONT_FILE, size=50)
small_font = ImageFont.truetype(FONT_FILE, size=14)

flag_prefix = 'cratectf{'
flag_suffix = '}'
cw = 30
ch = 42

found = ''

for part in range(8):
    for i in range(100):
        test_part = str(i).zfill(2)
        test = found + test_part + '11' * (7 - part)
        test = test[:4] + ' ' + test[4:8] + ' ' + test[8:12] + ' ' + test[12:]

        img = Image.open("card_blank.png")
        draw = ImageDraw.Draw(img)

        draw.text((5, FLAG_POSITION[1] + 18),
                  flag_prefix, font=small_font, fill=("white"))
        width, height = draw.textsize(test, font=font)
        draw.text((FLAG_POSITION[0] + width + 10, FLAG_POSITION[1] + 18),
                  flag_suffix, font=small_font, fill="white")

        # Print flag onto base image
        draw.text(FLAG_POSITION, test, font=font, fill="white")

        flag_coords = (FLAG_POSITION[0], FLAG_POSITION[1],
                       FLAG_POSITION[0] + width, FLAG_POSITION[1] + height)
        flag_part = blurred_img.crop(flag_coords)
        blur_part = img.crop(flag_coords)
        blur_part = blur_part.filter(ImageFilter.BoxBlur(radius=20))
        add = 0
        if part > 1:
            add += cw
        if part > 3:
            add += cw
        if part > 5:
            add += cw
        x = cw * (part * 2) + add
        char_coords = (x, 0, x+cw, ch)
        blur_part = blur_part.crop(char_coords)

        ch_part = flag_part.crop(char_coords)
        diff = ImageChops.difference(ch_part, blur_part)

        if not diff.getbbox():
            found += test_part
            break

flag = flag_prefix + found[:4] + ' ' + found[4:8] + ' ' + found[8:12] + ' ' + found[12:] + flag_suffix
print(flag)

När man kört scriptet så får man flaggan cratectf{1337 4894 1197 4115}

n00bz

Home of the n00bz CTF team.


By n00bz, 2022-11-28