Ir al contenido principal

Criptografía (CCIX): Solución Retos Criptografía OFPPT-CTF

Hace poco me he estado entretenido resolviendo los 
retos de OFPPT-CTF Morocco, competición en modalidad 'on-line', estilo CTF (del inglés, 'Capture the Flag') y formato 'Jeopardy', y en este post pongo la solución a los retos de la categoría 'Cryptography' que resolví.

Los retos incluidos en dicha categoría y que pude resolver (8 de 10) presentaron, a mi juicio, un nivel bajo de dificultad (☆☆☆).


- Rome famous general (Dificultad ☆☆☆):
Dan 3 pistas para resolver este reto, pero el título y el enunciado son más que suficientes para deducir que se trata del cifrado 'Keyed Caesar', una variante del cifrado césar que utiliza una clave en el cifrado y descifrado. Además, tienen la amabilidad de proporcionarnos la clave ('cipherkey'). Por tanto, para descifrar el criptograma únicamente tengo que utilizar una herramienta 'on-line':

Como se ve en la figura anterior la solución a este reto es: OFPPT-CTF{k3y3d_c43s4r_c1ph3r}.

Milkshake (Dificultad ☆☆☆):
Al igual que en el caso anterior no es necesario acudir a ninguna de las 2 pistas que dan para resolver este reto, ya que el enunciado es más que suficiente para deducir que hay que utilizar la herramienta 'cyberchef':
Como se ve en la figura anterior la solución a este reto es: OFPPT-CTF{I_L0v3_C7Fs}.

Transposition (Dificultad ☆☆☆):
Al igual que en los anteriores no es necesario acudir a ninguna pista (dan 2), ya que el título, el enunciado y la imagen son más que suficientes para deducir que se trata del cifrado 'Railfence'. Para descifrar el criptograma utilizo la misma herramienta 'on-line' que en la resolución del primero: 
Como se ve en la figura anterior la solución a este reto es:

OFPPT-CTF{R41l_F3nc3_1s_4_Cl4ss1c_Tr4ns0p0sit1$on_c1ph3r}.

RSA Mod. (Dificultad ☆☆):
Tampoco es necesario acudir a ninguna de las dos pistas que nos proporcionan, ya que por el título, pero sobre todo por la información que nos dan en el fichero 'encrypted.zip' es muy fácil deducir que el ataque a emplear es el de módulo común.

Como se ve en dicha información se ha utilizado el mismo módulo ('n'), aunque con distinto exponente de la clave pública ('e'), para cifrar un mismo texto en claro (la 'flag').

Creo un pequeño script en 'python':

import binascii
import gmpy2

def inv(num1, num2):
    global r0, s0, t0

    r0 = num1
    r1 = num2
    s0 = 1
    t0 = 0
    s1 = 0
    t1 = 1

    while r1 != 0:
           q = r0//r1
           r = r0%r1
           s = s0 - q * s1
           t = t0 - q * t1
           r0 = r1
           r1 = r
           s0 = s1
           s1 = s
           t0 = t1
           t1 = t

    return  r0, s0, t0

n = int('0xa96e6f96f6aedd5f9f6a169229f11b6fab589bf6361c5268f8217b7fad96708cfbee7857573ac606d7569b44b02afcfcfdd93c21838af933366de22a6116a2a3dee1c0015457c4935991d97014804d3d3e0d2be03ad42f675f20f41ea2afbb70c0e2a79b49789131c2f28fe8214b4506db353a9a8093dc7779ec847c2bea690e653d388e2faff459e24738cd3659d9ede795e0d1f8821fd5b49224cb47ae66f9ae3c58fa66db5ea9f73d7b741939048a242e91224f98daf0641e8a8ff19b58fb8c49b1a5abb059f44249dfd611515115a144cc7c2ca29357af46a9dc1800ae9330778ff1b7a8e45321147453cf17ef3a2111ad33bfeba2b62a047fa6a7af0eef',16)
e1 = int('0x10001',16)
e2 = int('0x23',16)
c1 = int('0x310ffa2576c3f1a193f625010cc41c21dac0022710e9c42916b81f60579738d833700faa94572bfc57eeec8b961ce6b1ec03d659ea9da71293d19419be1f2193a797c4eb933ff5a405443b1f4151fc253d4738c19c7cf0ed39e8624511d777b7fc7a866a3812ab4cc19038ca3a18f8e1f9df46dade804b9a3dc679726ef08a67576351aad20a60666623a26de367d41c56d21ed72c3402e66290e43fd87e277154de4ff2b2490bb599574b296c714afe090dba33f8e1e21b01bafab104f527bca35be930136d8df33fe81e7d87bb1b3b3ee45cc2614cfc61873e162d6521b230d7243748b229fda2d1d4e5f5f3def6349176f76876238ed3d8e1d6378a055767',16)
c2 = int('0xd646418a1491d8b7c970e3ede9fb997076a0be6b04e42d0ce0d9eb6658c59306a6794154539309708bc86afca5b8258774f644cb5894e7bd04352baf8a7a19b37157cf6cc47659aa3d8dab1b8056067a3cbaba97b6e3316d10eadabe7d14c0ba41c5b55dc8e8bddc88340e47765d12b6537c65f20aca56afc2e586b9b77f7bb43f3ee07fd4549cc591fd22270a3dbe23a158b0048090a5ce62d425299ae17123dd56b8bbf6fce700c61718ae2e723335936fb57b1a6c560a70a637cf5551bd9b9bdef02c0ee7973cb8522441b61e0d46d773fcf4b24ea2f4549e71ff8b2185e215fa00ba6a9f60312e5eee6c7c2b624cf45b65de56c0e4fc00bff55e1529733',16)

inv(e1, e2)

print ""
if r0 != 1:
    print "No existe inverso"
    m =""
elif s0 < 0:
    s = t0
    t = s0
    inv(c1, n)
    m = ((c2 ** s)%n)*(s0 ** (-t))%n
else:
    s = s0
    t = t0
    inv(c2, n)
    m = ((c1 ** s)%n)*(s0 ** (-t))%n

print binascii.unhexlify(gmpy2.digits(m,16))

Y lo ejecuto:
Como se ve en la figura anterior la solución a este reto es:

OFPPT-CTF{R$4_M0d_4tt4cks_4re_4n0th3r_Cl4ss1c_Vuln3r4b1l17y}.

RSA Small (Dificultad ☆☆):
En este reto no dan ninguna pista para ayudar a resolverlo, pero tampoco hace ninguna falta, ya que por el título y por el enunciado, pero sobre todo por la información que nos dan en el fichero 'rsa_small.zip' es muy fácil deducir que el ataque a emplear es el de exponente público pequeño:

Creo un pequeño script en 'python':

import gmpy2
import binascii

n = 848679985797447869399955772819127213061137842373015804903762494359645720791040778076619433302674004347484565791581642609473387655735195295365279289016435642019259985990645911733119485800890708230053795033609181332000447274578889940499411197562111094428807949016438566888871179849827432797743465183571439731186111884712225698892368979349739206606593045379047207591044512475303068095583610049728424692564119172882065602439029603348602584135304945650000715210121217415159672068653299460404758884228046013042562965080049653891004083434176688089444298777532346069082024899343877834584938045202455200048186554846026727297621240451214798525048971378675972260019196481887830771437670138972634154814409503426355185620129053316128528423087492174694811793403655971666568345076618727967344075031994286240815344178567441153634038071947827327700917234091487142266390015552941979817722214984014258022713900663398969526301690250025575483527895147735655625252139228855555368584244676794350771701435632552963431752523714399310405951557242368697834717565197145134464156785931396734151509020243119926355165138086318689699700337185418254990682421255569532070095700384447469238825430018975257552596722400439696783949509883005145800952113577752688735953731
e = 5
c = 1290693983568973212241774157251029501916031181300587856502104425060400825645233474412159795041070912725774295993070287999705559436744356587070331473154201672194895706660927805733716209570278752107616017153539788802992400477319421895132265308353914269512736230439032250634773967478099458568504291012797867556104874614937296951446237815056114697267646832399584346738180717835541698802244926455470361437886629916832531228754210088056426885624615069977138458285217304667225248399707130072871824121756788726012791836940206537928157363946715031682108412776344952206447795443691414126211540976228231813721934019177491660030885807301520689365508821556490894213716812362105926718336768325044896559692102465835491500325292511210492266786815154645636848969136539759596476855914079053513055397814403086420614976446006354782596760766518849838306525291408721775119110961750623361977018207968

print ''
print 'Modulo (n) ....................', n
print ''
print 'exponente clave publica (e) ...', e
print ''
print 'Criptograma (c) ...............', c

m,exacta = gmpy2.iroot(c,e)

if exacta:
   print ''
   print 'Texto en claro (m) ............', m
   print ''
   print 'Texto en claro (ASCII) ........', binascii.unhexlify(gmpy2.digits(m,16))

lo ejecuto:
Como se ve en la figura anterior la solución a este reto es:

OFPPT-CTF{Sm4ll_3xp0n3nts_1n_RS4_4re_n0t_s3cur3}.

German riddle (Dificultad ☆☆):
Aunque en este reto nos dan 1 pista para ayudar a resolverlo, no hace ninguna falta acudir a ella, ya que por la fotografía se ve claramente que se refiere a la Máquina Enigma, máquina electromecánica de cifrado empleada por el ejército alemán en la Segunda Guerra Mundial, y en el enunciado se dice que se desconoce parte de la clave con la que se cifro el texto en claro, pero como conocemos el principio del mismo ("OFPPT") un poco de fuerza bruta debería ser suficiente para obtener la 'flag'.

En concreto, sé:

- El modelo de la máquina utilizado: el M4, empleado por la armada de la Alemania nazi ('Kriegsmarine').

- El rotor "fino o estrecho" (en inglés, 'Thin Rotor') empleado de entre los dos posibles: el Gamma.

- La posición inicial de los rotores: 5 ('E'), 8 ('H'), 5 ('E'), 2 ('B').

- El ajuste de los anillos de los tres primeros rotores: 3, 2, 12.

- Las conexiones establecidas en el panel: rf, cq, dn, ej, kb, mt, os, wz, px, ah.

Desconozco:

- El reflector empleado:  el "B fino o estrecho" (en inglés, 'B Thin') o el "C fino o estrecho" (en inglés, 'C Thin'). Inicialmente voy a suponer que se utilizó el primero de ellos y si no obtengo nada lo intentaré con el segundo.

- Los rotores "normales" utilizados: el modelo M4 disponía de un total de 8 rotores (identificados con los números romanos I, II, III, IV, V, VI, VII y VIII) y que eran utilizables de tres en tres en las ranuras dispuestas para alojarlos.

- El ajuste del anillo del cuarto rotor: de 1 a 26.

Creo un pequeño script en 'python':

import sys
from enigma.machine import EnigmaMachine
rotor=['I','II','III','IV','V','VI','VII','VIII']
ciphertext='BXKFAPDLWWUWWFUPWIXDAQFYZUA'
for a in rotor:
  for b in rotor:
    for c in rotor:
       for i in range(1, 27):
         machine = EnigmaMachine.from_key_sheet(
           rotors='Gamma '+a+' '+b+' '+c,
           reflector='B-Thin',
           ring_settings="3 2 12 "+str(i),
           plugboard_settings='RF CQ DN EJ KB MT OS WZ PX AH')
         machine.set_display('EHEB')
         plaintext = machine.process_text(ciphertext)
         if("OFPPT" in plaintext):
           print "Modelo: M4"
           print "Reflector: B-Thin"
           print "Rotores: Gamma,",a,b,c
           print "Pos. inicial rotores: 5, 8, 5, 2"
           print "Ajuste de los anillos: 3, 2, 12,",i
           print "Conexiones: rf, cq, dn, ej, kb, mt, os, wz, px, ah"
           print ""
           print "Texto en claro:",plaintext.lower()

lo ejecuto:
Por lo que, como se ve en la figura anterior, la solución a este reto es:

OFPPT-CTF{german_enigma_decoded}.

Aunque la solución me parece un poco extraña, ya que los rotores "normales" utilizados son: I, III, I, y si no estoy equivocado no se podría repetir ninguno (ver lo que he indicado más arriba para este tipo de rotores).

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