Tuesday, January 1, 2013

Hack You Too CTF - Crypto 300 - Everybody Lies

Description:
Mr. Menhall has invented his own encryption algorithm and promised to give the flag to anyone who manages to decipher the message: vWsMajX21l6BdKwDxaRA3utqhpvFL0V=


For this challenge, source code of the encryption algorithm is given
def hashcrypt(msg, key):
    token = hashlib.sha1(key).digest()
    res = ""
    for c in msg:
        n = ord(c) ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
        n ^= 0xc2 ^ ord(token[0])
        n ^= 0xf3 ^ ord(token[1])
        n ^= 0x27 ^ ord(token[2])
        n ^= 0x4c ^ ord(token[3])
        n ^= 0x21 ^ ord(token[4])
        n ^= 0xfe ^ ord(token[5])
        n ^= 0xa3 ^ ord(token[6])
        n ^= 0xf0 ^ ord(token[7])
        n ^= 0x11 ^ ord(token[6])
        n ^= 0x54 ^ ord(token[5])
        n ^= 0xca ^ ord(token[4])
        n ^= 0x3c ^ ord(token[3])
        n ^= 0x20 ^ ord(token[2])
        n ^= 0xd1 ^ ord(token[1])
        n ^= 0xf2 ^ ord(token[0])
        res += chr(n)
        token = hashlib.sha1(chr(n)).digest()
    return res.encode('base64').encode('rot13')
We have to reverse the algorithm to find the plain text. The algorithm uses nth cipher text byte to compute token for the (n+1)th cipher text byte. Using this we can find all plain text except the 1st byte. Below is the code to do that
#!/usr/bin/env python
# decrypt.py

import hashlib

def hashdecrypt(msg):
    res = msg.decode('rot13').decode('base64')
    res = [ ord(i) for i in res]
    for i in range(len(res)):
        if i == 22:
            print ''.join([chr(i) for i in res]) # i_lied_no_flag_for_you!
            break

        n = res[-i-2]
        token = hashlib.sha1(chr(n)).digest()
        for c in xrange(32, 127):
            n  = c ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
            n ^= 0xc2 ^ ord(token[0])
            n ^= 0xf3 ^ ord(token[1])
            n ^= 0x27 ^ ord(token[2])
            n ^= 0x4c ^ ord(token[3])
            n ^= 0x21 ^ ord(token[4])
            n ^= 0xfe ^ ord(token[5])
            n ^= 0xa3 ^ ord(token[6])
            n ^= 0xf0 ^ ord(token[7])
            n ^= 0x11 ^ ord(token[6])
            n ^= 0x54 ^ ord(token[5])
            n ^= 0xca ^ ord(token[4])
            n ^= 0x3c ^ ord(token[3])
            n ^= 0x20 ^ ord(token[2])
            n ^= 0xd1 ^ ord(token[1])
            n ^= 0xf2 ^ ord(token[0])
            if n == res[-i-1]:
                res[-i-1] = c    
                break
     
hashdecrypt('vWsMajX21l6BdKwDxaRA3utqhpvFL0V=')
[ctf@renorobert Everybody Lies]# python decrypt.py 
�_lied_no_flag_for_you!
The 1st byte can be easily guessed as 'i'. So the flag is: i_lied_no_flag_for_you!

No comments :

Post a Comment