Download this file and get the flag. You will also need this wordlist.
The provided files are a python compiled file (keygame.pyc) and a txt file with a list of gibberish words (wordlist.txt). The wordlist didn't seem very interesting, so I proceeded to decompile the python file
$ uncompyle6 keygame.pyc > keygame.py
And had a look at the source code
import base64
from itertools import cycle
class myGame:
def __init__(self, xdim=4, ydim=4):
self.x = xdim
self.y = ydim
self.matrix = []
for i in range(self.x):
row = []
for j in range(self.y):
row.append(0)
self.matrix.append(row)
def make_keys(self, *args, **kwargs):
words = []
with open('wordlist.txt') as (f):
for line in f:
words.append(line.strip())
for i in range(self.x):
for j in range(self.y):
self.matrix[j][i] = words[(i + j)]
keyArray = []
keyArray.append(self.matrix[args[0]][args[1]])
keyArray.append(self.matrix[args[2]][args[3]])
key = ''
for k in keyArray:
key = key.strip() + str(k).strip()
print(key)
return key
def checkdata(self, key):
f = base64.b64decode('NSYDUhoVWQ8SQVcOAAYRFQkORA4FQVMDQQ5fQhUEWUYMDl4MHA==')
data = f.decode('ascii')
c = ''.join((chr(ord(c) ^ ord(k)) for c, k in zip(data, cycle(key))))
print('%s ^ %s = %s' % (data, key, c))
if __name__ == '__main__':
mgame = myGame(25, 25)
x = input('input a number: ')
y = input('input a number: ')
x1 = input('input a number: ')
y1 = input('input a number: ')
data = mgame.make_keys(int(x), int(y), int(x1), int(y1))
mgame.checkdata(data)
My take from it was that the programs takes four inputs and uses them for creating a key based on a matrix and on the wordlist. If the resulting key is the correct one, the checkdata
function is going to print out the flag.
Running the program confirmed my theory
$ python keygame.py
input a number: 1
input a number: 1
input a number: 1
input a number: 1
aa0caa0c
5&RYAW DASA_BYF
^
^ aa0caa0c = TG31{tils gmag!vhotmd c` oo!tei%mono}
Now, how to figure out what are the correct inputs? The sources shows that the game is created with a 25x25 matrix (mgame = myGame(25, 25)
) and since the inputs are used as indexes for the matrix, any input greater than 24 should be invalid.
A quick run of the program confirmed this theory as well
$ python keygame.py
input a number: 25
input a number: 25
input a number: 25
input a number: 25
Traceback (most recent call last):
File "keygame.py", line 56, in <module>
data = mgame.make_keys(int(x), int(y), int(x1), int(y1))
File "keygame.py", line 34, in make_keys
keyArray.append(self.matrix[args[0]][args[1]])
IndexError: list index out of range
So, I needed a way to test all the possible combinations of four inputs ranging from 0 to 24 and it turned out that python has a built-in way for doing just that. Enter itertools.products
import itertools
from keygame import myGame
inputs = [range(0, 25), range(0, 25), range(0, 25), range(0, 25)]
possibilities = [p for p in itertools.product(*inputs)]
mgame = myGame(25, 25)
for p in possibilities:
data = mgame.make_keys(*p)
result = mgame.checkdata(data)
if result.startswith('TG20{'):
print(result, p)
I commented out the print
statements from keygame.py to reduce the noise, and then waited for my script to spit out the flag
'TG20{this flag should be on teh moon}'