Sebastian's Blog

software developer. security enthusiast.

HACKVent 2019

HV19.09 Santas Quick Response 3.0

Sebastian

So the qr code looks broken. Doing a reverse image search on the first image reveals that the image was taken at Cambridge North railway station. The cladding of the building features a pierced design derived from Rule 30. So I thought maybe generate a Rule 30 image, put it over the qr code and do some xoring. First I shrunk the QR code image to 33×33 pixels. As the hints state, that centering is hard, I wrote the following python script which generates a Rule 30 set with the same size as the qr code, shifts it left respectively right, does the xoring, and stores the resulting image in a subfolder.

import sys

MAX_TIME = 33
HALF_SIZE = MAX_TIME
indices = range(-HALF_SIZE, HALF_SIZE+1)

# initial condition
cells = {i: '0' for i in indices}
cells[0] = '1'
# padding on both ends
cells[-HALF_SIZE-1] = '0'
cells[ HALF_SIZE+1] = '0'

new_state = {"111": '0', "110": '0', "101": '0', "000": '0',
             "100": '1', "011": '1', "010": '1', "001": '1'}
from PIL import Image

xm = Image.open('hv33.png')
rules = [[0 for _ in range(33)] for i in range(67)]
for time in range(0, MAX_TIME):
    x = 0
    for i in cells:
        if x < 65:
            rules[x][time] = (int(cells[i]))
        x += 1

    # evolve
    patterns = {i: cells[i-1] + cells[i] + cells[i+1] for i in
                indices}
    cells = {i: new_state[patterns[i]] for i in indices}
    cells[-HALF_SIZE-1] = '0'
    cells[ HALF_SIZE+1] = '0'
    

for x in range(1, 2 * 66):
    im = Image.new('RGB', (33, 33))
    pixels = im.load()
    for i in range(33):
        for j in range(33):
            if xm.getpixel((i, j)) == 0:
                val = 1
            else:
                val = 0         
            if i - 66 + x > 0 and i - 66 + x < len(rules):
                val = val ^ int(rules[i - 66 + x][j])
            if val == 1:
                pixels[i,j] = (0, 0, 0)
            else:
                pixels[i,j] = (255, 255, 255)

    im.save('img/' + str(x) + '.png', 'PNG')

One of the images turns out to be a valid qr code which reveals the flag: HV19{Cha0tic_yet-0rdered}.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top