Shifted
2 minutos de lectura
Se nos proporciona este código fuente en Python:
import string
import random
flag = open("flag.txt").read().strip()
mystery_num = random.randint(100,1000)
new_alphabet = list(string.ascii_lowercase + string.digits + string.punctuation)
enc_flag = ""
def shift(char):
index = new_alphabet.index(char)
new_index = (index + mystery_num) % len(new_alphabet)
return new_alphabet[new_index]
for char in flag:
enc_flag += shift(char)
mystery_num += 10
print(enc_flag)
# 15[=>ts-!]kgjhz%6cn~";=;.1b3:>}sq7n'\^]42t
Lo que hace el script es crear un alfabeto y un número aleatorio (mystery_num
). Luego, para cifrar la flag, encuentra el índice del carácter en texto claro correspondiente, le suma el número aleatorio (módulo la longitud del alfabeto) y devuelve el carácter en ese nuevo índice.
Como sabemos el formato de las flags (ictf{...}
), podemos encontrar el valor del número aleatorio módulo la longitud del alfabeto:
$ python3 -q
>>> import string
>>> new_alphabet = list(string.ascii_lowercase + string.digits + string.punctuation)
>>> enc_flag = '''15[=>ts-!]kgjhz%6cn~";=;.1b3:>}sq7n'\^]42t'''
>>> index = new_alphabet.index('i')
>>> new_index = new_alphabet.index(enc_flag[0])
>>> mystery_num = (new_index - index) % len(new_alphabet)
>>> mystery_num
19
Nótese que no nos importa que mystery_num
no sea el valor aleatorio real (que está entre 100 y 1000), ya que se aplica módulo la longitud del alfabeto.
Ahora podemos definir la función inversa de shift
(unshift
) y obtener la flag:
>>> def unshift(char):
... new_index = new_alphabet.index(char)
... index = (new_index - mystery_num) % len(new_alphabet)
... return new_alphabet[index]
...
>>> flag = ''
>>> for char in enc_flag:
... flag += unshift(char)
... mystery_num += 10
...
>>> flag
'ictf{sh1ft1ng_ch@rs_w1th_4_myst3ry_numb3r}'