Boston Key Party 2015 - Haymarket

Translate the legacy method of programming using punch cards with a custom Python OCR.

Introduction

Haymarket was a reverse engineering challenge at Boston Key Party 2015.

Monty Hall wrote a script of how he was supposed to run one of his game shows for his trusty accounting computer some time ago, but hes not really sure what the punch cards mean any more. I mean, that was a while ago. Only, hes sure his key is hidden somewhere in these punch-cards, if he could figure out how to run them…

Identification

We are given an archive containing 32 pictures with PNG extension.
This pictures are punch cards, it contains either commands for controlling automated machinery or data for data processing applications. Both commands and data are represented by the presence or absence of holes in predefined positions.

This is a deprecated old technology, we probably won't find any decoder for this specific pictures so we have to code our own.

Decoding

After reading some documentations a were able to develop an automatic process to extract the data from the pictures.

#!/usr/bin/env python
import Image

a = 1
b = 2
c = 4
d = 8
e = 16
f = 32
g = 64
h = 128
i = 256
j = 512
k = 1024
l = 2048

lines = (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048)

o = {};
o[0] = " "
o[a] = "&"
o[b] = "-"
o[c] = "0"
o[d] = "1"
o[e] = "2"
o[f] = "3"
o[g] = "4"
o[h] = "5"
o[i] = "6"
o[j] = "7"
o[k] = "8"
o[l] = "9"

o[a + d] = "A"
o[a + e] = "B"
o[a + f] = "C"
o[a + g] = "D"
o[a + h] = "E"
o[a + i] = "F"
o[a + j] = "G"
o[a + k] = "H"
o[a + l] = "I"

o[b + d] = "J"
o[b + e] = "K"
o[b + f] = "L"
o[b + g] = "M"
o[b + h] = "N"
o[b + i] = "O"
o[b + j] = "P"
o[b + k] = "Q"
o[b + l] = "R"

o[c + d] = "/";
o[c + e] = "S";
o[c + f] = "T";
o[c + g] = "U";
o[c + h] = "V";
o[c + i] = "W";
o[c + j] = "X";
o[c + k] = "Y";
o[c + l] = "Z";

o[e + k] = ":"
o[f + k] = "#"
o[g + k] = "@"
o[h + k] = "'"
o[i + k] = "="
o[j + k] = "\""

o[a + e + k] = "[unknown]"
o[a + f + k] = "."
o[a + g + k] = "<"
o[a + h + k] = "("
o[a + i + k] = "+"
o[a + j + k] = "+"

o[b + e + k] = "!"
o[b + f + k] = "$"
o[b + g + k] = "*"
o[b + h + k] = ")"
o[b + i + k] = ";"
o[b + j + k] = "^"

o[c + f + k] = ","
o[c + g + k] = "%"
o[c + h + k] = "_"
o[c + i + k] = ">"
o[c + j + k] = "?"

ORIGIN_X = 15
ORIGIN_Y = 20
RECTANGLE_SIZE_X = 5
RECTANGLE_SIZE_Y = 9
GAP_X = 7
GAP_Y = 20

output = ""

for i in range(1, 33):
    picture = Image.open("L" + str(i) + ".png")
    pix = picture.load()
    for x in range(0, 80):
        pos_x = ORIGIN_X + GAP_X * x
        total = 0
        for y in range(0, 12):
            pos_y = ORIGIN_Y + GAP_Y * y
            is_hole = True
            for x_offset in range(0, RECTANGLE_SIZE_X):
                for y_offset in range(0, RECTANGLE_SIZE_Y):
                    if pix[pos_x + x_offset, pos_y + y_offset] != (20, 20, 20, 255):
                        is_hole = False;
            if is_hole :
                total = total + lines[y]
        output += o[total]

print(output)

Result

We decoded the punch cards with the script above and got a COBOL application.
After a quick review of the code we can notice the instruction DISPLAY 'KEY (SETALEXTREBEKISASOCIALENGINEER)'.