Ir al contenido principal

Criptografía (CXLIX): Solución Reto picoCTF 2018 "SpyFi"

Solución a otro reto de criptografía de la plataforma picoCTF 2018.

En esta ocasión se trata de un reto en el que se ve involucrado el método de operación más sencillo, ECB ('Electronic Code-Book'), de los algoritmos de cifrado por bloques, y que,  en mi opinión, presenta un nivel de dificultad alto ().

SpyFi - Points: 300:

Su enunciado dice lo siguiente: '
James Brahm, James Bond's less-franchised cousin, has left his secure communication with HQ running, but we couldn't find a way to steal his agent identification code. Can you? Conect with nc 2018shell.picoctf. com 33893Source'.
Solución: se proporciona un archivo fuente en el que puedo ver el cifrado de un mensaje utilizando el criptosistema AES en modo ECB. El tamaño del bloque es de 16 Bytes.

Tal y como nos cuenta wikipedia, en el tipo de cifradores indicado anteriormente los mensajes en claro se dividen en bloques (en el caso de nuestro reto de 16 Bytes), y en el modo ECB cada uno de ellos es cifrado por separado utilizando la misma clave.
La desventaja de este modo es que a bloques de texto plano o en claro idénticos les corresponden bloques idénticos de texto cifrado.

Dicho lo anterior vuelvo al reto. Me conecto al servidor: se me da la bienvenida y se me solicita que introduzca mi informe de situación, y después de introducir este último se muestra un texto cifrado o criptograma:
Analizo el archivo fuente que se nos proporciona con relación al criptograma obtenido y llego a la conclusión de que el cifrado del mensaje se ha realizado de la siguiente manera:

message = """Agent,
Greetings. My situation report is as follows:
{0}
My agent identifying code is: {1}.
Down with the Soviets,
006
"""

Utilizando “/” para indicar el salto de línea:

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
/My agent identi
5c55697e5d18d2b94fffe188b4f3f279
fying code is: x
c551f6fbef081e96daec728c670444d3
...
Como informe de situación he introducido 59 caracteres "a" con lo que:

- Veo que, efectivamente, a idénticos bloques de texto plano o en claro les corresponden idénticos textos cifrados (líneas resaltadas en color verde).

- He obtenido un texto cifrado correspondiente a un bloque (línea resaltada en color azul) que me permitirá utilizarlo como valor de referencia para realizar un ataque de fuerza bruta con objeto de obtener el primer carácter de texto en claro (el carácter desconocido "x" que figura en el texto en claro de dicha línea) del código de identificación del agente 006, que es lo que pretendo robar y, por tanto, es la solución a este reto.

Es decir, si realizo fuerza bruta sobre el último carácter ("x") de la línea resaltada en azul (voy probando con todos los posibles caracteres: a, b, c,..., z, A, B, C,..., Z, 0, 1, 2,..., 9, !...) llegará un momento en que el criptograma que obtenga para ese bloque será igual a nuestro valor de referencia, ya que, tal y como he dicho, a bloques idénticos les corresponden textos cifrados iguales, y el carácter probado será precisamente el primero del código de identificación de agente que busco.

Indico cómo funcionaría para el primer carácter del código de identificación de agente:

- Introduzco como informe de situación: aaaaaaaaaaafying code is: a

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
fying code is: a
c17da5606c552f2f750a47a9f342a75c
...
- El texto cifrado obtenido para el último bloque que se muestra no coincide con nuestro valor de referencia. Por tanto, "a" no es el primer carácter del texto en claro correspondiente al código de identificación de agente.

- Voy probando con los demás caracteres hasta que llego a "p", es decir, introduzco como informe de situación: aaaaaaaaaaafying code is: p

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
fying code is: p
c551f6fbef081e96daec728c670444d3
...
- El texto cifrado obtenido para el último bloque que se muestra coincide con nuestro valor de referencia. Por tanto, "p" es el primer carácter del texto en claro correspondiente al código de identificación de agente.

Creo un pequeño script en python para obtener este primer carácter (al final de este post pongo el script para 'crackear' completamente el código de identificación de agente). Lo ejecuto y obtengo:
Una vez obtenido el primer carácter del texto en claro, para obtener el segundo sólo tengo que introducir como informe de situación 58 caracteres "a", con objeto de calcular el nuevo valor de referencia incorporando el carácter del texto en claro hallado (primer carácter del código de identificación de agente), y continuar con el mismo procedimiento de fuerza bruta.

Explicado lo anterior, para conseguir la solución de este reto generalizo el script empleado para obtener el primer carácter, de la siguiente manera:

#!/usr/bin/env python3
import socket

charset='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '

encontrado=' '
flag=''
situation_report_ref='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
situation_report_car=' aaaaaaaaaaafying code is: '
n=1

while encontrado!='' and encontrado!='}':
   print('[+] Informe de situacion ...', situation_report_ref)

   s = socket.socket()
   s.connect(('2018shell.picoctf.com', 33893))

   while True:
      recibido=s.recv(448).decode().strip()
      if 'Welcome, Agent 006!' in recibido:
         print(recibido)
      elif 'Please enter your situation report:' in recibido:
         print(recibido)
         s.send((situation_report_ref).encode())
         s.send(b'\n')
      else:
         str_brute_force=recibido[256:288]
         break

   s.close

   if n>11:
      situation_report_car=' aaaaaaaaaaa'+situation_report_car[12:27]
      n=0
   else:
      n+=1

   situation_report=situation_report_car[1:27]

   for i in charset:
      s = socket.socket()
      s.connect(('2018shell.picoctf.com', 33893))

      situation_report_car=situation_report+i
      print(situation_report_car)

      encontrado=''

      while True:
          recibido=s.recv(384).decode().strip()
          if 'Welcome, Agent 006!' in recibido:
             pass
          elif 'Please enter your situation report:' in recibido:
             s.send((situation_report_car).encode())
             s.send(b'\n')
          else:
             if recibido[128:160]==str_brute_force:
                encontrado=i
                print('[+] Encontrado un caracter del codigo de identificacion de agente:', i)
                flag=flag+i
                print('[+] Flag =', flag)
             break

      if encontrado!='':
        situation_report_ref=situation_report_ref[0:59-len(flag)]
        break
      elif i==' ' and encontrado=='':
         print('[-] No se ha encontrado un caracter del codigo de identificacion de agente.')
         break

   s.close()

Lo ejecuto:
Y cuando finaliza obtengo la flag completa:

picoCTF{@g3nt6_1$_th3_c00l3$t_6081670}.

Comentarios

Entradas populares de este blog

Criptografía (I): cifrado Vigenère y criptoanálisis Kasiski

Hace unos días mi amigo Iñaki Regidor ( @Inaki_Regidor ), a quien dedico esta entrada :), compartió en las redes sociales un post titulado "Criptografía: el arte de esconder mensajes"  publicado en uno de los blogs de EiTB . En ese post se explican ciertos métodos clásicos para cifrar mensajes , entre ellos el cifrado de Vigenère , y , al final del mismo, se propone un reto consistente en descifrar un mensaje , lo que me ha animado a escribir este post sobre el método Kasiski  para atacar un cifrado polialfabético ( conociendo la clave descifrar el mensaje es muy fácil, pero lo que contaré en este post es la forma de hacerlo sin saberla ). El mensaje a descifrar es el siguiente: LNUDVMUYRMUDVLLPXAFZUEFAIOVWVMUOVMUEVMUEZCUDVSYWCIVCFGUCUNYCGALLGRCYTIJTRNNPJQOPJEMZITYLIAYYKRYEFDUDCAMAVRMZEAMBLEXPJCCQIEHPJTYXVNMLAEZTIMUOFRUFC Como ya he dicho el método de Vigenère es un sistema de sustitución polialfabético , lo que significa que, al contrario que en un sistema de

Criptografía (XXIII): cifrado de Hill (I)

En este post me propongo explicar de forma comprensible lo que he entendido sobre el cifrado de Hill , propuesto por el matemático Lester S. Hill , en 1929, y que se basa en emplear una matriz como clave  para cifrar un texto en claro y su inversa para descifrar el criptograma correspondiente . Hay tres cosas que me gustan de la criptografía clásica, además de que considero que ésta es muy didáctica a la hora de comprender los sistemas criptográficos modernos: la primera de ellas es que me "obliga" a repasar conceptos de matemáticas aprendidos hace mucho tiempo y, desgraciadamente, olvidados también hace demasiado tiempo, y, por consiguiente, que, como dice  Dani , amigo y coautor de este blog, me "obliga" a hacer "gimnasia mental"; la segunda es que, en la mayoría de las ocasiones, pueden cifrarse y descifrase los mensajes, e incluso realizarse el criptoanálisis de los criptogramas, sin más que un simple lápiz y papel, es decir, para mi es como un pasat

¿Qué significa el emblema de la profesión informática? (I)

Todas o muchas profesiones tienen un emblema que las representa simbólicamente y en el caso de la  informática: " es el establecido en la resolución de 11 de noviembre de 1977  para las titulaciones universitarias superiores de informática, y  está constituido por una figura representando en su parte central  un  núcleo toroidal de ferrita , atravesado por  hilos de lectura,  escritura e inhibición . El núcleo está rodeado por  dos ramas : una  de  laurel , como símbolo de recompensa, y la otra, de  olivo , como  símbolo de sabiduría. La  corona  será la  de la casa real  española,  y bajo el escudo se inscribirá el acrónimo de la organización. ". Veamos los diferentes elementos tomando como ejemplo el emblema del COIIE/EIIEO (Colegio Oficial de Ingenieros en Informática del País Vasco/ Euskadiko Informatikako Ingeniarien Elkargo Ofiziala ) . Pero no sólo el COIIE/EIIEO adopta el emblema establecido en dicha resolución, sino que éste se adopta también como im