Fallos del Hackme – Retos numéricos

Esta vez no se trata de errores de programación, sino de retos matemáticos que ponen a prueba lo que creemos saber sobre algoritmos de cifrado y su vulnerabilidad a ataques de fuerza bruta.

Podrás resolver estos retos a partir de haber obtenido los 400 puntos en el juego. Así que si aún no lo has hecho te invito a resolver algunos retos más hasta alcanzar este reto.

Pero bueno, llegados a este punto, os dejo echarle un ojo.

Y las pistas que nos da el creador de este reto, que no he sido yo…

Here's a ciphertext that was generated by the script:

   bWN/XXVDRVRDUmVJQkNVcU9STn5JVFVnVENIAVJwQ1RfdUNFVENSWw==

Now, to break it, you have to do three things.  First, figure out how
to reverse the encryption, when you know the secret key (the
character).  Second, try decoding with all possible secret keys
(characters).  Third, analyze those results to see which one looks
most like English ASCII text.  Here you need to do use some facts
about what ASCII letters in English look like.

Finally, a note about b64encode (and b64decode).  Base64 is a way to
take arbitrary bytes and represent them only with letters, numbers,
and a few simple punctuation symbols---this avoids printing garbage
characters.  You'll have to undo this process when solving the
challenge.

Happy Hacking!

Aquí se complica un poco la cosa. La salida viene en base64, asi que tendremos que recomponerla revirtiendo la base64.

Lo siguiente que hemos de saber es el operador ^ un XOR binario que lanza sobre cada letra usando la key de longitud 1 que alguien le dio y que nosotros desconocemos.

Como la key es de un solo carácter, eso nos ayuda bastante, bastará con probar con las 28 letras del abecedario, los números y los caracteres especiales hasta que encontremos uno que nos de la respuesta que queremos.

Otra cosa que debemos saber es que una propiedad de la XOR es que

a XOR b = c pero c XOR b = a

from base64 import b64encode, b64decode

key = "¡?=$&%().-_;*/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
msg = "bWN/XXVDRVRDUmVJQkNVcU9STn5JVFVnVENIAVJwQ1RfdUNFVENSWw=="
decodificado=b64decode(msg)

for k in key:
  output = ""
  print k
  for d in decodificado:
    output+=chr(ord(d)^ord(k))
  print output
  if 'KEY' in output:
    break

He cogido todos los caracteres del teclado y los he colocado uno detrás de otro en la cadena key, para así poder recorrerlos y no tener que probar letra a letra desde la consola invocando el script.

Luego he cogido la cadena que quiero descifrar y la he puesto en la variable msg.

decodifico msg para que deje de estar en base64 y aplico la regla de antes de que a XOR b da c pero c XOR b dará a. Luego concateno letra a letra el resultado y saco el resultado en pantalla.

Cómo en los otros retos, la palabra clave KEY debe aparecer en algún momento, así que la uso para dejar de buscar.

Esos son resultados previos a la solución

Volvemos a actuar por tanteo, o por fuerza bruta, pero lo que se trata de demostrar es que el cifrado basado en una operación XOR es reversible y inseguro frente a ataques de este tipo.

Y ahora el siguiente reto que pone a prueba lo que sabemos de RSA y de los números primos en general.

bignumber = 202557564740749725343243267960623572731942487045L

if (arg1 >= arg2 or
    arg1 == 1 or
    arg1 * arg2 != 18243150071292141317265306851):
    print "You've got the wrong arguments..."
    exit(1)

print "Congrats you had the right input."
print int2str(bignumber * arg1)

En el cifrado RSA la cosa va así. Tenemos una clave publica y una privada. Lo que aquí aparece como arg1 y arg2. Sabemos que son pareja porque si las multiplicamos nos dan el resultado esperado. El resultado esperado se obtiene multiplicando dos números primos por tanto solo podemos obtenerlo sabiendo cuáles son arg1 y arg2.

Una vez tengamos arg1 y arg2, descifrar el bignumber será directo.

La seguridad de este tipo de cifrado se basa en lo difícil que es calcular números primos. Tienes que dividir el numero final por todos los números que le quedan por debajo y esperar a que de un resto 0 para encontrar la solución. En este ejemplo es factible, pero con números realmente largos podrías estar años calculando.

Así que busquemos el divisor que nos falta y obtengamos arg1 y arg2 por fuerza bruta.

numero = 18243150071292141317265306851
numero2 = 2

while numero % numero2 != 0:
    numero2 = numero2 + 1
    if numero2%1000 == 0:
        print "vas por " + str(numero2)
        

print "arg1: " + str(numero2)
print "arg2: " + str(numero / numero2)

Empiezo en 2 y voy sumando 1 probando todos los números a ver si son divisores del numero largo. El operador % devuelve el resto de la división entera. Que será 0 cuando encontremos el divisor.

Pon ahora los valores que has obtenido en el script anterior en este otro script

from numbers_helper import *

arg1 = PON AQUI TU VALOR
arg2 = PON AQUI EL OTRO VALOR

bignumber = 202557564740749725343243267960623572731942487045L

if (arg1 >= arg2 or
    arg1 == 1 or
    arg1 * arg2 != 18243150071292141317265306851):
    print "You've got the wrong arguments..."
    exit(1)

print "Congrats you had the right input."
print int2str(bignumber * arg1)

Y habrás obtenido la clave que te faltaba mediante un ataque por fuerza bruta sobre cifrado basado en clave pública y privada.

Como puedes observar, no requerimos de un ordenador cuántico. El mundo ya es bastante inseguro hoy por hoy. Con la potencia de cálculo adecuada los días son horas y las horas minutos. Algunos te dirán que siempre nos quedarán los algoritmos de blockchain para garantizar la integridad de una cadena de transacciones, pero la verdad es que blockchain es susceptible de ataques del 51%, dónde de nuevo todo se basa en poseer más y mejores equipos que el resto.

Hemos construido un mundo que parece sacado de una distopía de ciencia ficción. Hemos dejado todo el poder a empresas privadas con el poder de cálculo suficiente para hacer del mundo su campo de juego.

El único rival de una buena CPU es el cerebro humano, pero un abuso de la tecnología nos está lobotomizando. Por eso me alegra que quede gente con ganas de pensar, de programar, de investigar, …

Aunque sea con mi ayuda, habéis llegado al último reto.

¡Gracias por estar ahí!

Play That Class
Play That Class

Me encanta escribir, la tecnología y la educación. En estos artículos intento unir mis tres pasiones.

Artículos: 21

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *