# Pybonhash writeupWe are given a [.pyc file](https://github.com/henriknero/writeups/tree/master/pybonhash/pybonhash/pybonhash.cpython-36.pyc), this file can simply be decompiled using uncompyle6 which gives us [this](https://github.com/henriknero/writeups/tree/master/pybonhash/pybonhash/pybonhash.py). We are also supplied with a hash.txt that is 6528(204*32) characters long. 
## pybonhash file```pythonimport string, sys, hashlib, binasciifrom Crypto.Cipher import AESfrom flag import keyassert len(key) == 42data = open(sys.argv[1], 'rb').read()assert len(data) >= 191FIBOFFSET = 4919MAXFIBSIZE = len(key) + len(data) + FIBOFFSET
def fibseq(n):    out = [     0, 1]    for i in range(2, n):        out += [out[(i - 1)] + out[(i - 2)    return out
FIB = fibseq(MAXFIBSIZE)i = 0output = ''while i < len(data):    data1 = data[(FIB[i] % len(data))]    key1 = key[((i + FIB[(FIBOFFSET + i)]) % len(key))]    i += 1    data2 = data[(FIB[i] % len(data))]    key2 = key[((i + FIB[(FIBOFFSET + i)]) % len(key))]    i += 1    tohash = bytes([data1, data2])    toencrypt = hashlib.md5(tohash).hexdigest()    thiskey = bytes([key1, key2]) * 16    cipher = AES.new(thiskey, AES.MODE_ECB)    enc = cipher.encrypt(toencrypt)    output += binascii.hexlify(enc).decode('ascii')
print(output)
```So data i read from a file supplied in arg 1. The data is then hashed using the key supplied in a file flag.py and outputted to stdout. 
So the program iterates through the data and the key for len(data) times. Each iteration generating a 64byte string. Each iteration picks 2 characters from the data-string and 2 characters from the key at the index of a fibonacci number which is chosen by two different equations.
Each 2byte datastring is hashed using md5, and the 2 bytes taken from the key are multiplied to generate a 32byte key for a AES ECB crypto. 
```md5(2 databytes) -> AES_ECB(2 keybytes*16) -> "output_hash"```
So initially we thought we would need to utilize knowledge of the flag format ```midnight{xxxxxxxxxxxxxxxxxxxx}```. But the script hints that each character is ascii encoded which means "only" 128 possible solutions per key and data byte. So there are 128^4 possible inputs for each 64byte output. And we know that because of it being md5hashed we can be relatively certain that each input output 64byte is unique. **TLDR We bruteforced it.**
```pythonoutput = open("pybonhash/hash.txt").read()fuck = [output[i:i+64] for i in range(0, len(output), 64)]
import binascii, hashlibfrom Crypto.Cipher import AESfrom itertools import productfrom string import ascii_letterskeyword_map= {}for x in range(0,128):    for y in range(0,128):        keyword_map[binascii.hexlify(hashlib.md5((chr(x) + chr(y)).encode('utf-8')).digest())] = (chr(x) + chr(y))for x in range(0,128):    print(bytes([x, y]))    for y in range(0,128):        thiskey = bytes([x, y]) * 16        cipher = AES.new(thiskey, AES.MODE_ECB)        for key in keyword_map:            enc = cipher.encrypt(key)            if binascii.hexlify(enc).decode('ascii') in fuck:                print(binascii.hexlify(enc).decode('ascii') + " : " + chr(x) + chr(y))``` So at this moment I just put the output of this script into the [pybonhash script](https://github.com/henriknero/writeups/tree/master/pybonhash/pybonhash/pybonhash_mod.py) and map each output-hash to the key. Then print the key:
```midnight{xwJjPw4Vp0Zl19xIdaNuz6zTeMQ1wlNP}```
