Skip to content

Instantly share code, notes, and snippets.

@Lense
Last active September 22, 2015 19:27
Show Gist options
  • Save Lense/fc8bac5b0dc01a963cec to your computer and use it in GitHub Desktop.
Save Lense/fc8bac5b0dc01a963cec to your computer and use it in GitHub Desktop.
CSAW quals 2015 crypto 200: punchout

From irc I found out that the data was encoded in ebcdic instead of ascii (str.encode("cp1140") in Python3).

I just kind of assumed it would be an xor stream reused on all 3 files, and made a quick test to find the string flag{ in 3:

  • For each offset i in 3:
    • xor flag{ with the data in 3 at offset i to get the (potential) key at that offset
    • xor that value with the data at 2 and 1 at the same offset
    • If that data looks like text, return i

This became findOffset() in solve.py, and confirmed: the encoding was an xor stream, both files 1 and 2 were text, and the flag was in file 3.

Then I tried testing all possible next characters in the flag after the open curly brace, and kept the ones that made the decryption of 1 and 2 look the best. The hardest part of this challenge, by far, was figuring out that 1 decrypted to some weird characters (\n3·A·) in the middle. (by this time my team had already solved the challenge using cribbing, whatever that means)

The flag ended up being: flag{https://i.imgur.com/ZNem5o3.gifv}

We found these System/360 punch cards and we need to extract the data. We already read the data off for you.

It looks encrypted. Can you help?

HINT: This is actually encrypted. With technology and techniques that were available in 1965

HINT: https://gist.github.com/withzombies/40554f02d6c7055fb0bc punchout.tar.xz-24504ddc1e81092010497ee49fc52e1c

#!/usr/bin/env python3
import string
import struct
import sys
import time
def xor(data, key):
out = []
for i in range(0,min(len(data), len(key))):
out.append(data[i] ^ (key[i] if type(key[0] == int) else ord(key[i])))
return bytes(out)
def goodChar(c):
if c in string.printable:
return True
# Cheating here
if ord(c) in (183, 194):
return True
return False
def findOffset():
encFlag = ("flag{".encode("cp1140"))
for i in range(len(f3)):
ikey = xor(f3[i:], encFlag)
d1 = xor(f1[i:], ikey).decode("cp1140")
d2 = xor(f2[i:], ikey).decode("cp1140")
if all(map(goodChar, d1)) and all(map(goodChar, d2)):
print(str(i) + ":", d1, d2)
"""
Output:
257: c$fgH l$a;I
340: s6to{ ~6MpF
576: dn@gP wl$gS
741: m, an Rober
so the most likely offset is 741
"""
def decode():
flag = "flag{"
while flag[-1] != "}":
for c1 in range(256):
if not goodChar(chr(c1)):
continue
for c2 in range(256):
if not goodChar(chr(c2)):
continue
encFlag = (flag + chr(c1) + chr(c2)).encode("cp1140")
ikey = xor(f3[i:], encFlag)
d1 = xor(f1[i:], ikey).decode("cp1140")
d2 = xor(f2[i:], ikey).decode("cp1140")
if all(map(goodChar, d1)) and all(map(goodChar, d2)):
print(repr(chr(c1) + "," + chr(c2)) + ":", repr(d1), repr(d2))
print("flag: " + flag)
flag += input("Enter next character:")
print("-" * 80)
return flag
with open("1", 'br') as a, open("2", "br") as b, open("3", "br") as c:
f1, f2, f3 = a.read(), b.read(), c.read()
findOffset()
i = input("Enter offset i:")
# Cheating here
if i != "741":
print("Wrong")
exit(1)
i = int(i)
print(decode())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment