{"id":14197,"date":"2017-07-26T15:31:47","date_gmt":"2017-07-26T13:31:47","guid":{"rendered":"https:\/\/codisec.com\/?p=14197"},"modified":"2023-03-22T16:29:57","modified_gmt":"2023-03-22T15:29:57","slug":"ctfzone-2017-decrypt-undecryptable","status":"publish","type":"post","link":"https:\/\/codisec.com\/ctfzone-2017-decrypt-undecryptable\/","title":{"rendered":"CTFZone 2017: Decrypt the undecryptable"},"content":{"rendered":"
CTF: CTFZone 2017
\nPoints: 724
\nCategory: ppc, reverse<\/p>\n
Oh noes! It looks like we’ve lost decryption keys to our super-secret archive that contains all the blackmail material we’ve accumulated over the years!
\nLuckily, the encryption system was built with the government money by the lowest bidder, so maybe it contains some flaws.<\/p><\/blockquote>\nIn this challenge we were given a TAR archive decrypt_the_undecryptable.tar<\/a>, which contained two files:<\/p>\n
\n
decrypt_utility<\/code> – an 64-bit ELF executable<\/li>\n
flag.encrypted<\/code> – a 1200×800 BMP image<\/li>\n<\/ul>\n
<\/p>\n
flag.encrypted<\/h5>\n
Solution<\/h3>\n
By looking at the encrypted image we can clearly see a repeating pattern, which might indicate that data was XOR’ed with a key of currently unknown length. Hex dump confirmed that theory. Indeed there were repeating 128-byte blocks inside the image data.
\nAs a result of this simple analysis, we came up with very straightforward idea for decryption:<\/p>\n\n
- Split image into 128-byte chunks.<\/li>\n
- Find the most common chunk (it probably represents some solid color of background).<\/li>\n
- XOR all data blocks with discovered key.<\/li>\n<\/ol>\n
from pwn import *\r\nfrom collections import Counter\r\n\r\nn = 128\r\nheader_size = 0x36\r\n\r\ndata = open(\"flag.encrypted\", \"rb\").read()\r\nheader = data[:header_size]\r\ndata = data[header_size:]\r\n\r\nchunks = [data[i:i+n] for i in xrange(0, len(data), n)] # split data into chunks\r\nkey = Counter(chunks).most_common(1)[0][0]\r\n\r\noutput = header\r\noutput += xor(chunks, key)\r\nopen(\"flag.bmp\", \"wb\").write(output)\r\n<\/pre>\n<\/h3>\n
Although the result is not perfect, it’s enough to extract the flag:
ctfzone{5784e25b2af8b3fd817621cdf48e6e675d0e9388}<\/code>.<\/p>\n
Why this method “almost” works<\/h3>\n
First, a quick recap on block ciphers. Blocks ciphers work on fixed-size groups of bits and transform them using a secret key. The same key is used for both encryption and decryption.<\/span><\/p>\n
In our case, AES-256<\/a> is responsible for data encryption and that means block size of 128 bits (16 bytes) and key size of 256 bits (32 bytes). Although presence of decryption utility might give us some hope of extracting the key, it is unfortunately impossible. The only trace of the original encryption key remains as its SHA1<\/a> sum, used to verify whether the key supplied as argument from command line is correct.<\/span><\/p>\n
All of this leads us to the final ingredient and ultimately the flaw, which allowed us to decrypt the data. AES is used in CFB<\/a> mode which uses ciphertext from previous block as input for the next block (look at diagram below for reference), however, it is used in an unusual way. Data is split into 128-byte fragments (8 AES blocks), each of which is encrypted separately i.e. resetting IV to zeros. The XOR “key” that our Python script found is basically an encrypted fragment of zero bytes. Since we know the output of AES with IV as input, we\u2019re able to recover the plaintext. We can repeat this trick if plaintext contains only zero bytes. Unfortunately, when we encounter a block with some non-zero bytes, our decryption method breaks for the next block (different ciphertext used as input for AES). Thus the result contains some artifacts.<\/span><\/p>\n
<\/p>\n
<\/h3>\n
In the diagram, you can see, how blocks are chained in CFB mode. Orange color represents our XOR “key”, grey represents zero byte block, and green some non-zero bytes. We are able to decrypt everything until some unexpected, non-zero byte appears. In that case we XOR this block correctly, because output of AES isn’t changed, but the next block is impossible to decrypt.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"
Decrypt the undecryptable CTF: CTFZone 2017 Points: 724 Category: ppc, reverse Description Oh noes! It looks like we’ve lost decryption keys to our super-secret archive that contains all the blackmail material we’ve accumulated over the years! Luckily, the encryption system…<\/span> <\/p>\n
Read more ›<\/div>\n<\/a><\/p>\n","protected":false},"author":17,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[37],"tags":[34,33,31],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n