c1b3rwall / module_3

Files from module_3
13 stars 14 forks source link

Ejercicio 5 #7

Open jfzazo opened 3 years ago

jfzazo commented 3 years ago

Ayer abrí el "issue" con el enunciado equivocado, hoy ya traigo la solución. El problema vino en que estuve dándole vueltas y casi lo consigo pero, como ocurre en muchas ocasiones, se quedó a medias.

Al grano. Una cadena de números, podrían parecer hexadecimal pero no lo son. Si se realiza un análisis en frecuencia se observa que solamente aparecen los caracteres: 0,6,7,8,9. ¿Se podría haber ocultado algo en los bits menos significativos? Claramente tampoco por la longitud del mensaje.

Siguiente paso... observar qué ocurre entre un número y el siguiente. La idea intuitiva es que cada número es una letra, aunque no tendría necesariamente que ser así.

Como intento, podemos tratar de creer que 80 es la m, 89 es la o (ya que nuestras flags siempre empiezan por module3{...}), pero entre la m y la o solamente tenemos la n (dado que seguramente se use un alfabeto internacional). ¿Y si los números no tienen su valor habitual y solamente son representaciones? Quizá después del 0 viene un número cualquiera y el siguiente sea un 9. De ese modo 80 pudiera ser m y 89 o. Genial, puede ser una buena apreciación.

¿Como interviene el primer número entonces? Una noche de reflexión y descubro que es una tabla indexada por dos índices. Nada que yo haya descubierto, tiene nombre y se llama polybius. Ejemplo:

|   \   |   1   |   2   |   3   |   4   |   5   |
|   1   |   A   |   B   |   C   |   D   |   E   |
|   2   |   F   |   G   |   H   |   I   |   J   |
|   3   |   K   |   L   |   M   |   N   |   O   |
|   4   |   P   |   Q   |   R   |   S   |   T   |
|   5   |   U   |   V   |   W   | X   | Y   |

Con la anterior tabla, podremos representar HOLA como 23 35 32 11. Pues dicho y hecho. A sustituir números por otros números. Si el 0 va al 1, el 6 al 2, ..., el 9 al 5, creo que se obtiene QUREYFIXFZSFYYGNF.

Claro, no hemos jugado con las permutaciones. ¿Por qué debería ir el 0 al 1 y así sucesivamente? Para no volverme loco codificando, sustituiré la cadena original por:

DA DE DB AE ED BA BD EC BA EE DC BA ED ED BB CC BA

donde 0 es A, 6 es B, ..., 9 es E.

Y pico el siguiente código:

import itertools
import re

def generate_array(key=''):
    alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'
    array = []
    _tmp = []
    key = re.sub(r'[^a-zA-Z]+', '', key)  # remove non-alpha character
    key = key.upper()

    if key:
        for k in key:
            alphabet = alphabet.replace(k, '')

        alphabet = key + alphabet

    for y in range(5):
        for x in range(5):
            _tmp.append(alphabet[0 + 5 * y + x])
        array.append(_tmp)
        _tmp = []

    return array

def display_array(array):
    row_labels = ['1', '2', '3', '4', '5']
    print('      1   2   3   4   5')
    for row_label, row in zip(row_labels, array):
        print(' %s [%s  ]' % (row_label, ' '.join('%03s' % i for i in row)))

def decode(numbers, array):
    numbers = re.sub(r'[\D]+', '', numbers)
    text=""
    for number in range(0, len(numbers), 2):
        try:
            oy = int(numbers[number]) - 1
            ox = int(numbers[number + 1]) - 1
            text += array[oy][ox]
        except IndexError:
            pass
        continue
    return text

cadena = "DA DE DB AE ED BA BD EC BA EE DC BA ED ED BB CC BA"
array = generate_array()
for p in list(itertools.permutations(['A', 'B','C','D','E'])):
    t=cadena.replace(p[0], '1')
    t=   t.replace(p[1], '2')
    t=   t.replace(p[2], '3')
    t=   t.replace(p[3], '4')
    t=   t.replace(p[4], '5')
    print(decode(t,array))

Como bien sabemos la permutaciones de esos 5 caracteres son 120 (5!) por lo que aunque sea una salida larguita, todavía se podrá observar a mano. Ejecutamos el anterior código y se ve que para la permutación ('B', 'C', 'D', 'E', 'A'), es decir, el 0 va a la quinta posición, el 6 a la primera el nueve a la cuarta y la tabla:

>>> display_array(array)
      1   2   3   4   5
 1 [  A   B   C   D   E  ]
 2 [  F   G   H   I   K  ]
 3 [  L   M   N   O   P  ]
 4 [  Q   R   S   T   U  ]
 5 [  V   W   X   Y   Z  ]

Se tiene la solución al reto.

La tabla volviendo a la represantación original es:

      6   7   8   9   0
 6 [  A   B   C   D   E  ]
 7 [  F   G   H   I   K  ]
 8 [  L   M   N   O   P  ]
 9 [  Q   R   S   T   U  ]
 0 [  V   W   X   Y   Z  ]
artema-xa commented 3 years ago

Muchas gracias por compartir

rotgogo commented 3 years ago

Muchas gracias por la ayuda. Sin ella no lo había descifrado. Busqué info sobre polybius y en esta web: https://www.dcode.fr/polybius-cipher Reyenas el alfabeto y le cambias los números tambíen te muestra la flag. Buena deducción jfzazo!!

Mueltex commented 3 years ago

Gracias por la ayuda!! Había logrado averiguar que se usaba polybius, pero el orden numérico lo tenía alterado

edikuba commented 3 years ago

@jfzazo excelente trabajo, habría tardado un montón de deducir esto, ni sabia que existia el Polybius, y tambien gracias a @rotgogo porque dcode.fr lo hace más sencillo.... Solo tengo solo una pregunta, ¿cómo sabías que había que omitir la "J" en el orden del alfabeto? y no otra letra??

asalazard commented 3 years ago

Muchas gracias por el write-up, no conocía esta codificación...

En el alfabeto gallego no hay "J" y viene del latín, pero no eran gallegos los cibercriminales :-) , en la web de decode indica

"As latin alphabet has 26 letters and the grid has 25 cells, a letter to remove is chosen, usually it's J, V, W or Z which are deleted. The order of the letters in the grid can be modified using a key to generate a deranged alphabet.

The encryption phase is a substitution of each letter by its coordinates (line, column) in the grid."