Posts TAMU Crypto 18 - LarryCrypt
Post
Cancel

TAMU Crypto 18 - LarryCrypt

Inroduction

TAMU CTF 2018 - LarryCrypt

Description

A binary executable called larrycrypt was provided.

./larrycrypt -R 4 -K “V3c70R” flag

Writeup

We tried some input for the larrycrypt binary and we noticed that it was always using Mu as key, no matter what was the -K parameter. It was likely some bug, but then the SimpleDES challenge we just solved came to our minds.

The binary was using the same key as the other challenge’s example. So we thought it was using the same algorithm, but it wasn’t the case.

Larrycrypt was using 6bit blocks for the ciphertext. The first block of ciphertext was the same as SimpleDES’s first 6bit of cyphertext when using the same key and the same number of rounds. With some more reverse engineering we figured out that larrycrypt was taking the first 12 bits of plaintext, splitting them into L0 and R0, performing the round function and printing only the resulting L1. So they were using the same round function.

But then the sequence changes, we take the R output from the round function and use it as L for the next round along with the next block of ciphertext.

This image shows an example on 3 blocks of data, the output cypertext is made of cypher0, cypher1. L2 won’t be printed

upload-image

To decrypt this we need to bruteforce all the possible 6bit last blocks (L2 in the image), decrypt all the blocks and check if the plaintext is good use the previous des pyhton script and the bruteforce the plain text

Scripts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import simple_des

class SimplerDES(simple_des.SimpleDES):
    def encrypt(self, data):
        if len(data[0]) == 8:
            data = simple_des.to_twelve(data)
        result = []
        for block in data:
            a,b = self.split_block(block)
            result.extend([a,b])
        data = result
        result = []
        self.schedule_key(len(data))
        Lr = data[0]
        for i in range(0,len(data)-1):
            Rr = data[i+1]
            for r in range(self.rounds):
                sk = self.subkeys[i][r]
                Lr, Rr = self.round(sk, Lr, Rr)
            result.append(Lr)
            Lr = Rr
        return result
    
    def decrypt(self, data, last):
        self.invert_key(len(data))
        result = []
        Lr = last
        for i in range(len(data),0,-1):
            i -=1 # hotfix
            Rr = data[i]
            for r in range(self.rounds):
                sk = self.subkeys[i][r]
                Lr, Rr = self.round(sk, Lr, Rr)
            result.append(Lr)
            Lr = Rr
        result.reverse()
        return result


import itertools

#fi = open('flags.txt','w')

ciphertext = ['000101','000000','100111','011001','101110','011101','001110','101111','010001','101111','110000','001001','110010','111011','110111','010001','000100','101011','100010','100010','000001','010100','001111','010010','111110','001110','000111']
key = simple_des.ascii_to_bin("Mu")

f = SimplerDES(key, rounds=4)

for i in itertools.product('01', repeat=6):
    decrypted = f.decrypt(ciphertext, ''.join(i))
    l = ''.join(decrypted)
    #fi.write(l+'\n')
    if simple_des.bin_to_ascii(l[-8:]) == '}':
        l = '010001'+l # fix the starting G  :D
        print(simple_des.bin_to_ascii(l))
    
#fi.close()    
This post is licensed under CC BY 4.0 by the author.