user@Robert_Solca:~/CTFs$

Solved challenges

Farm

Description

Explore the Farm very carefully!

Solution

We get the following two files:
farm.sage
#!/usr/bin/env sage

from sage.all import *
import string, base64, math
from flag import flag

ALPHABET = string.printable[:62] + '\\='

F = list(GF(64))

def keygen(l):
        key = [F[randint(1, 63)] for _ in range(l)] 
        key = math.prod(key) # Optimization the key length :D
        return key

def maptofarm(c):
        assert c in ALPHABET
        return F[ALPHABET.index(c)]

def encrypt(msg, key):
        m64 = base64.b64encode(msg)
        enc, pkey = '', key**5 + key**3 + key**2 + 1
        for m in m64:
                enc += ALPHABET[F.index(pkey * maptofarm(chr(m)))]
        return enc

# KEEP IT SECRET 
key = keygen(14) # I think 64**14 > 2**64 is not brute-forcible :P

enc = encrypt(flag, key)
print(f'enc = {enc}')
        


enc.txt
enc = 805c9GMYuD5RefTmabUNfS9N9YrkwbAbdZE0df91uCEytcoy9FDSbZ8Ay8jj
        


I've never used sage before, but I've managed to find the documentation.
keygen(l) generates a random key and returns it. maptofarm(c) verifies if the given char is in alphabet, and if it is it returns the element from list F that is at the same index as is c in the alphabet. encrypt(msg, key) first encodes the message using base64. After it uses the provided key to generate another key that is used to encrypt the base 64 encoded message. In the end it returns the encrypted message.
To solve this problem I've used the following script:
#!/usr/bin/env sage

from sage.all import *
import string, base64, math

flag = b'ASIS'
ALPHABET = string.printable[:62] + '\\='

F = list(GF(64))

def prod(list):
        prod = 1
        for item in list:
        prod *= item
        return prod

def keygen(l):
        key = [F[randint(1, 63)] for _ in range(l)] 
        key = prod(key) # Optimization the key length :D
        return key

def maptofarm(c):
        assert c in ALPHABET
        return F[ALPHABET.index(c)]

def encrypt(msg, key):
        m64 = b'Q'
        enc, pkey = '', key**5 + key**3 + key**2 + 1
        for m in m64:
                enc += ALPHABET[F.index(pkey * maptofarm(chr(m)))]
                pkey = F[8]/maptofarm(chr(m))
                print(pkey)
        
        return pkey

# KEEP IT SECRET 
key = keygen(14) # I think 64**14 > 2**64 is not brute-forcible :P
pkey = encrypt(flag, key)

def solve(enc, pkey):
        m64 = ''
        for char in enc:
        ind = ALPHABET.index(char)
        m2f = F[ind]/pkey
        m64 += ALPHABET[F.index(m2f)]
        print('64: ',m64)
enc = '805c9GMYuD5RefTmabUNfS9N9YrkwbAbdZE0df91uCEytcoy9FDSbZ8Ay8jj'

solve(enc, pkey)
        


Long story short: it does the reverse operations. I've modified the encrypt to return the pkey by doing the reverse operations. The solve(enc, pkey) takes as arguments the encrypted message and the pkey found previously. It takes every char from the encrypted message and does the reverse operations of the encrypt message. After I've used this site to decode the flag.

Share this:

facebook twitter google pinterest linkedin email