T i s
z k
a
Sep 21 2015

CSAW 2015 Bricks of Gold Problem Statement
We've captured this encrypted file being smuggled into the country. All we know is that they rolled their own custom CBC mode algorithm - its probably terrible. bricks

HINT: take a second look at the file for elements needed for the crypto


Observations


  • The Initialization Vector was placed at the end of the file in plaintext. THE_SECTRET_IV=CASH
  • The first 4 bytes have a similar hamming distance to the IV and the next 8 bytes


Using these observations it is safe to assume that repeating key xor is being used as a block cipher in CBC mode with a block length of 4. [1]

The theoretical encryption algorithm would work by xoring the first 4 bytes of plaintext with the Initialization Vector then with the key. Then xorring the next 4 bytes of plaintext with the previous 4 bytes of ciphertext and then with the key and so on.
Note: Most filetypes begin with a File header. For example PDF files begin with "%PDF" and Elf files begin with "\x7fELF"

Part One

Create a list of every file header and then brute force every possible 4 byte KEY with the IV and check if there are any matches with the lists of file headers
#brute.py

def xor_strings(a, b):
    la, lb = list(a), list(b)
    eb = ""

    for i in xrange(len(la)):
        eb += chr(ord(la[i]) ^ ord(lb[i]))

    return eb

cipher  = "$XMT" #First 4 bytes of ciphertext
IV      = "CASH" #Initialization vector


magic_numbers = ["%PDF", "\x7fELF", "\x00\x00\x01\xBA", "\xca\xfe\xba\xbe", "etc."]
possible_keys = []


for a in xrange(ord("A"), ord("Z") + 1):
    for b in xrange(ord("A"), ord("Z") + 1):
        for c in xrange(ord("A"), ord("Z") + 1):
            for d in xrange(ord("A"), ord("Z") + 1):
                key = chr(a) + chr(b) + chr(c) + chr(d)
                undone = xor_strings(xor_strings(key, IV), cipher)
                if undone in magic_numbers:
                   possible_keys.append((undone, key))

print possible_keys
python brute.py
[('%PDF', 'BIZZ')]

Part Two

Decrypt the file with every possible key

import sys

def xor_strings(a, b):
    la, lb = list(a), list(b)
    eb = ""

    for i in xrange(len(la)):
        eb += chr(ord(la[i]) ^ ord(lb[i]))

    return eb



with open("bricks") as f:
    w = f.read()
    IV  ="CASH"
    key = sys.argv[1]

    #CBC decryption

    prev = w[:4]
    plain = xor_strings(xor_strings(w[:4], key), IV)


    for i in xrange(4, len(w), 4):
        plain += xor_strings(xor_strings(w[i:i+4], key), prev)
        prev = w[i: i+4]

    sys.stdout.write(plain)
python decrypt.py BIZZ > flag.pdf
This resulted in a pdf