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 (★★☆☆☆).
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:
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))
Y 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()
Y 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
Publicar un comentario