Crypto 300: Revolver

By UNAMAmada Team

Descripcion del reto:


Analiza el script task.py el cual tiene la lógica de encripción del archivo flag.enc e implementa la función de desencripción para obtener el plain-text. Considera que el texto de la bandera empieza con flag{




Nos daban dos archivos task.py y flag.enc. Dentro del archivo flag.env tenemos:




.._3veh.s30xe4.rl5el_..wrg_130._.anm_.._rneg_t_safc1e{.e0_.n_mh34.l}ty% 

Y el task.py:


#!/usr/bin/env python
#-*- coding:utf-8 -*-

import random
from secret import flag

def enc(message, p):
 t = len(p)
 while len(message) % (2*t):
  message += "."
 message = message[1:] + message[:1]
 message = message[0::2] + message[1::2]
 message = message[1:] + message[:1]
 res = ""
 for j in xrange(0, len(message), t):
  for k in xrange(t):
   res += message[j:j+t][p[k]]
 message = res
 return message

def dd(message, p, l):
 for _ in xrange(l):
  message = enc(message, p)
 return message

t, l = 7, random.randint(0, 1337)
p = range(t)
random.shuffle(p)
enc = dd(flag, p, l)
f = open('flag.enc', 'w')
f.write(enc)
f.close()

  • En las primeras líneas tenemos: t se fija como 7, l es un número aleatorio del 0 al 1337; p se genera aleatoriamente mediante random.shuffle ()
  • La función dd llama a la función enc l veces
  • Significa que agrega un padding hasta que la longitud del mensaje sea dividida por 14, por lo que solo agregará dos puntos en la bandera cifrada
  • El msg = msg[1:] + msg[:1] mueve el primer carácter al final ‘abc’ à ‘bca’
  • El msg[0::2] + msg[1::2] dividirá el msg y lo juntará, es decir hace una cadena con las letras pares más las letras impares así:  “abcd” à “acbd”
  • Luego msg = msg[1:] + msg[:1] volverá a poner el primer carácter al final
  • El último doble for devolverá el resultado revolviendo msg usando p.
El chiste de este reto es que hay 5040 posibles llaves, así que se usaremos fuerza bruta utilizando itertools.permutations:

import itertools
   
def decrypt(msg, perm):
    l = len(perm)
    flag = ''
    res = msg
    tmp_flag = ''
    for j in xrange(0, len(msg), l):
        for k in xrange(l):
            flag += res[j:j+l][perm[k]]
    flag = flag[-1] + flag[:-1]
    for i in range(0,35):
        tmp_flag += flag[i]+flag[i+35]
    flag = tmp_flag
    flag = flag[-1] + flag[:-1]
    return flag

l = 7
p = range(7)
p = itertools.permutations(p)
for x in p:
    f = open("./flag.enc").read()
    for i in xrange(0,1338):
        f = decrypt(f, x)
        if 'flag{' in f:
            print f
            break



Bandera
flag{n0_h0rr1e5_we__4v3_m0re_challenges_s33_y4_n3xt_t1me}

Comments